2011-06-12 90 views
5

我有一个C#应用程序,需要尽快扫描特定域中的许多网页。我有过所有的URL(多线程)和擦伤他们的使用下面的代码循环一个Parallel.Foreach:最快的方法来在一个网站内抓取所有网页

private string ScrapeWebpage(string url, DateTime? updateDate) 
     { 
      HttpWebRequest request = null; 
      HttpWebResponse response = null; 
      Stream responseStream = null; 
      StreamReader reader = null; 
      string html = null; 

      try 
      { 
       //create request (which supports http compression) 
       request = (HttpWebRequest)WebRequest.Create(url); 
       request.Pipelined = true; 
       request.KeepAlive = true; 
       request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate"); 
       if (updateDate != null) 
        request.IfModifiedSince = updateDate.Value; 

       //get response. 
       response = (HttpWebResponse)request.GetResponse(); 
       responseStream = response.GetResponseStream(); 
       if (response.ContentEncoding.ToLower().Contains("gzip")) 
        responseStream = new GZipStream(responseStream, CompressionMode.Decompress); 
       else if (response.ContentEncoding.ToLower().Contains("deflate")) 
        responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); 

       //read html. 
       reader = new StreamReader(responseStream, Encoding.Default); 
       html = reader.ReadToEnd(); 
      } 
      catch 
      { 
       throw; 
      } 
      finally 
      {//dispose of objects. 
       request = null; 
       if (response != null) 
       { 
        response.Close(); 
        response = null; 
       } 
       if (responseStream != null) 
       { 
        responseStream.Close(); 
        responseStream.Dispose(); 
       } 
       if (reader != null) 
       { 
        reader.Close(); 
        reader.Dispose(); 
       } 
      } 
      return html; 
     } 

正如你所看到的,我有HTTP压缩的支持,并建立request.keepalive和request.pipelined为true。我想知道如果我使用的代码是在同一站点内刮取多个网页的最快方式,或者有更好的方法可以保持会话对多个请求打开。我的代码是为每个我打的页面创建一个新的请求实例,我是否应该试图只使用一个请求实例来打开所有页面?启用流水线和Keepalive是否理想?

+0

“刮尽可能快地” - 请注意,除非你有与网站所有者达成某些协议,这将让你尽快取缔;没有人喜欢未经授权的刮板,特别是如果它们也是意外的DoS(并且为每个请求打开一个新的连接可能会压倒很多服务器) – Piskvor 2011-06-12 21:44:33

+0

关键点:是的,keepalive和流水线会让你获得更好的性能(因为设置/拆卸开销)。 – Piskvor 2011-06-12 21:45:46

+0

是的,它总是一个罚款线,不要太多,以保持低于雷达,但足够快,以保持您的数据保持最新状态。 HttpWebRequest对象的默认超时时间为100秒,我将其设置为10秒,然后获得了大量超时。我意识到有什么不对劲,然后将默认连接限制从10更改为100K,并解决了所有超时问题,现在所有的Web请求都超级快..太快..我现在需要扼杀这个。 :) – Justin 2011-06-13 01:47:50

回答

1

原来是我缺少的是这样的:

ServicePointManager.DefaultConnectionLimit = 1000000; 
+0

你可以标记你的文章作为答案, d想知道你如何使用这个功能,以便它支持保持活着? – Smith 2011-07-10 19:18:27

+0

您可以举例说明如何在后续调用之间使用此函数以保持活动状态? – Smith 2011-08-23 09:19:07

相关问题