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

Nei*_*ir0 3 c# web-crawler

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

是Parallel.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);
Run Code Online (Sandbox Code Playgroud)

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

这段代码也很糟糕.

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

我认为我做错了什么.

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

Mar*_*nst 8

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

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

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

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);
Run Code Online (Sandbox Code Playgroud)

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

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