《分布式爬蟲框架XXL-CRAWLER》
一、簡介
1.1 概述
XXL-CRAWLER 是一個分布式爬蟲框架。一行代碼開發一個分布式爬蟲,擁有"多線程、異步、IP動態代理、分布式、JS渲染"等特性;
1.2 特性
- 1、簡潔:API直觀簡潔,可快速上手;
- 2、輕量級:底層實現僅強依賴jsoup,簡潔高效;
- 3、模塊化:模塊化的結構設計,可輕松擴展
- 4、面向對象:支持通過注解,方便的映射頁面數據到PageVO對象,底層自動完成PageVO對象的數據抽取和封裝返回;單個頁面支持抽取一個或多個PageVO
- 5、多線程:線程池方式運行,提高采集效率;
- 6、分布式支持:通過擴展 "RunData" 模塊,並結合Redis或DB共享運行數據可實現分布式。默認提供LocalRunData單機版爬蟲。
- 7、JS渲染:通過擴展 "PageLoader" 模塊,支持采集JS動態渲染數據。原生提供 Jsoup(非JS渲染,速度更快)、HtmlUnit(JS渲染)、Selenium+Phantomjs(JS渲染,兼容性高) 等多種實現,支持自由擴展其他實現。
- 8、失敗重試:請求失敗后重試,並支持設置重試次數;
- 9、代理IP:對抗反采集策略規則WAF;
- 10、動態代理:支持運行時動態調整代理池,以及自定義代理池路由策略;
- 11、異步:支持同步、異步兩種方式運行;
- 12、擴散全站:支持以現有URL為起點擴散爬取整站;
- 13、去重:防止重復爬取;
- 14、URL白名單:支持設置頁面白名單正則,過濾URL;
- 15、自定義請求信息,如:請求參數、Cookie、Header、UserAgent輪詢、Referrer等;
- 16、動態參數:支持運行時動態調整請求參數;
- 17、超時控制:支持設置爬蟲請求的超時時間;
- 18、主動停頓:爬蟲線程處理完頁面之后進行主動停頓,避免過於頻繁被攔截;
1.3 下載
文檔地址
源碼倉庫地址
源碼倉庫地址 | Release Download |
---|---|
https://github.com/xuxueli/xxl-crawler | Download |
https://gitee.com/xuxueli0323/xxl-crawler | Download |
技術交流
1.4 環境
- JDK:1.7+
二、快速入門
爬蟲示例參考
(爬蟲示例代碼位於 /test 目錄下)
- 1、爬取頁面數據並封裝VO對象
- 2、爬取頁面,下載Html文件
- 3、爬取頁面,下載圖片文件
- 4、爬取頁面,代理IP方式
- 5、爬取公開的免費代理,生成動態代理池
- 6、分布式爬蟲示例
- 7、JS渲染方式采集數據,"htmlUnit" 方案
- 8、JS渲染方式采集數據,"selenisum + phantomjs" 方案
- 9、采集非Web頁面,如JSON接口等,直接輸出響應數據
第一步:引入Maven依賴
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-crawler</artifactId>
<version>${最新穩定版}</version>
</dependency>
第二步:定義 "PageVo/頁面數據對象"(可選)
在此推薦兩款工具,可以直觀迅速的獲取頁面元素的Jquery cssQuery表達式。
- 1、Chrome DevTools:首先定位元素位置,然后從Element選中選中元素,點擊右鍵選擇“Copy + Copy selector”即可;
- 2、Jquery Selector Helper(Chrome插件):首先定位元素位置,然后從Element右側打開Selector界面,然后定位元素即可;
// PageSelect 注解:從頁面中抽取出一個或多個VO對象;
@PageSelect(cssQuery = "body")
public static class PageVo {
@PageFieldSelect(cssQuery = ".blog-heading .title")
private String title;
@PageFieldSelect(cssQuery = "#read")
private int read;
@PageFieldSelect(cssQuery = ".comment-content")
private List<String> comment;
// set get
}
第三步:創建爬蟲
XxlCrawler crawler = new XxlCrawler.Builder()
.setUrls("https://my.oschina.net/xuxueli/blog")
.setWhiteUrlRegexs("https://my\\.oschina\\.net/xuxueli/blog/\\d+")
.setThreadCount(3)
.setPageParser(new PageParser<PageVo>() {
@Override
public void parse(Document html, Element pageVoElement, PageVo pageVo) {
// 解析封裝 PageVo 對象
String pageUrl = html.baseUri();
System.out.println(pageUrl + ":" + pageVo.toString());
}
})
.build();
第四步:啟動爬蟲
crawler.start(true);
三、總體設計
架構圖
3.1 功能定位
XXL-CRAWLER 是一個分布式Web爬蟲框架。采用模塊化設計,各個模塊可靈活進行自定義和擴展。
借助 XXL-CRAWLER,一行代碼開發一個分布式爬蟲。
3.2 核心概念
概念 | 說明 |
---|---|
XxlCrawler | 爬蟲對象,維護爬蟲信息 |
PageVo | 頁面數據對象,一張Web頁面可抽取一個或多個PageVo |
PageLoader | Wed頁面加載器,負責加載頁面數據,支持靈活的自定義和擴展 |
PageParser | Wed頁面解析器,綁定泛型PageVO后將會自動抽取頁面數據對象,同時支持運行時調整請求參數信息; |
NonPageParser : 非Web頁面解析器,如JSON接口等,直接輸出響應數據
3.3 爬蟲對象:XxlCrawler
功能:爬蟲對象,維護爬蟲信息,可選屬性如下。
方法 | 說明 |
---|---|
setUrls | 待爬的URL列表 |
setAllowSpread | 允許擴散爬取,將會以現有URL為起點擴散爬取整站 |
setWhiteUrlRegexs | URL白名單正則,非空時進行URL白名單過濾頁面 |
setIfPost | 請求方式:true=POST請求、false=GET請求 |
setUserAgent | UserAgent |
setParamMap | 請求參數 |
setCookieMap | 請求Cookie |
setTimeoutMillis | 超時時間,毫秒 |
setPauseMillis | 停頓時間,爬蟲線程處理完頁面之后進行主動停頓,避免過於頻繁被攔截; |
setProxyMaker | 代理生成器,支持設置代理IP,同時支持調整代理池實現動態代理; |
setThreadCount | 爬蟲並發線程數 |
setPageParser | 頁面解析器 |
setPageLoader | 頁面加載器,默認提供 "JsoupPageParser" 和 "HtmlUnitPageLoader" 兩種實現; |
setRunData | 設置運行時數據模型,默認提供LocalRunData單機模型,支持擴展實現分布式模型; |
start | 運行爬蟲,可通過入參控制同步或異步方式運行 |
stop | 終止爬蟲 |
3.4 核心注解:PageSelect
功能:描述頁面數據對象,通過該注解從頁面抽取PageVo數據信息,可選屬性如下。
PageSelect | 說明 |
---|---|
cssQuery | CSS選擇器, 如 "#body" |
3.5 核心注解:PageFieldSelect
功能:描述頁面數據對象的屬性信息,通過該注解從頁面抽取PageVo的屬性信息,可選屬性如下。
(支持基礎數據類型 T ,包括 List
PageFieldSelect | 說明 |
---|---|
cssQuery | CSS選擇器, 如 "#title" |
selectType | jquery 數據抽取方式,如 ".html()/.text()/.val()/.attr()"等 |
selectVal | jquery 數據抽取參數,SelectType=ATTR 時有效,如 ".attr("abs:src")" |
datePattern | 時間格式化,日期類型數據有效 |
3.6 多線程
以線程池方式並行運行,提供對應API(可參考"章節3.3")調整線程池大小,提高運行效率;
3.7 異步
支持同步、異步兩種方式啟動運行。
- 同步:將會阻塞業務邏輯,爬蟲爬取完全部頁面后才會繼續執行后續邏輯。
- 異步:不會阻塞業務邏輯,爬蟲邏輯以異步方式運行。
3.8 動態代理
ProxyMaker(代理生成器):實現代理支持的組件。支持設置代理IP,同時支持調整代理池實現動態代理;
系統已經提供了兩種策略實現;
- RoundProxyMaker(循環代理生成器): 以循環方式獲取代理池中代理;
- RandomProxyMaker(隨機代理生成器): 以隨機方式獲取代理池中代理;
3.9、PageParser
PageParser(頁面解析器):綁定泛型PageVO后將會自動抽取頁面數據對象,同時支持運行時調整請求參數信息;
內部方法 | 說明 |
---|---|
public void preParse(PageRequest pageRequest) | 可選實現,發起頁面請求之前觸發調用,可基於此運行時調整請求參數; |
public abstract void parse(Document html, Element pageVoElement, T pageVo) | 必須實現,頁面抽離封裝每個PageVO之后觸發調用,可基於此處理PageVO文檔或數據; |
3.10、分布式支持 & RunData
支持自定義RunData(運行時數據模型)並結合Redis或DB共享運行數據來實現分布式爬蟲。默認提供LocalRunData實現單機版爬蟲。
- RunData:運行時數據模型,維護爬蟲運行時的URL和白名單規則。
- 單機:單機方式維護爬蟲運行數據,默認提供 "LocalRunData" 的單機版實現。
- 分布式/集群:集群方式維護爬蟲爬蟲運行數據,可通過Redis或DB定制實現。
RunData抽象方法 | 說明 |
---|---|
public abstract boolean addUrl(String link); | 新增一個待采集的URL,接口需要做URL去重,爬蟲線程將會獲取到並進行處理; |
public abstract String getUrl(); | 獲取一個待采集的URL,並且將它從"待采集URL池"中移除,並且添加到"已采集URL池"中; |
public abstract int getUrlNum(); | 獲取待采集URL數量; |
3.11、JS動態渲染 & PageLoader
頁面數據通過 "PageLoader" 組件加載,默認使用以下兩種實現:
- JsoupPageLoader:速度最快,推薦采用這種方式(不支持JS動態渲染);
- HtmlUnitPageLoader:支持JS動態渲染;
- SeleniumPhantomjsPageLoader:支持JS動態渲染,"selenisum + phantomjs" 方案,兼容性較高;
得益於模塊化結構設計,可自由擴展其他 "PageLoader" 實現,如 "selenisum + chrome/headless" 方式等;
注意:
- 1、HtmlUnitPageLoader 為擴展功能,因此maven依賴(htmlunit)scope為provided類型,使用時請單獨引入;
- 2、SeleniumPhantomjsPageLoader 為擴展功能,因此maven依賴(selenisum + phantomjs)scope為provided類型,使用時請單獨引入;
- 3、JS渲染方式采集數據實用性廣,但是也存在缺點,如下:
- 2.1:JS渲染,速度較慢;
- 2.1:JS渲染,環境要求較高;
- 2.3:在需要JS渲染的場景下,推薦做法是:分析頁面請求,模擬並主動發起Ajax請求來代替JS引擎自動請求渲染。因為速度更快,更可控;
四、版本更新日志
版本 V1.0.0,新特性[2017-09-13]
- 1、面向對象:通過VO對象描述頁面信息,提供注解方便的映射頁面數據,爬取結果主動封裝Java對象返回;
- 2、多線程:線程池方式並行運行;
- 3、異步:支持同步、異步兩種方式運行;
- 4、擴散全站:支持以入口URL為起點擴散爬取整站;
- 5、去重:防止重復爬取;
- 6、URL白名單:支持設置頁面白名單正則,過濾URL;
- 7、自定義請求信息,如:請求參數、Cookie、Header、UserAgent輪詢、Referrer等;
- 8、輕量級:底層實現僅依賴jsoup,簡潔高效;
- 9、超時控制:支持設置爬蟲請求的超時時間;
- 10、主動停頓:爬蟲線程處理完頁面之后進行主動停頓,避免過於頻繁被攔截;
- 11、單個頁面支持抽取一個或多個PageVO;
版本 V1.1.0,新特性[2017-11-08]
- 1、頁面默認cssQuery調整為html標簽;
- 2、升級Jsoup至1.11.1版本;
- 3、修復PageVO注解失效的問題;
- 4、屬性注解參數attributeKey調整為selectVal;
- 5、代理IP:對抗反采集策略規則WAF;
- 6、動態代理:支持運行時動態調整代理池,以及自定義代理池路由策略;
版本 V1.2.0,新特性[2017-12-14]
- 1、爬蟲Builder底層API優化;
- 2、支持設置請求Headers;
- 3、支持設置多UserAgent輪詢;
- 4、失敗重試:支持請求失敗后主動重試,並支持設置重試次數;
- 5、動態參數:支持運行時動態調整請求參數;
- 6、分布式支持:支持自定義RunData(運行時數據模型)並結合Redis或DB共享運行數據來實現分布式。默認提供LocalRunData單機版爬蟲。
版本 V1.2.1,新特性[2018-02-07]
- 1、JS渲染:支持JS渲染方式采集數據,可參考 "爬蟲示例6";
- 2、抽象並設計PageLoader,方便自定義和擴展頁面加載邏輯,如JS渲染等。底層提供 "JsoupPageLoader(默認/推薦)","HtmlUnitPageLoader"兩種實現,可自定義其他類型PageLoader如 "Selenium" 等;
- 3、修復Jsoup默認加載1M的限制;
- 4、爬蟲線程中斷處理優化;
版本 V1.2.2,新特性[2018-10-24]
- 1、系統底層重構,規范包名;
- 2、采集線程白名單過濾優化,避免冗余失敗重試;
- 3、增強JS渲染方式采集能力,原生新提供 "SeleniumPhantomjsPageLoader",支持以 "selenisum + phantomjs" 方式采集頁面數據;
- 4、支持采集非Web頁面,如JSON接口等,直接輸出響應數據;選擇 "NonPageParser" 即可;
版本 V1.3.0,新特性[迭代中]
- 1、[ING]增強JS渲染采集能力,原生提供 "selenium chrome headless" 方案實現,並提供開箱即用的 PageLoader ;
- 2、[ING]進一步優化 selenium 特性兼容問題;
TODO LIST
- 1、擴展SelectType;
- 2、協程,擱置,jsoup/htmlunit/selenisum協程兼容性低;
- 3、bloomfilter去重,可選接入,大數據量下推薦;
- 4、對抗爬蟲蜜罐,成功率檢測,歷史數據學習;
- 5、對抗主動休眠防御,Timeout即可;
- 6、頁面生僻字中文亂碼處理;
五、其他
5.1 項目貢獻
歡迎參與項目貢獻!比如提交PR修復一個bug,或者新建 Issue 討論新特性或者變更。
5.2 用戶接入登記
更多接入的公司,歡迎在 登記地址 登記,登記僅僅為了產品推廣。
5.3 開源協議和版權
產品開源免費,並且將持續提供免費的社區技術支持。個人或企業內部可自由的接入和使用。
- Licensed under the GNU General Public License (GPL) v3.
- Copyright (c) 2015-present, xuxueli.
捐贈
無論金額多少都足夠表達您這份心意,非常感謝 :) 前往捐贈