15

我想创建一个 web __scraper__ 应用程序,我想用 webbrowser 控件、htmlagilitypack 和 xpath 来完成它。

现在我设法创建了 xpath 生成器(为此我使用了 webbrowser),它工作正常,但有时我无法动态(通过 javascript 或 ajax)获取生成的内容。我还发现,当 webbrowser 控件(实际上是 IE 浏览器)生成一些额外的标签(如“tbody”)时,htmlagilitypack `htmlWeb.Load(webBrowser.DocumentStream);` 又没有看到它。

另一个注意事项。我发现以下代码实际上获取了当前网页源,但我无法提供 htmlagilitypack `(mshtml.IHTMLDocument3)webBrowser.Document.DomDocument;`

你能帮我吗?

4

3 回答 3

30

我只是花了几个小时试图让 HtmlAgilityPack 从网页呈现一些 ajax 动态内容,我从一个无用的帖子转到另一个帖子,直到找到这个。

答案隐藏在最初帖子下的评论中,我想我应该把它理顺。

这是我最初使用但不起作用的方法:

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 不会呈现或执行呈现缺失内容的 ajax 查询。

这是有效的解决方案:

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

这个想法是使用能够呈现 ajax 内容的 WebBrowser 加载,然后等到页面完全呈现,然后再使用 Microsoft.mshtml 库将 HTML 重新解析到敏捷包中。

这是我可以访问动态数据的唯一方法。

希望它可以帮助某人

于 2014-02-22T14:58:58.147 回答
2

Selenium能解决问题吗?据我所知,它创建了浏览器引擎的实例......有点并且应该允许执行 js 并允许您获得操作 DOM 的结果。

于 2015-08-06T17:39:27.467 回答
-7

使用 HTML Agility 打包文件的以下方法。

htmlAgilityPackDocument.LoadHtml(this.browser.DocumentText);

或者

if (this.browser.Document.GetElementsByTagName("html")[0] != null)
    _htmlAgilityPackDocument.LoadHtml(this.browser.Document.GetElementsByTagName("html")[0].OuterHtml);
于 2013-03-12T08:48:33.970 回答