需求
爬取百度搜索某個關鍵字對應的前一百個網址。
實現方式
VS2017 + Chrome
.NET Framework + C# + Selenium(瀏覽器自動化測試框架)
環境准備
創建控制台應用程序,通過NuGet添加對Selenium的引用
這里因為我用的Google瀏覽器,所以添加這兩個的引用。
代碼輸出
1 static void GrabUrlByKeyWord(string keyWord) 2 { 3 //創建chrome驅動程序 4 IWebDriver webDriver = new ChromeDriver(); 5 //跳至百度 6 webDriver.Navigate().GoToUrl("https://www.baidu.com"); 7 //找到頁面上的搜索框 輸入關鍵字 8 webDriver.FindElement(By.Id("kw")).SendKeys(keyWord); 9 //點擊搜索按鈕 10 webDriver.FindElement(By.Id("su")).Click(); 11 }
運行看一下效果先
1 static void Main(string[] args) 2 { 3 GrabUrlByKeyWord("香香瓜子"); 4 }
是不是感覺太簡單了,這么快就來到目標頁面了(這么想就太天真了。。)
F12,觀察發現搜索結果都在一個id為content_left的div中,進一步解刨
百度對目標做了中轉,最關鍵的是它對目標url做了加密。。。
那么?問題來了,我們怎么獲取到目標真實的網址呢?
當然,方法有很多:
①可以通過Selenium模擬真實操作,每個結果都點進去,獲取地址欄的網址;(這樣效率是不是太低了。。。)
②解密;(目前我還沒有找到解密方法。。。)
③后台通過HttpClient發送請求,獲取url;
......
......
......
把想說的思想總結一下:
使用HttpClient一個一個去請求的地址來獲取真實地址的話,這樣效率很低,
使用PLINQ並行查詢 或 多線程 的話,效率變高了,但是它的執行順序是不定的,
我們需要的結果又是排名的順序,這時候可以把操作對象封裝成不依賴順序的model,
例如給model加一個rank排名屬性,后期可以根據該屬性進行處理。
貼一段來自Microsoft的文本:
雖然可以指示 PLINQ 暫留任何源序列的順序,但這會對性能產生不利影響。 最佳做法是,盡量將查詢的結構設計為不依賴順序暫留。