C# 在类库中使用WebBrowser进行Web抓取
我需要在类库中创建一个方法来获取URL的内容(可以由JavaScript动态填充) 我不知道,但整天都在谷歌上搜索,这就是我想到的:(大部分代码来自)C# 在类库中使用WebBrowser进行Web抓取,c#,.net,web-scraping,C#,.net,Web Scraping,我需要在类库中创建一个方法来获取URL的内容(可以由JavaScript动态填充) 我不知道,但整天都在谷歌上搜索,这就是我想到的:(大部分代码来自) 使用系统; 使用System.Threading.Tasks; 使用系统线程; 使用System.Windows.Forms; 公共静态类WebScraper { [状态线程] 公共异步静态任务LoadDynamicPage(字符串url、CancellationToken令牌) { 使用(WebBrowser WebBrowser=new We
使用系统;
使用System.Threading.Tasks;
使用系统线程;
使用System.Windows.Forms;
公共静态类WebScraper
{
[状态线程]
公共异步静态任务LoadDynamicPage(字符串url、CancellationToken令牌)
{
使用(WebBrowser WebBrowser=new WebBrowser())
{
//导航并等待文档完成
var tcs=new TaskCompletionSource();
WebBrowserDocumentCompletedEventHandler onDocumentComplete=(s,arg)=>tcs.TrySetResult(true);
使用(token.Register(()=>tcs.trysetconceled(),useSynchronizationContext:true))
{
webBrowser.DocumentCompleted+=onDocumentComplete;
尝试
{
webBrowser.Navigate(url);
wait tcs.Task;//等待文档完成
}
最后
{
webBrowser.DocumentCompleted-=onDocumentComplete;
}
}
//获取根元素
var documentElement=webBrowser.Document.GetElementsByTagName(“html”)[0];
//异步轮询当前HTML的更改
var html=documentElement.OuterHtml;
while(true)
{
//异步等待,如果请求取消,则将抛出
等待任务。延迟(500,令牌);
//如果WebBrowser仍然忙,请继续轮询
如果(webBrowser.IsBusy)
继续;
var htmlNow=documentElement.OuterHtml;
如果(html==htmlNow)
break;//未检测到任何更改,结束轮询循环
html=htmlNow;
}
//考虑页面完全呈现
token.ThrowIfCancellationRequested();
返回html;
}
}
}
它当前抛出此错误
ActiveX控件“8856f961-340a-11d0-a96b-00c04fd705a2”不能为空
实例化,因为当前线程不在单线程中
公寓
我接近了吗?上述问题有解决办法吗
或者,如果我偏离了正轨,是否有现成的解决方案可以使用.NET(可以从类库调用)获取动态web内容?以下是我在web应用程序中测试的内容,并且工作正常 它在另一个线程中使用
WebBrowser
控件,并返回任务
,其中包含浏览器内容完全加载时完成的任务:
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
public class BrowserBasedWebScraper
{
public static Task<string> LoadUrl(string url)
{
var tcs = new TaskCompletionSource<string>();
Thread thread = new Thread(() => {
try {
Func<string> f = () => {
using (WebBrowser browser = new WebBrowser())
{
browser.ScriptErrorsSuppressed = true;
browser.Navigate(url);
while (browser.ReadyState != WebBrowserReadyState.Complete)
{
System.Windows.Forms.Application.DoEvents();
}
return browser.DocumentText;
}
};
tcs.SetResult(f());
}
catch (Exception e) {
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
return tcs.Task;
}
}
使用系统;
使用System.Threading.Tasks;
使用系统线程;
使用System.Windows.Forms;
公共类BrowseBasedWebScraper
{
公共静态任务加载url(字符串url)
{
var tcs=new TaskCompletionSource();
线程线程=新线程(()=>{
试一试{
Func f=()=>{
使用(WebBrowser浏览器=新WebBrowser())
{
browser.ScriptErrorsSuppressed=true;
浏览器.导航(url);
while(browser.ReadyState!=WebBrowserReadyState.Complete)
{
System.Windows.Forms.Application.DoEvents();
}
返回browser.DocumentText;
}
};
SetResult(f());
}
捕获(例外e){
tcs.SetException(e);
}
});
SetApartmentState(ApartmentState.STA);
thread.IsBackground=true;
thread.Start();
返回tcs.Task;
}
}
谢谢!这对我不起作用,但可能足以满足我现在的需要,不客气。关于另一个问题,我想这是因为默认情况下,WebBrowser
控件不使用最新版本的浏览器。您可以强制它使用最新版本。我申请了windows窗体应用程序。System.windows.forms.application.DoEvents
似乎不是关键。这个问题仍然存在,特别是在大量Ajax请求方面,这可能意味着解决方案可能在Ajax请求代码方面(请参阅)。
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
public class BrowserBasedWebScraper
{
public static Task<string> LoadUrl(string url)
{
var tcs = new TaskCompletionSource<string>();
Thread thread = new Thread(() => {
try {
Func<string> f = () => {
using (WebBrowser browser = new WebBrowser())
{
browser.ScriptErrorsSuppressed = true;
browser.Navigate(url);
while (browser.ReadyState != WebBrowserReadyState.Complete)
{
System.Windows.Forms.Application.DoEvents();
}
return browser.DocumentText;
}
};
tcs.SetResult(f());
}
catch (Exception e) {
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
return tcs.Task;
}
}