Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在类库中使用WebBrowser进行Web抓取_C#_.net_Web Scraping - Fatal编程技术网

C# 在类库中使用WebBrowser进行Web抓取

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

我需要在类库中创建一个方法来获取URL的内容(可以由JavaScript动态填充)

我不知道,但整天都在谷歌上搜索,这就是我想到的:(大部分代码来自)

使用系统;
使用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;
    }
}