2011-06-12 71 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