C# .NET4.0中并行化web爬虫的最佳实践
我需要通过代理下载很多页面。 构建多线程网络爬虫的最佳实践是什么 是并行的。For\Foreach足够好了,还是更适合于繁重的CPU任务 你对下面的代码怎么看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++) {
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);