.net 4.0 中并行网络爬虫的最佳实践

2024-01-21

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

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);

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

这段代码也运行得很糟糕。

 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() 方法

我建议查看反应式扩展来做到这一点,例如:

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);

其中 ExtractResponse 可能只是使用 StreamReader.ReadToEnd 来获取字符串结果(如果这就是您想要的)

您还可以考虑使用 .Retry 运算符,如果您遇到连接问题等,它可以轻松地让您重试几次......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

.net 4.0 中并行网络爬虫的最佳实践 的相关文章

随机推荐