Laden...

WebBrowserDocumentCompleted geht einfach nicht (immer)

Erstellt von Homeros vor 8 Jahren Letzter Beitrag vor 8 Jahren 2.816 Views
H
Homeros Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren
WebBrowserDocumentCompleted geht einfach nicht (immer)

Hallo Leute,
ich hoffe ihr könnt mir weiterhelfen.

Ich möchte eine Seite (Suchmaschine) ansteuern, etwas suchen und das Ergebnis auswerten... dann folgt der nächste Suchbegriff.

Nun habe ich ein Problem, das ganze funktioniert nur manchmal.
Habe schon viel mit Application.DoEvents() & Thread.Sleep(; rumprobiert, aber so richtig will das ganze nicht.

Grundidee:
Aus einer Form wird eine Form mit webBrowser aufgerufen und den Suchbegriff übergeben usw:


 public Form2()
        {
            InitializeComponent();
 webBrowser1.Navigate(url);
webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
        Form1.TEXTBOX2text = webBrowser1.DocumentText;

//Damit ich das Fenster auch wieder alleine zu bekomme:
        System.Windows.Forms.Timer t1 = new System.Windows.Forms.Timer(); 
        t1.Interval = 6000;
        t1.Tick += new EventHandler(t1_Tick);
        t1.Start(); // Timer starten
}
//Hier springt er ganz oft gar nicht hin. :(
     private void webBrowser1_DocumentCompleted(object sender,
            WebBrowserDocumentCompletedEventArgs e)
        {
            webBrowser1.Document.GetElementById("suche").SetAttribute("value", Form1.text);
            webBrowser1.Document.GetElementById("suchestart").InvokeMember("Click"); 
        }
public void t1_Tick(object sender, EventArgs e)
        {
Close();
        }

Kann mir da jemand weiterhelfen?
Ich will eigentlich einfach, dass die Seite 5Sek zum laden Zeit hat, dann alles aufgefüllt wird, abgeschickt. Wieder kurz gewartet und dann der Quelltext gespeichert.
Eigentlich ja ganz simpel, aber ich komme nicht drauf.

Vielen Dank!
VG

3.170 Beiträge seit 2006
vor 8 Jahren

Hallo,

setz den Handler _bevor _Du Navigate(...) aufrufst.
Es gibt allerdings auch Suchmaschinen, die Dich aussperren wenn sie bemerken dass Du automatisiert suchst.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

H
Homeros Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

Also wenn ich das so setze:

[...] 
webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(DocumentCompleted);
            webBrowser1.Navigate(url);
[...]

Geht es leider garnicht mehr 😕

So geht es ca. jedes dritte mal:

    webBrowser1.Navigate(url);
            System.Threading.Thread.Sleep(2500);
            webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(DocumentCompleted);
             System.Threading.Thread.Sleep(2500);

Ich verwende meine eigene Seite zum testen dafür, also ich werde auf keinen Fall ausgesperrt. 😃

VG

3.170 Beiträge seit 2006
vor 8 Jahren

Hallo,

So wie Du es gemacht hast, ergibt das auch alles nicht wirklich Sinn.

Du navigierst zuerst zu der Seite.
Dann setzt Du den Handler -> wenn die Seite zu diesem Zeitpunkt schon geladen ist, wird de rHandler nicht mehr ausgeführt, er sollte auf jeden Fall vorher registriert werden.

Anschließend erwartest Du, dass in webBrowser1.DocumentText das Ergebnis steht... die Suchergebnisse sind dann da aber ganz bestimmt noch nicht drin.
Des weiteren wird vermutlich das InvokeMember("Click") dafür sorgen, dass wieder navigiert wird -> dann landest Du erneut in dem Handler, weil er immer noch registriert ist.

Auf die Art wird das ganze eigentlich eher zum Glücksspiel.

Ich würde Dir empfehlen:

  • Handler registrieren
  • zur Seite navigieren
  • den Handler sich selbst deregistrieren lassen
  • den Handler einen anderen (noch zu schreibenden) DocumentCompleted-Handler registrieren lassen, in dem Du das Suchergebnis einsammeln kannst
  • dann (immer noch im ersten Handler) das InvokeMember("Click") aufrufen.

Den Timer brauchst Du dann eigentlich gar nicht mehr. Das Close kannst Du auch in dem zweiten Handler aufrufen wenn das Ergebnis da ist.

Wenn die Suche keine neue Seite lädt, sondern über Javascript die Ergebnisse nachlädt, funktioniert das alles allerdings so gar nicht, dann brauchst Du einen komplett anderen Ansatz.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

H
Homeros Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

Erstmal vielen Dank! 😃

Ich habe das jetzt wie folgt geschrieben:


   public Form2(string text)
        {
            InitializeComponent();
            webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted); //1)Handler registrieren
            webBrowser1.Navigate(url); //2) zur Seite navigieren
}
       private void DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            webBrowser1.DocumentCompleted -= new WebBrowserDocumentCompletedEventHandler(DocumentCompleted); //3)den Handler sich selbst deregistrieren lassen
            webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted2);//4)den Handler einen anderen registrieren lassen
            webBrowser1.Document.GetElementById("suche").SetAttribute("value", Form1.text);
            webBrowser1.Document.GetElementById("suchestart").InvokeMember("Click");   //5)Formular abschicken
        }
        private void DocumentCompleted2(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            Form1.TEXTBOX2text = webBrowser1.DocumentText; //6)Weitergabe des Quelltextes
            Close();
        }

