在.net 4.0中并行化Web爬虫的最佳实践

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

是Parallel.For \ Foreach是否足够好还是更适合繁重的CPU任务?

您对以下代码怎么说?

var multyProxy = new MultyProxy(); multyProxy.LoadProxyList(); Task[] taskArray = new Task[1000]; for(int i = 0; i  { multyProxy.GetPage((string)obj); }, (object)"http://google.com" ); taskArray[i].Start(); } Task.WaitAll(taskArray); 

它的工作非常糟糕。 这很慢,我不知道为什么。

这段代码也很糟糕。

  System.Threading.Tasks.Parallel.For(0,1000, new System.Threading.Tasks.ParallelOptions(){MaxDegreeOfParallelism=30},loop => { multyProxy.GetPage("http://google.com"); } ); 

好吧,我认为我做错了什么。

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

您基本上使用CPU绑定线程进行IO绑定任务 – 即。 即使您正在并行化您的操作,它们仍然主要使用ThreadPool线程,该线程主要用于CPU绑定操作。

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

我建议看看Reactive Extensions来做这件事,例如:

 IEnumerable urls = ... get your urls here...; var results = from url in urls.ToObservable() let req = WebRequest.Create(url) from rsp in Observable.FromAsyncPattern( req.BeginGetResponse, req.EndGetResponse)() select ExtractResponse(rsp); 

其中ExtractResponse可能只是使用StreamReader.ReadToEnd来获取字符串结果,如果这是你所追求的

您还可以查看使用.Retry运算符,如果您遇到连接问题等,这将很容易让您重试几次…

在main方法的开头添加:

 System.Net.ServicePointManager.DefaultConnectionLimit = 100; 

因此,您不会局限于少量的并发连接。

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

         

设置并发连接数而不是50

有关它的更多信息,请访问http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx