C# .NET4.0中并行化web爬虫的最佳实践

C# .NET4.0中并行化web爬虫的最佳实践,c#,web-crawler,C#,Web Crawler,我需要通过代理下载很多页面。 构建多线程网络爬虫的最佳实践是什么 是并行的。For\Foreach足够好了,还是更适合于繁重的CPU任务 你对下面的代码怎么看 var multyProxy = new MultyProxy(); multyProxy.LoadProxyList(); Task[] taskArray = new Task[1000]; for(int i = 0; i < taskArray.Length; i++) {

我需要通过代理下载很多页面。 构建多线程网络爬虫的最佳实践是什么

是并行的。For\Foreach足够好了,还是更适合于繁重的CPU任务

你对下面的代码怎么看

var multyProxy = new MultyProxy();

   multyProxy.LoadProxyList();


   Task[] taskArray = new Task[1000];

        for(int i = 0; i < taskArray.Length; i++)
        {
            taskArray[i] = new Task( (obj) =>
                {                                                             
                       multyProxy.GetPage((string)obj);
                },

            (object)"http://google.com"
            );
            taskArray[i].Start();
        }


   Task.WaitAll(taskArray);
我觉得我做错了什么


当我开始我的脚本时,它只使用2%-4%的网络

当您使用大量连接(添加到app.config或web.config)时,这可能会对您有所帮助:



在主要方法的开头添加以下内容:

System.Net.ServicePointManager.DefaultConnectionLimit = 100;

因此,您将不限于少量并发连接。

对于IO绑定的任务,您基本上使用了CPU绑定的线程-即,即使您正在并行化您的操作,它们仍然基本上使用了线程池线程,主要用于CPU绑定的操作

基本上,您需要使用异步模式下载数据,将其更改为使用IO完成端口-如果您使用WebRequest,则使用BeginGetResponse()和EndGetResponse()方法

我建议使用反应式扩展来实现这一点,例如:

IEnumerable<string> urls = ... get your urls here...;
var results = from url in urls.ToObservable()
             let req = WebRequest.Create(url)
             from rsp in Observable.FromAsyncPattern<WebResponse>(
                  req.BeginGetResponse, req.EndGetResponse)()
             select ExtractResponse(rsp);
IEnumerable URL=。。。在这里获取您的URL。。。;
var results=来自url.ToObservable()中的url
let req=WebRequest.Create(url)
从可观察的rsp.FromAsyncPattern(
req.BeginGetResponse,req.EndGetResponse)()
选择响应(rsp);
其中ExtractResponse可能只是使用StreamReader.ReadToEnd来获取字符串结果,如果您想要的是这个结果的话


您还可以考虑使用.Retry操作符,如果您遇到连接问题等,它将允许您轻松重试几次。

谢谢。我是Rx的新手,如何下载100页?我是否需要创建100个Observable并订阅每个URL?如果您已经拥有完整的URL列表,您可以使用.ToObservable从列表中创建一个IObservable-查看使用的相同代码,但在Observable.FromAsyncPattern中从rsp获取错误“调用'SelectMany'时类型推断失败”(
System.Net.ServicePointManager.DefaultConnectionLimit = 100;
IEnumerable<string> urls = ... get your urls here...;
var results = from url in urls.ToObservable()
             let req = WebRequest.Create(url)
             from rsp in Observable.FromAsyncPattern<WebResponse>(
                  req.BeginGetResponse, req.EndGetResponse)()
             select ExtractResponse(rsp);