Leider geht das nicht. 😕
Ist das so wie du dir das vorgestellt hast?

Ergebnisse werden nicht nachgeladen und mir reicht auch die erste Seite.

Und ja genau so ist es bisher, ein Glücksspiel, machmal geht es manchmal nicht, dass kenne ich sonst nicht vom Programmieren. 😒

3.170 Beiträge seit 2006
vor 8 Jahren

Hallo,

genau so hatte ich es gemeint. Ich habe Deinen Code nur ein ganz klein wenig angepasst (nur ein Form, URL hart codiert), und läuft bei mir problemlos:

   public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted); //1)Handler registrieren
            webBrowser1.Navigate("http://localhost:53646/"); //2) zur Seite navigieren

        }
        private void DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            webBrowser1.DocumentCompleted -= new WebBrowserDocumentCompletedEventHandler(DocumentCompleted); //3)den Handler sich selbst deregistrieren lassen
            webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted2);//4)den Handler einen anderen registrieren lassen
            webBrowser1.Document.GetElementById("suche").SetAttribute("value", "myValue");
            webBrowser1.Document.GetElementById("suchestart").InvokeMember("Click");   //5)Formular abschicken
        }
        private void DocumentCompleted2(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            var my = webBrowser1.DocumentText;
            Close(); // <-- hier ein Haltepunkt, dann enthält "my" das Gewünschte
        }

    }

Unter der URL kommt bei mir folgende einfache HTML-Seite zurück:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form method="get">
        <input type="text" value="" id="suche" />
        <input type="submit" id="suchestart" />
    </form>
</body>
</html>

Wie gesagt, das funktioniert! Vom Prinzip her ist das also alles korrekt.

Bei Dir stimmt irgendwas anderes nicht, wo kommen denn Form1 und url her?

Die Instanz von Form1 aus der Du Dein Form2 erzeugst kann an der Stelle ja eigentlich gar nicht bekannt sein...
Ggf. könntest Du auch mal das HTML Deiner Seite posten.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

148 Beiträge seit 2013
vor 8 Jahren

Könnte mich jetzt täuschen, da es etwas her ist, aber das Problem mit dem DocumentCompleted Event ist, dass es nicht nur einmal ausgeführt wird wenn die Seite wirklich geladen ist. Soweit ich weiß, wird es für jede Ressource, die geladen wird, ausgeführt. Z.B. auch für jeden IFrame auf der Seite. Kannst du ja mal testen.

Grüße

P.S.: Das es bei MarsStein funktioniert würde dazu passen, da dort keine weiteren Ressourcen geladen werden.

H
Homeros Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

Ich denke Geaz hat recht. 😦 Das DocumentCompletedEvent wird öfters aufgeführt...wegen inframe usw.

Ist es nicht möglich, die Seite zu laden und wenn sie komplett da ist (wie gesagt nach 5sek warten oder so), sie auszulesen und meine Befehle abzusetzen... dann nochmal warten und den Quelltext von der neuen Seite auszulesen?

Kennt ihr vllt noch einen anderen Ansatz, den ich mir ansehen kann?

5.657 Beiträge seit 2006
vor 8 Jahren

Hi Homeros,

wenn du nur den Inhalt eines Frames auslesen willst, dann brauchst du auch nur die URL des Frame-Inhaltes zu laden.

Aber wenn es sich dabei um die Ausgabe einer Suchmaschine handelt, sollte man lieber die entsprechende API verwenden anstatt die HTML-Ausgabe zu parsen.

Von der Verwendung von Application.DoEvents oder Thread.Sleep würde ich dringend abraten. Das ist einfach nur ein Zeichen für schlechtes Design.

Ganz allgemein würde ich dazu raten, dir erstmal die Datenquelle genau anzuschauen, dann deine Anforderungen zu definieren und dann (systematisch) zu implementieren und zu testen.

Christian

Weeks of programming can save you hours of planning

H
Homeros Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

Vielen Dank für eure Hilfe!

Ich habe noch etwas darüber gegrübelt.
Also das was mir noch einfällt, ich habe ich immer die gleiche Seite, kann ich mir nicht 1x den Quelltext runterladen (und fest im Programm abspeichern), diesen "ausfüllen" und dann das an die Seite senden?
So müsste ich nur gucken was zurück kommt.
Geht sowas? Und wenn ja, womit mache ich das?

@MrSparkle: Die Seite hat Frames, aber ist selbst kein Frame. Sprich ich muss die URL aufrufen. 😕
Ne, eine Suchmaschine war nur ein bsp.,ich dachte das funktioniert überall gleich. >.<