htmlagilitypack und dynamisches Inhaltsproblem

c# dynamic-content html-agility-pack

Frage

Hallo allerseits.

Ich möchte eine Web-Scrapper-Anwendung erstellen, und ich möchte es mit Webbrowser-Steuerelement, HTMLAGILITYPACK und XPath tun.

Im Moment habe ich es geschafft, einen xpath Generator zu erstellen (ich habe dafür einen Webbrowser benutzt), was gut funktioniert, aber manchmal kann ich nicht dynamisch (via Javascript oder Ajax) generierten Inhalt aufnehmen. Auch habe ich herausgefunden, dass, wenn Webbrowser-Steuerelement (eigentlich IE-Browser) generiert einige zusätzliche Tags wie "tbody", während wieder htmlagilitypack `htmlWeb.Load (webBrowser.DocumentStream);` sieht es nicht.

eine andere Anmerkung. Ich habe herausgefunden, dass der folgende Code tatsächlich die aktuelle Webseitenquelle erfasst, aber ich konnte damit nicht das htmlagilitypack `(mshtml.IHTMLDocument3) webBrowser.Document.DomDocument;`

Kannst du mir bitte dabei helfen? Vielen Dank

Beliebte Antwort

Ich habe gerade Stunden damit verbracht, HtmlAgilityPack dazu zu bringen, einige dynamische Ajax-Inhalte von einer Webseite zu rendern, und ich ging von einem unbrauchbaren Beitrag zu einem anderen, bis ich diesen fand.

Die Antwort ist in einem Kommentar unter dem ursprünglichen Post versteckt und ich dachte, ich sollte es auf den Punkt bringen.

Dies ist die Methode, die ich anfangs verwendet habe und nicht funktioniert hat:

private void LoadTraditionalWay(String url)
{
    WebRequest myWebRequest = WebRequest.Create(url);
    WebResponse myWebResponse = myWebRequest.GetResponse();
    Stream ReceiveStream = myWebResponse.GetResponseStream();
    Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
    TextReader reader = new StreamReader(ReceiveStream, encode);
    HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
    doc.Load(reader);
    reader.Close();
}

WebRequest wird nicht die Ajax-Abfragen rendern oder ausführen, die den fehlenden Inhalt rendern.

Dies ist die Lösung, die funktioniert hat:

private void LoadHtmlWithBrowser(String url)
{
    webBrowser1.ScriptErrorsSuppressed = true;
    webBrowser1.Navigate(url);

    waitTillLoad(this.webBrowser1);

    HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
    var documentAsIHtmlDocument3 = (mshtml.IHTMLDocument3)webBrowser1.Document.DomDocument; 
    StringReader sr = new StringReader(documentAsIHtmlDocument3.documentElement.outerHTML); 
    doc.Load(sr);
}

private void waitTillLoad(WebBrowser webBrControl)
{
    WebBrowserReadyState loadStatus;
    int waittime = 100000;
    int counter = 0;
    while (true)
    {
        loadStatus = webBrControl.ReadyState;
        Application.DoEvents();
        if ((counter > waittime) || (loadStatus == WebBrowserReadyState.Uninitialized) || (loadStatus == WebBrowserReadyState.Loading) || (loadStatus == WebBrowserReadyState.Interactive))
        {
            break;
        }
        counter++;
    }

    counter = 0;
    while (true)
    {
        loadStatus = webBrControl.ReadyState;
        Application.DoEvents();
        if (loadStatus == WebBrowserReadyState.Complete && webBrControl.IsBusy != true)
        {
            break;
        }
        counter++;
    }
}

Die Idee ist, mit dem WebBrowser zu laden, der den Ajax-Inhalt rendern kann, und dann zu warten, bis die Seite vollständig gerendert ist, bevor dann die Microsoft.mshtml-Bibliothek verwendet wird, um den HTML-Code in das Agility-Pack zu zerlegen.

Nur so konnte ich auf die dynamischen Daten zugreifen.

Hoffe es hilft jemandem



Related

Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow