调用Javascript返回web抓取的数据

本文关键字:数据 抓取 web Javascript 返回 调用 | 更新日期: 2023-09-27 17:58:51

我正试图编写一个网络抓取应用程序,但一个网站在加载页面后运行一些JavaScript来生成我需要的数据时遇到了问题。

页面加载完成后会运行以下javascript:

$(document).ready( function() { 
$("#periodSelect, #typeSelect").change(spotSystemPrice.load);
spotSystemPrice.load();

完成后,它会用数据填充div(id="spotSystemPriceOutput")。

我尝试只使用WebBrowser类来执行此操作,但InvokeScript只允许调用函数,而不允许调用方法。到目前为止,我找到的最接近的解决方案是使用调用该方法的MSHTML.dll插入一些javascript。这似乎是可行的,但我需要一些帮助将div输出加载到字符串中,或者我甚至可以使用全文html。我对C#还很陌生,所以我完全不了解这一点,我认为我需要的最后一步会很容易,所以我只需要你们中的一位专家来帮助我:)

这是我正在使用的代码。任何能帮助我完成它的建议,甚至是一个完全不同的解决方案,都将不胜感激。

WebBrowser wb = new WebBrowser();
wb.Navigate(URL);
while (wb.ReadyState != WebBrowserReadyState.Complete)
            Application.DoEvents();
var doc = (IHTMLDocument2)wb.Document.DomDocument;
var headItems = (IHTMLElementCollection)doc.all.tags("head");
var scriptObject = (IHTMLScriptElement)doc.createElement("script");
scriptObject.type = @"text/javascript";
scriptObject.text = "spotSystemPrice.load();";
var node = (IHTMLDOMNode)headItems.item(null, 0);
node.appendChild((IHTMLDOMNode)scriptObject);

有趣的是,如果我将javascript注入更改为"spotSystemPrice.load();alert('');"在消息框上单击"确定"后,我可以使用文本可视化器在对象资源管理器中看到结果,该可视化器为我提供了((((mshtml.HTMLHeadElementClass)(node)).dococument).body).ninnerHTML的表达式引用。向javascript中添加警报将如何更改我的结果?我需要等待某种onComplete事件吗?

更新:我还发现这看起来很有用。使用WebBrowser.Document.InvokeScript调用javascript对象方法,我将代码修改为:

WebBrowser wb = new WebBrowser();
wb.Navigate(URL);
while (wb.ReadyState != WebBrowserReadyState.Complete)
            Application.DoEvents();
string JScript = "spotSystemPrice.load();";
object[] args = { JScript };
wb.Document.InvokeScript("eval", args);
while (wb.ReadyState != WebBrowserReadyState.Complete)
            Application.DoEvents();

但是div元素中仍然没有数据。但出于某种原因,如果我让javascript"alert('');",甚至不尝试调用该方法,我需要的数据就在那里!发生了什么事?我很困惑。

调用Javascript返回web抓取的数据

如果脚本中已经存在函数spotSystemPrice.load,则可以尝试InvokeScript:

wb.Document.InvokeScript("spotSystemPrice.load");

注意,我没有在函数末尾使用()。在这之后,随着更多的数据将被加载,你需要等待,直到它再次全部加载,所以重用你的代码:

while (wb.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();

你也可以等到wb。Document.Body不为null和/或您的div包含数据。

while (wb.Document.Body == null) Application.DoEvents();
while (wb.Document.GetElementById("spotSystemPriceOutput").InnerHtml.length == 0) Application.DoEvents();

但在这一点上,我会实施某种暂停,以防出现故障,这样它就不会永远停留在那里,但值得一试。