c# Crawler将单线程WebClient调用移动到多线程
本文关键字:移动 多线程 调用 WebClient Crawler 单线程 | 更新日期: 2023-09-27 18:04:54
我们目前有一个网络爬虫,我们的客户没有能力为我们提供一个xml文件。这个列表正在建设,所以我需要有一个更有效的方式来抓取这些网站。爬虫的逻辑很简单:
Pass in www.example.com/widgets
Store the html and pass it to crawler function
crawl widgets page 1
IF widgets page 1 is the end of their product list
stop
else
go to widgets page 2
对于队列中的每个站点重复此操作。如您所见,如果Site 1有5000个产品,那么Site 2在完成之前无法继续。什么是最好的多线程方式,这样我就可以限制我对每个站点的请求数量,但同时抓住多个站点?我试过Parallel。但结果是非常零星和不可预测的。目前,我们通过使用Windows任务管理器同时启动"组"存储来处理这个问题。下面是一些示例代码:
foreach(site in ListofSites)
{
int page = 1;
bool continue_crawling = true;
while(continue_crawling)
{
HtmlDocument doc = new HtmlDocument();
var htmlWeb = new HtmlWeb();
htmlWeb.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
doc = htmlWeb.Load(URL + page);
string html = doc.DocumentNode.OuterHtml;
continue_crawling = ParseFile(html);
page++;
}
}
private bool Parse(string html)
{
//parse the file and see if we have enough data
return endofproduct;
}
所有c# HTTP请求都将通过请求URL域的ServicePoint
。ServicePoint将从ServicePointManager.DefaultConnectionLimit
继承ConnectionLimit
。默认值是2,根据RFC2616的"良好客户端实践":
单用户客户端不应该与任何服务器或代理保持超过2个连接。
所有这一切都意味着,向同一域中的url发起1兆次HTTP请求最多只能发送2个HTTP请求,并且除非一个请求完成,否则另一个请求将不会启动。要实现更高的并发性,您需要为感兴趣的域增加ServicePoint连接限制。使用线程(包括PTL)执行并发IO相当原始,但如果修复了限制,应该可以工作。当然,使用异步IO更可取。