htmlagilitypack e problema di contenuto dinamico

c# dynamic-content html-agility-pack

Domanda

Ciao a tutti.

Voglio creare un'applicazione web scrapper e voglio farlo con il controllo webbrowser, htmlagilitypack e xpath.

in questo momento sono riuscito a creare il generatore di xpath (ho usato il browser web per questo scopo), che funziona bene, ma a volte non riesco ad afferrare il contenuto generato dinamicamente (tramite javascript o ajax). Inoltre ho scoperto che quando il controllo del webbrowser (in realtà il browser IE) genera alcuni tag extra come "tbody", mentre di nuovo htmlagilitypack `htmlWeb.Load (webBrowser.DocumentStream);` non lo vede.

un'altra nota. ho scoperto che il codice seguente in realtà afferra l'origine della pagina web corrente, ma non potrei fornire con esso il pacchetto htmlagility `(mshtml.IHTMLDocument3) webBrowser.Document.DomDocument;`

Puoi aiutarmi per favore? Grazie

Risposta popolare

Ho passato ore a cercare HtmlAgilityPack per il rendering di alcuni contenuti dinamici ajax da una pagina Web e stavo passando da un post inutile a un altro finché non ho trovato questo.

La risposta è nascosta in un commento sotto il post iniziale e ho pensato che dovrei raddrizzarlo.

Questo è il metodo che ho usato inizialmente e non ha funzionato:

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 non eseguirà il rendering o eseguirà le query ajax che eseguono il rendering del contenuto mancante.

Questa è la soluzione che ha funzionato:

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++;
    }
}

L'idea è di caricare usando il WebBrowser che è in grado di eseguire il rendering del contenuto di ajax e quindi attendere che la pagina sia completamente renderizzata prima di utilizzare la libreria Microsoft.mshtml per ri-analizzare l'HTML nel pacchetto agility.

Questo era l'unico modo per accedere ai dati dinamici.

Spero che aiuti qualcuno



Related

Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow