不要誤會,我不是針對python,也不是針對nodejs,我是說除了.NET之外,玩爬蟲的都是垃圾 ...
這幾天在微信群里又聊到.NET可以救中國但是案例太少不深的問題,我說.NET玩爬蟲簡直就是宇宙第一,於是大神朱永光說,你為何不來寫一篇總結一下?
那麼今天就全面的來總結一下,在.NET生態下,如何玩爬蟲
關於爬蟲
從搜索引擎開始,爬蟲應該就出現了,爬的對象當然也就是網頁URL,在很長一段時間內,爬蟲所做的事情就是分析URL、下載WebServer返回的HTML、分析HTML內容、構建HTTP請求的模擬、在爬蟲過程中存儲有用的信息等等,而伴隨著App的發展以及CS系統通訊方式的HTTP化,對服務介面特別是HTTP RESTFul介面的爬蟲也開始流行。爬蟲的具體形式,包括模擬瀏覽器行為和模擬HTTP行為。在爬蟲的發展過程中,也涌現出無數的工具和語言實踐,而今天要說的就是,.NET生態是爬蟲最好的伴侶
但是不要誤會,我不是針對python,也不是針對nodejs,我是說除了.NET之外,所有玩爬蟲的都是垃圾
一、先談一談對於爬蟲的理解
很多人在研究爬蟲的初期,熱衷於進行瀏覽器行為的模擬,包括使用一些語言中的WebBrowser控制項或者類似PhantomJS這樣的無頭瀏覽器,來模擬真實Web行為,進行Dom元素的填寫、按鈕點擊、滾動條操作等等。雖然這樣的做法更接近真實場景,但由於瀏覽器事件的複雜性,在批量高速的處理場景中,這樣的做法穩定程度會大打折扣,我個人非常不贊同這樣的理念。我認為只有從本質上對Web行為進行HTTP的分析,才是關鍵,任何複雜的瀏覽器行為,最終都可以準確的拆分為JS邏輯和HTTP行為,所以想要掌握好爬蟲技術,對HTTP的理解和分析至關重要。
二、那麼第一個神器就登場了,Fiddler
雖然不是最早一批誕生的嗅探器,但Fiddler得益於.NET框架的強大並且融合了一個基於JScript .NET的子系統,敏捷而全面嗅探的功能快速的獲得了市場的認可,積累了大量用戶,而在被.NET控制項開發公司Telerik收購後,發展迅猛,更推出了脫離UI的跨平臺庫FiddlerCore,可以將嗅探行為融入到大型搜索網路和爬蟲系統或者是外掛應用中。
Fiidler是.NET紅利的下的優良產物,而一個好的爬蟲開發工程師,首要學習目標就是對HTTP的嗅探分析,這時候Fiddler就必不可少了。在這裡列舉Fiddler幾個常見的用法
1)HTTP行為捕捉。這是基本功能,打開Fiddler後,瀏覽器或者一般進程有任何通訊發生,都會記錄下具體的HTTP請求和響應。並且根據Content-Type自動顯示為具體的內容,當然了,我推薦直接分析RAW信息,直觀明瞭也能更深刻的理解HTTP。本功能常用功能場景有,分析網頁行為、分析應用程式行為、手工獲取登陸Cookies等。
2)HTTPS支持。Fiddler在添加一個本地證書後,可以完整的支持對HTTPS鏈接的抓取。
3)手機應用抓包。現在很多手機應用都使用了RESTFul的後端介面,但在手機上抓取的難度和代價都較大,替代的解決方案是,在Fiddler裡面,開啟一個HTTP代理伺服器,並設置埠,當手機的WIFI網路和Fiddler客戶端網路在同一區域網網段時,設置手機的WIFI網路的代理地址為Fiddler的HTTP代理伺服器地址,這樣手機上任何App的HTTP通訊,都會被Fiddler抓取到。本功能常用功能場景有,手機App抓包、遠程代理測試等。而這一用法也常常和安卓模擬器進行配合,可以在PC上完成全部手機應用的通訊行為的分析。
4)HTTP模擬器。Fiddler內置一個請求構造器(Composer),可以手工構建任何HTTP行為,本功能常用場景有,手工抓取與爬蟲測試。
5)HTTP劫持。Fiddler可以攔截HTTP請求,並響應修改後的數據,這一用法常見於外掛軟體的研發過程,在應用時,則多是FiddlerCore庫在外掛系統中的使用。這裡不得不補充一句,在這之前,最流行的是winpcap庫(或者winpcap庫的.NET封裝Pcap.Net、sharppcap等),雖然winpcap的工作原理使得其應用範圍更廣,但FiddlerCore無疑已經成為了當前應用端最炙手可熱的領域庫。
三、接下來再說一下.NET對HTTP的操控能力
爬蟲的主要邏輯部分,即是通過程式對HTTP進行操控,包括對目標URL的下載、對模擬HTTP請求的構造。有趣的是,即使只用System.Net下,WebClinet和HttpWebRequest這兩個類,就已經能夠滿足99%的爬蟲場景。下麵列舉一些常用的場景
1)URL快速下載(上傳)。使用WebClinet對URL進行瀏覽並下載,可以說代碼清晰、支持豐富。包括編碼格式、下載格式、非同步下載、Form上傳、參數拼接等等各種。
2)HTTP請求構造。在很多場景中,需要偽造Referer、UserAgent、ContentType等等,從一個語言的HTTP庫對HTTP協議的支持細膩程度可以看出其是否親爬蟲,幸運的是,HttpWebRequest確實足夠全面,能夠滿足所有的自定義需求。
3)Cookies處理。雖然Cookies已經逐漸淡出歷史的舞臺,但依然有大量的Web開發框架是以Cookie為支撐做Session體系的,所以Cookie的靈活操作也非常重要。
4)代理服務。有時候目標伺服器會對IP訪問做限制,這時候使用代理伺服器以及不停的更換代理伺服器就非常重要了,如下處理也很簡潔
不過,也承認一下缺陷,Socks4或者Socks5代理也是會偶爾出現在爬蟲處理中,而HttpWebRequest並不直接支持,而我之前用到過一個非常好的網路處理庫(收費的,還有EMail處理等各種),有完整的Socks5支持,但是好多年了,記不得名字了,有知道的同學可以告訴我,我補充到這篇文章里。
當然了,得益於.NET語言的強大,除了WebClinet和HttpWebRequest這兩個老古董外,還有不少好東西,比如
1)HttpClient。這是.NET4.5框架裡帶來的新東西,相比HttpWebRequest,HttpClient更像是一個無頭瀏覽器,對非同步的支持也更加完備,處理邏輯也更加合理,建議一直用HttpWebRequest做爬蟲的同學可以遷移到HttpClient來。
2)其他基於.NET的第三方HTTP庫或者知名HTTP的.NET實現。例如RestSharp,EasyHttp,Indy.Sockets等等,這些庫對HTTP進行更加便捷方便的封裝,有興趣的同學也可以試一試,當然了,在這裡我也提一個建議,不要沉迷於對HTTP請求便捷的封裝,.NET也不例外,這會讓你遠離HTTP的本質,對爬蟲能力的提升並無幫助。
四、內容處理也是.NET的強項
在做內容型爬蟲時,會出現很多對下載後的內容進行處理的場景,主要也就是對文本的處理,這裡又一次體現了.NET的優勢,包括
1)String類及周邊類。我們來看一張圖
這裡基本上涵蓋了對字元串的所有處理方法,結構清晰、使用方便。除此之外,還有很多周邊類,諸如Char、StringBuilder、Encoding等等,用過的都知道好!
2)正則處理。老實說,正則的學習成本往往會高於使用成本,有時候簡單的場景用一些基本的演算法和字元串處理比正則要方便的多,但作為頂級爬蟲玩家,正則處理是一門必須掌握的技能,而一旦你深入而且熟練的掌握了正則處理方法,那麼對字元串的查找、重覆數據的處理的效率將會邁上新的臺階。.NET下正則的處理在System.Text.RegularExpressions命名空間里。
3)Javascript模擬。正如前面所說,所有複雜的瀏覽器行為,最終都可以準確的拆分為JS邏輯和HTTP行為,很多複雜邏輯或者加密的頁面,直接下載到的數據還需要經過一些JS處理,才能夠變成有用的數據,這個時候Microsoft.JScript命名空間的作用就凸顯了,可以快速方便的模擬一些Javascript的內置方法,特別是時間類、數學類、加密類的一些古怪方法,避免走彎路。
4)序列化與反序列化(JSON、XML處理)。很多新應用的通訊格式多為XML或者JSON,對於此類內容的處理,會涉及到很多JSON、XML序列化反序列化,其中也以JSON序列化居。
首先是XML的處理,.NET中有System.Xml.Serialization命名空間或者System.Runtime.Serialization.DataContractSerializer等。而對XML處理的關鍵,在於能夠靈活的自定義符合XML標準的內容,例如如下代碼:
然後是JSON的處理,雖然JSON標準並沒有XML那麼複雜,但想要靈活處理,也需要好的框架和工具支撐,在.NET裡面,有下麵幾個好東西推薦
第一個推薦的是Json.NET,這是一個非常流行的JSON處理工具,具體用法不細說,貼幾個官方的介紹代碼
第二個推薦的是Jil,這是一個速度更快、更加敏捷且細粒度更高的JSON處理庫,與.NET動態語言特性配合,能夠寫出如下優雅且實用的代碼
總之一句話,這樣科班而正統的序列化處理體系,不僅能力強大,更讓人心情舒暢!
五、.NET下,敏捷地存儲數據會是一個好幫手
爬到的數據不可能總是在記憶體里操作,大部分時候,也需要存為臨時文件或者資料庫數據。而.NET在這裡的優勢依然非常明顯。
1)保存到文本文件。.NET提供了很多類,可以方便的操作文本文件,例如下麵這樣的超敏捷文本文件操作。
除此之外,還有FileStream、StreamReader等強大的文件操作類可供使用。
2)保存到資料庫。爬蟲程式對目標進行一系列處理後,有用的數據會存入資料庫,如果說在.NET下對SQL Server、MySQL、Oracle、SQLite等資料庫的全面支持是一輛性能十足的跑車,那Linq語法糖加上兩個ORM框架(Linq To SQL、ADO.NET Entity Framework)則是給這個跑車加了個渦輪增壓。可以讓我們用最敏捷漂亮的方式,將爬蟲數據存入到資料庫中,簡潔到窒息
如果有大批量數據快速插入需求,同樣也有Z.EntityFramework.Extensions這樣的第三方擴展組件可供使用。
凡此種種,只為讓數據處理不要成為爬蟲研發的累贅和束縛
六、.NET生態數不勝數的優秀特性讓爬蟲開發變得優雅
除了以上這些和爬蟲直接相關的內容,.NET還有無數的優秀的特性,可以讓爬蟲開發如虎添翼,我列舉幾個
1)WinForm開發。.NET的WinForm開發,應該是自Delphi後,效率最高的桌面UI開發方式了,雖然和爬蟲沒太大關係,但是如果能夠熟練用好WinForm,完全可以替代控制台應用,來進行爬蟲研發,提高研發效率,誰都別裝逼(特別是Linuxer、Macer等),畢竟,複雜可視化比控制台樣方便多了。
2)多線程處理。即使是在.NET 2.0時期,委托相關機制,便已革新了Win32的多線程API使用方式,而進入到Task並行庫時代後,更是優美到飛起,例如下麵這兩種常見的多線程處理方式
同步語句,非同步處理
線程併發,靈活跳出
我想,事已至此,其他所有的語言(.NET體系除外),都是望塵莫及吧。
4)定時處理。定時處理在很多爬蟲場景裡面都會用到,這裡也簡單提一下,在.NET里處理定時可以採用兩種方式,1、是編寫WIndows Service服務來進行定時任務的控制,2、是用定時雲服務(阿裡雲監控、騰訊雲撥測等)喚醒一個IIS托管的ASP.NET Web Application。特別是第二種方式,思路新穎,經我實踐也非常穩定可靠,有興趣的同學可以試一試。
5)其他優秀特質。.NET架構和.NET體系語言因Anders Hejlsberg的偉大而偉大,數不勝數的優秀語言特質,在任何一個聰明的開發人員面前,都是寶藏,諸如泛型、擴展方法、動態語言特性、Lamada表達式、反射等等,到底對爬蟲的開發有何幫助,只待大家去慢慢體驗和挖掘咯
七、規模化、系統化的爬蟲,.NET下的軟體工程
當出現龐大目標、複雜策略的時候,客觀上下載器就要升級為下載系統、多線程處理擴充了隊列處理、定時程式就也演變為任務體系,這個時候,爬蟲程式就升級成了規模化的爬蟲系統,變成了一個軟體工程的問題,正如上面所說,.NET很強,但實踐太少,能夠深刻理解.NET人也很少。
.NET處理爬蟲很強,可問題是,.NET處理哪個領域不強?都非常強!.NET的軟體工程,還有待各位不斷的去探索,去發揚!
七、最後再補充一個附加題,就是超高速IPV4的代理IP掃描
這是我之前很深入研究過的一個課題,雖然和爬蟲沒有直接的關係,但結果(高匿名HTTP代理)和爬蟲也有著密不可分的聯繫,況且處理過程也非常值得借鑒,所以分享出來
1)先說一下結果。藉助.NET體系來處理代理IP的掃描,效率極高,產量驚人,實測單節點(100M電信家庭光纖接入)每天可以產生5萬個有效的代理IP。下麵說一下幾個關鍵點
2)IP段資源和資源處理。優質的IP段(特別是機房IP段)以及IP段劃分,都是重要的資源,3個關鍵操作包括, 對純真等IP地址庫存入資料庫進行查詢、將IP段以一定的模型存入資料庫進行查詢、建立分散式的IP段處理隊列機制。
3)SYN高速掃描(S掃描器方式)。超高速IPV4的代理IP掃描的核心技術,就是利用TCP/IP漏洞的SYN半連接掃描,有一個使用C寫的s.exe掃描器是最常見的用法,基於命令行執行模式,而在.NET中,則可以用System.Diagnostics下麵的Process類進行完整的控制和處理,這又一次體現了.NET的價值。本方式下也有個缺陷,就是僅限Windows Server 2003以下操作系統使用。
4)SYN高速掃描(.NET封裝SYN方式)。正如上文所說,.NET對於winacap有很多成熟的封裝,可以做到在Windows 10操作系統下的SYN高速掃描,並控制掃描更加穩定(S掃描器高速但並不穩定),用於桌面級分散式代理IP掃描是絕佳配備。
5)代理IP驗證。掃描到開放埠的IP地址後,只有驗證成功了才能被我們所用,而往往成功率都在萬分之一以下,所以驗證的過程又是一個關鍵所在,幸好我們有.NET下的優秀的多線程處理,使得這一驗證程式非常簡潔和易重構。
如果對此話題有興趣的同學,可以聯繫我尋求進一步的幫助,今天篇幅有限,只是簡單略過
八、今天要說的差不多就結束了,下麵是總結
總結1。今天討論的東西不是爬蟲而是.NET如何玩爬蟲。也並不是在說.NET某個具體功能如何絕頂厲害,而是在說在.NET生態下的很多出色功能結合到一起後,就變成了一個非常美好親爬蟲的體系。所以無論是從生態能力出發還是基於學習實踐成本的考慮,做爬蟲程式或是大規模爬蟲系統,.NET一定是首選!
總結2。我試圖告訴一些用其他語言正在研究爬蟲的人們,你們走了一條邪路,以python比較有名的爬蟲框架scrapy為例,這又是一群想建造輪子的忙碌不休的但卻又智商不高的程式員所折騰出怪胎,試圖統一爬蟲的過程,構建模塊化流程化的插件機制,但事實上,這種東西用的越多,越遠離了爬蟲的本質,越不能適應複雜的爬蟲場景。爬蟲的本質是對目標WebServer頁面行為和業務流程的精準分析,是對HTTP的深刻理解,是對正則、多線程等周邊技術以及軟體工程的靈活運用,爬蟲場景稍微複雜變化一下,scrapy這樣的爬蟲就成了雞肋,運用scrapy這樣的工具,對程式員在爬蟲領域的學習成長來說,不僅沒有明顯幫助,更顯反智,我有遇到過相當多做爬蟲的同學,連HTTP Header裡面有些什麼都說不出來說不清楚,卻玩爬蟲工具6的飛起,這無疑是可悲的。切記先學會走路,再去跑步,而當你深刻的理解了爬蟲的本質後,你就會發現,並沒有所謂的爬蟲語言或者爬蟲框架,只有高效的語言和工具,而這時:
.NET生態就恰到好處的映入你眼前,讓你流連忘返!
轉載請註明出處,歡迎郵件交流:[email protected],或者加QQ群:11444444