最近在摸索爬蟲相關的東西,寫點隨筆,以便忘記。
目的與用途
現實的項目中,我們需要太多的第三方接口了。而往往這些第三方接口由於條件限制,一時拿不到。
譬如:
1. 淘寶網今天有什么特價商品。
2. 百度今天的熱搜榜是什么。
3. 某用戶的水電、話費、煤氣有沒有欠費,欠了多少。
等等問題,怎么辦呢?
解決不了就請程序員出馬,因為程序員是萬能的,程序員是無敵的。
原理
既然我們沒有能力(財力)與阿里巴巴、百度等第三方做對接,那么我們可以通過模擬訪問他們對於的頁面,並抓取對應的數據,來收集相關的信息。
這里,模擬是關鍵,也有很多細節要處理。后面我會一一講解。
工具
工欲善其事,兵線利器。 想要模擬訪問他人的網頁,爬取對應的數據, 那么我們首先要了解對應的網頁做了什么動作,如何了解,這里我介紹我用過的三種工具。
1. IE的開發人員工具
IE的開發人員工具,在打開IE的時候,按“F12”能直接呼出,並選擇“網絡” > "開始捕捉"
對於抓包功能,需要IE的版本達到9或者9以上。 IE8不支持抓包功能。
優點: IE自帶,非常方便。
缺點: IE9和IE11的界面風格還有點不一樣。 IE11對於數據的拷貝非常不方便。 IE9用着感覺還行。至少數據能拷貝。 但是我有個較復雜的數據爬取,它居然漏了關鍵的post。
建議: 只支持IE的網站,並且相對較簡單的數據爬取,可以直接選擇此工具。
2. CHROME的開發人員工具
google的開發人員工具還是不錯的。同樣的按F12能呼出,或者按 CTRL+Shift+I也能呼出。
同樣的選擇“網絡” 即可捕捉 操作當前頁面的數據包。
優點: 瀏覽器自帶
缺點: 暫時沒發現。
3. httpwatch
前段時間的一次抓包,一直抓不到,后來想到可能是IE開發人員工具的問題,下了這個試試。 結果挺不錯的。比較專業。
優點: 抓包很全面
缺點: 需要自行安裝
如果是新手,我建議使用CHOROME的開發工具,或者httpwatch。
相關的類
原則上,只要實現HTTP協議的類,應該都可以, C#與抓包有關的類我用了2個,基本滿足需要了。
WebClient 類,
此類使用非常簡單, 直接提交頁面參數與URL即可獲得對應的頁面輸出內容。 但是如果涉及到客戶端與服務端的會話保持(如:需要登錄后才能看到的數據)的情況,就無勇武之地了。對於WebClient的用法
HttpWebRequest & HttpWebResponse
這兩個類是較底層的類,如果需要與服務器保持會話。就需要靠這兄弟兩了。
聽說其他語言抓包相對簡單, 而C#相對繁瑣,也是因為她,誰讓他那么底層的呢,而且聽說還稍微有BUG,但我沒遇到。
HtmlAgilityPack
此類屬於第三方類,請自行百度。 當然也不一定需要用。 需要看做出的爬蟲需要爬的數據多不多,如果只想獲取頁面中一兩個字段,完全不需要用。
我們知道,使用爬蟲爬出來的是一大串字符串, 但其實他就是html標記的字符串, 我們非常希望用js來操作dom元素。 可惜C#中,並沒有這樣的功能。而這個第三方類,就是實現了將html標記的字符串,直接轉換成了類似DOM一樣的對象。 這樣,我們就能輕松獲取查找對應的數據值了。
hello world
由於后面還會說到模擬登錄、文件傳輸等相關信息,這里我用HttpWebRequest 類來說明。
以博客園首頁列表的數據為例:
static void Main(string[] args) { string html= Hello(); Console.WriteLine(html); Console.Read(); } static string Hello() { //列表數據,一般通過抓包工具,點擊下一頁,來發現共同的規則,從而找到對應的URL string url = "http://www.cnblogs.com/mvc/AggSite/PostList.aspx"; //根據抓包工具,獲取需要POST的數據, 並分析對應的數值, 明細這里PageIndex:1 是指第二頁。其他的暫不做分析 string postData = "{ \"CategoryType\":\"SiteHome\",\"ParentCategoryId\":0,\"CategoryId\":808,\"PageIndex\":1,\"TotalPostCount\":4000,\"ItemListActionName\":\"PostList\"}"; //1.構建Request HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); req.Method = "POST";// POST OR GET, 如果是GET, 則沒有第二步傳參,直接第三步,獲取服務端返回的數據 req.AllowAutoRedirect = false;//服務端重定向。一般設置false req.ContentType = "application/x-www-form-urlencoded";//數據一般設置這個值,除非是文件上傳 //2.同過流的形式,傳輸參數。 byte[] postBytes = Encoding.UTF8.GetBytes(postData); req.ContentLength = postBytes.Length; Stream postDataStream = req.GetRequestStream(); postDataStream.Write(postBytes, 0, postBytes.Length); postDataStream.Close(); //3. 獲取服務器端的返回數據。 HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); string html = new StreamReader(resp.GetResponseStream()).ReadToEnd(); return html; }
最簡單的模擬抓包,主要3步
1. 構建HttpWebRequest。
2. 構建需要傳輸的參數
3. 獲取HttpWebResponse
參考文獻:
http://www.cnblogs.com/hambert/p/6118299.html
http://www.crifan.com/emulate_login_website_using_csharp/
https://q.cnblogs.com/q/67303/