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# Crawler将单线程WebClient调用移动到多线程

所有c# HTTP请求都将通过请求URL域的ServicePoint。ServicePoint将从ServicePointManager.DefaultConnectionLimit继承ConnectionLimit。默认值是2,根据RFC2616的"良好客户端实践":

单用户客户端不应该与任何服务器或代理保持超过2个连接。

所有这一切都意味着,向同一域中的url发起1兆次HTTP请求最多只能发送2个HTTP请求,并且除非一个请求完成,否则另一个请求将不会启动。要实现更高的并发性,您需要为感兴趣的域增加ServicePoint连接限制。使用线程(包括PTL)执行并发IO相当原始,但如果修复了限制,应该可以工作。当然,使用异步IO更可取。