在我工做的多家公司,有衆多的領域,如房產,電商,廣告等領域。儘管業務相差很大,但都涉及到爬蟲領域。開發爬蟲項目多了後,天然而然的會面對一個問題——html
這些開發的爬蟲項目有通用性嗎?java
有沒有可能花費較小的代價完成一個新的爬蟲需求?python
在維護運營過程當中,是否可以工具化,構建基於配置化的分佈式爬蟲應用?數據庫
這就是是咱們今天要討論的話題。服務器
立項之初,咱們從使用的腳度試着提幾個需求。架構
1. 分佈式抓取
因爲抓取量可能很是龐大,一臺機器不足以處理百萬以上的抓取任務,所以分佈式爬蟲應用是首當其衝要面對並解決的問題。
2. 模塊化,輕量
咱們將爬蟲應用分紅「應用層,服務層,業務處理層,調度層」 四個腳色。併發
3. 可管理,可監控
管理監控是一個體系,即配置可管理化,運行實時監控化。在系統正常運行時,能夠變動爬蟲的配置,一旦實時監控爬蟲出現異常,可實時修正配置進行干預。全部的一切,都可以經過UI界面進行操做。框架
4. 通用性,可擴展。
爬蟲業務每每多變,不一樣領域的爬取需求不盡相同。舉例說,房源抓取包含圖片抓取,小區信息抓取,房源去重等模塊。新聞抓取包括內容抓取,正文提取,信息摘要等相關。
所以,系統須要可以支持業務擴展需求,能夠支持不一樣的業務使用同一套框架進行應用開發。 分佈式
針對業務需求,咱們將系統分解成多個應用模塊。模塊化
應用層是針對管理員,系統維護人員使用。主要分紅兩個模塊,系統配置模塊和運營管理模塊。
系統配置模塊:系統配置模塊包含抓取網站管理配置,在線測試等功能。
運營管理模塊:運營管理模塊包含實時抓取量統計,分析,正確率等。甚至包括失敗緣由,失敗量。
系統運營人員能夠根據運營模塊獲得實時的反饋,使用系統配置模塊進行配置修正,在線測試正確後將配置生效,再實時監控新的配置產生的效果。
服務層是整個系統傳輸的中樞,至關於整個分佈式集中的系統總線和數據總線。服務層提供一個http/thrift接口,讀取數據庫,輸出配置信息。
提供網站爬蟲配置接口。從數據庫中實時讀取配置信息,響應業務層的配置請求。
提供業務層輸出寫入接口。接受業務層實時爬取的信息彙總,包括正確數據量,錯誤數據量,以及錯誤緣由。
提供實時報表統計分析。響應應用層的運營管理模塊,查詢數據庫,實時提供數據分析報告。
業務處理層是整個爬蟲系統的核心,可分紅多臺應用服務器進行處理。業務處理層主要包含解決兩件事情。
如何獲取url
獲得url後,如何處理
對於爬蟲來講,如何獲取url相當重要。咱們將這一過程定義爲發現系統。對於發現系統而言,目標爲如何發現待抓取網站的詳細url列表,儘量的發現更全。
假設場景 A
咱們逛一個電商網站:打開首頁-打開分類頁-可能會有多層分類頁-逐層點擊-直至最小的分類頁面。
打開這個分類頁會發現該分類頁下的全部分頁頁面,一頁一頁往下翻,就可以得到該分類頁的全部商品。
假設場景 B
咱們逛一個汽車網站:打開首頁-找到品牌頁-接着找到車系-最後找到車款頁面。
經過以上場景分析能夠獲得一個結論,人能很是智能的找到全部待抓取的詳細頁面,即電商的商品,汽車的車款頁面。那麼,是否能夠經過配置方式來模擬這一過程呢?
請看下圖:
備註以下:
1. root_info:
定義發現模塊的入口頁面,如同人打開汽車站的網頁,後續的發現都是起始於這些入口頁。
這裏給出的實例是,某汽車網的品牌列表頁,根據「模板化」套用變量的配置,共有100個入口頁。
2. steps:
依次遍歷這100個入口頁,分別會執行steps中定義的步驟。機器模擬人的方式進行查看瀏覽。
每一個step中,會使用"link_module"定義的類進行邏輯進行處理。
讀取入口頁的html,結合"sub_prefix","sub_suffix"和"select"定義的內容,得到頁面子區域html。
使用"link_match_method"的方法(含前綴包含,匹配等),抽取子區域的連接。
每一個連接 和"link_pattern"進行匹配,匹配成功的url進入下一步。
每一步獲得的url,自動進和地下一步處理,處理邏輯爲遞歸上面a-c,直至"last_step"爲true爲止。
此處,即"last_step"爲true中發現的url,即爲發現系統最終須要獲取的url列表。發現系統總結,經過配置的方式,結合人類的瀏覽習慣,經過若干步迭代,最終獲取網站的詳細頁url列表。
因爲每一步的抽取連接規則,以及步數據都是人爲定義,所以,能夠適配絕大部分網站的發現系統。固然,越複雜的網站發現配置可能更多一些、更爲繁雜,但萬變不離其宗。
前提固然是每一個業務的處理各不相同,有抽取頁面屬性功能、有正文提取、有圖片獲取,甚至有和當前系統對接等。
因爲業務處理不一致,很天然想到的是經過配置方式,定義職責鏈系統,如同著名框架Netty中的Pipeline設計。在處理過程當中,定義一個Context上下文處理類,而且,全部的中間結果都暫緩在這個Context中。
描述比較空洞,仍是結合實際案例來看。
備註以下:
獲得一個url後,讀取配置,當url和"site"匹配時,適用當前"site"規則。
1 pipeline定義職責鏈的處理過程
此處的定義爲「抓取模塊,Javascript處理模塊,通用解析模塊」。對應的處理以下:
先執行抓取模塊,獲得html。緊接着執行Javascript處理模塊,輸入爲html,解析html,此處多是評論,也多是價格,總之處理的是動態加載項目,緊接着處理「通用解析模塊」
2 "parser_rules"定義的是解析模塊
最終輸出的是kv,在java中是map,python中是dict。即從上一步的html中,找到每一薦的"sizzle",執行"prefix","suffix"即先後綴移除(過濾如同「價格:xxx元,前綴爲「價格:",後綴爲元)。
對了,sizzle也是一個開源技術,聽說之前鼎鼎有名的Jquery也是"sizzle"引擎。Java中可使用Jsoup解析處理。
怎麼知道須要取的"sizzle"內容是什麼呢?具體能夠結合firebug插件,選中便可得。選中後,結合應用層的管理工具,便可進行測試。
3 「isrequire"
能夠看到,配置項中有「isrequire",表示這項內容是否必須。若是必須,且在實際處理中獲取不到,那麼在抓取的過程當中,就會記錄一個錯誤, 錯誤緣由天然是「$key is null"。此外,每個module均可能出錯,一旦出錯,就沒有必要日後去執行。
所以,在抓取過程當中,業務處理層從服務層得到一批url(默認100個)後,在處理這一百個url結束後,會向服層report,report內容爲:
當前任務處理機器,於什麼時間處理100個頁面。不一樣網站成功多少、失敗多少、什麼模塊失敗多少,解析模塊什麼字段失敗多少。
全部這些信息,均是實時統計,並在運營監控系統中以圖表形示繪製出來,必要時能夠發出報警,交由維護人員實時干預。
Q: 提一個問題,新增一個anotherauto.com網站怎麼辦?
A: 其實也很簡單,再增長一個配置唄。業務定義pipeline,若是有解析需求,填寫對應的解析項便可。
以上兩個系統,發現系統和處理系統,在咱們實際生產中,是經過如下步驟貫穿。
發現系統累計發現待抓取網站的詳細頁,由於是一個累計持續的過程。所以有把握持續無限接近網站的100%頁面。
處理系統經過服務層,每次去取配置信息(可能維護人員在實時修正)及待抓取的列表進行處理。
待抓取的列表根據業務的優先級,分普通隊列及優先級隊列,經過任務調度系統進行統一管理和配置。
調度層
調度層主要是業務系統。
新增一個網站任務調度
網站發現頻率,包括增量發現頻率和全量發現頻率
網站抓取優先級推送至隊列
斷點續抓管理
......
從業務模塊上看
應用層,服務層,業務處理層,調度層
從功能系統上看
發現系統,抓取系統, 配置系統,監控系統
從擴展性上看
自定義職責鏈,自定義屬性提取
從實時性上看
實時抓取,實時配置生效,實時監控,實時測試
從系統架構上看
分佈式架構,服務層主從切換設計,輕量(僅依賴於隊列,數據庫,java)
①
②
③
*爬蟲模塊 ui二 (1.6 任務配置) :
定義每一個爬蟲任務的處理執行職責鏈,不一樣的爬蟲任務能夠有不一樣的處理鏈。對於系統而言,處理每個待爬取的url,都會按照職責鏈的順序執行。後置處理類則是一批任務執行後(如上文的100個url),批量提交的方式。如文件落地,入庫,推往線上系統等。經過任務處理定義,則能夠自定義各種不一樣場景的爬蟲業務,在不編碼的前提下增長系統的靈活性。*
④
*屬性配置:
如圖所示,維護人員增長條測試的url,同時定義須要提取的屬性,則可在線定義該頁面對應的屬性輸出,可見便可得。
在增長便利性,可測試性的基礎上,又能靈活的選取頁面的任意屬性,值得一提的是,能夠經過firefox插件獲取sizzle的配置。*
⑤
*1.9查看明細:
在爬蟲系統的運行過程當中,幾乎能夠實時的進行任務的監控。因爲爬蟲任務實時將爬取的狀態寫入數據庫,所以徹底能夠經過ui界面進行管理及監控。1. 監控:監控爬蟲任務當前時間成功次數,錯誤次數,什麼模塊錯誤,甚至某個屬性提取錯誤。2. 管理:維護人員觀測監控效果後,可實時進行編輯及管理(見上一張圖),以應對不一樣網站的改版需求。全部編輯實時生效,編輯完成後,無需重啓服務,又可實時監控爬蟲任務的最新效果。*
踏浪無痕 豈安科技高級架構師
十餘年數據研發經驗,擅長數據處理領域工做,如爬蟲、搜索引擎、大數據應用高併發等。擔任過架構師,研發經理等崗位。曾主導開發過大型爬蟲,搜索引擎及大數據廣告DMP系統目前負責豈安科技數據平臺開發與搭建。