2011-03-28 64 views
2

我正在开发一个用于网页抓取的Windows应用程序。为此,我使用Webbrowser控件 - 我无法使用webrequest/webclient/webresponse类,因为网页是使用JavaScript动态加载的。
该应用程序工作正常,但由于我做了很多处理,它会不必要地加载用户界面。我间歇性地收到“无响应”的信息。因此,我所做的是:

1.在UI线程创建的WebBrowser
2.将长期运行的进程在后台线程
3.每当我需要的页面”的文件我用一个控制.Invoke。
4.通过invoke调用将页面的文档返回到后台线程

在回调函数中,我可以看到页面的文档被提取得很好。但是,返回给后台工作者的文档(HtmlDocument)未正确评估。当我通过调试器时,出现“功能评估超时消息...”。我已经玩弄了语法,并继续收到无效的转换异常或跨线程消息异常。
下面是我是如何编码的回调/委托:
与Control.invoke一起使用Webbrowser

private delegate HtmlDocument RefreshDelegate(); 
private HtmlDocument RefreshBrowser() 
    { 
     WebBrowser br1 = ((WebBrowser)this.Controls["br1"]); //get webbrowser, "br1" 
     br1.Refresh(); //refresh browser 
     return br1.Document; //is retrieved correctly 
    } 


现在在后台工作是处理 “返回” 的代码HTMLDocument的:

WebBrowser br1 = ((WebBrowser)this.Controls["br1"]); //get the browser 
HtmlDocument document = (HtmlDocument)br1.Invoke(new RefreshDelegate(this.RefreshBrowser)); //not evaluated 
//do stuff with document 


遇到的调试器消息:“功能评估被禁用,因为上一个函数e估价超时。你必须继续执行以重新启用功能评估“。这是否是解决此问题的正确方法?正如我所说我无法使用webrequest等获取javascript内容,我也无法在UI上运行htmldocument解析,因为它会导致糟糕的用户体验,另外,我碰巧需要创建几个网页浏览器实例,如果这不是最好的方法,我也可以开放给其他的图书馆,谢谢。

回答

1

我建议使用该HtmlAgilityPack,这是专门为网络“杀局”设计的。

http://htmlagilitypack.codeplex.com/

+0

它也运行JavaScript吗? – 2011-03-28 21:03:45

+0

不,它不运行JavaScript。但是你可以使用http://jint.codeplex.com/来运行javascript。 – 2011-03-28 21:12:07

+0

在使用网页浏览器之前,我实际上使用了htmlagility包。我特别喜欢你如何使用xpath来提取元素。我有我的形式存储在.js文件中的脚本(我相信jQuery)。所以javascript调用是“隐形”的。 jint.codeplex可以在这种情况下工作吗? – iab 2011-03-29 14:17:16

2

这是因为你在调用web浏览器的方法工作者线程或调试器线程实际上并不在该线程上运行。 WebBrowser是一个公寓线程化的COM组件,COM自动将来自工作者的调用封装回UI线程。这在调试器中效果不佳,因为UI线程被调试器冻结。

没有办法做到这一点,实际上让这些调用在UI线程上运行仍然会导致UI冻结。唯一的解决办法是在浏览器的STA线程上完全关闭浏览器。你不能看它,不应该成为我想象的问题。检查this answer您需要的代码。

+0

它的工作!你为我节省了几个小时的无目标调试。我认为重要的部分是将公寓状态设置为STA。非常感谢 :) – iab 2011-03-29 14:14:07