一套簡單的java爬蟲框架VW-Crawler釋出啦!!!
VW-Crawler
背景
自己一直對爬蟲比較感興趣,大學的畢業論文也是一個爬蟲專案(爬教務處資訊,然後做了個Android版教務管理系統,還獲得了優秀畢業設計的稱號),自那以後遇到自己感興趣的網站就會去抓一下。前段時間工作上需要一些JD資訊,我就從網上找了個開源的爬蟲框架WebMagic,使用簡單,易配置,功能也很強大,當然了也有些網站的資料不適合使用。前前後後寫了不下十幾個,慢慢的就想是不是可以把這些爬蟲程式碼再抽象出來,做出一個簡易的爬蟲框架呢?於是就嘗試去看WebMagic的原始碼,後來又發現了一個原始碼比較容易解讀的爬蟲框架XXL-CRAWLER,簡單的分析了原始碼之後,開發自己一套爬蟲框架的慾望更加強烈,於是在2017年底的時候就開始了開發,中間斷斷續續得停了寫,寫了停。直到最近8月底的時候才算出了一個版本,然後順勢把它放到了Maven公服倉庫上。一個人的力量很薄弱,要想完善這個爬蟲的健壯性、可用性和易擴充套件性還需要大家的力量!
特點
- 語言: Java開發,框架比較簡單,多處使用的是介面程式設計,是學習Java不錯的例子
- 難度: 及其簡單,配置一下,寫個解析邏輯,整理下儲存方法,就OK了
- 輕量: 使用Jsoup做預設的下載器,依賴性較低
- 執行緒: 可自主設定執行緒數抓取,提高抓取效率
- 重試: 支援失敗重試,次數可以自定義
- 代理: 支援配置代理池,預設隨機使用代理IP,也可自定義演算法獲取
- 去重: 雙重去重,預設對URL去重,也可以定義第二層去重邏輯
- 控制: 可自主控制是否需要解析頁面,減少資源的使用
- 精準: 通過設定URL的正則來精準的解析每一個URL
- 擴充套件: 幾乎每一個環節都可以自定義
使用
使用Maven
<dependency>
<groupId>com.github.vector4wang</groupId>
<artifactId>vw-crawler</artifactId>
<version>${last.version}</version>
</dependency>
離線使用
可以在專案主頁的release下載最新版本jar,然後匯入自己的專案中。
步驟
- 配置引數
- 抽象正則
- 解析頁面
- 儲存資料
各環節均支援自定義
示例
抓取CSDN某使用者的部落格內容
設定爬蟲的基本配置,如User-Agent、起始地址、目標頁面的url正則表示式、執行緒數和超時時間等
new VWCrawler.Builder()
// 配置引數
.setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36") // 設定請求頭
.setUrl("https://blog.csdn.net/qqhjqs") // 設定爬蟲起始地址
.setThreadCount(10) // 設定幾個執行緒抓取資料
.setTimeOut(5000) // 設定超時時間
// 抽象正則
.setTargetUrlRex("https://blog.csdn.net/qqhjqs/article/details/[0-9]+") // 設定目標頁面url的正則表示式
// 解析頁面
.setPageParser(new CrawlerService<Blog>() {
/**
* 有的url可能在某個場景下不需要可在此處理
* 預設返回false,可以不做處理
* @param url 即將要抓取的url
* @return
*/
@Override
public boolean isExist(String url) {
if ("https://blog.csdn.net/qqhjqs/article/details/79101846".equals(url)) {
return true;
}
return false;
}
/**
* 有的頁面有WAF,可以再真正解析前,做個判斷,遇到特殊標誌的直接可以跳過
* 預設返回true,可以不做處理
* @param document 即將要解析的document
* @return
*/
@Override
public boolean isContinue(Document document) {
if ("最近和未來要做的事 - CSDN部落格".equals(document.title())) {
System.out.println("模擬遇到WAF此頁面不做解析");
return false;
}
return true;
}
/**
* 目標頁面的doc物件,還有通過註解處理後的物件
* @param doc 文件內容
* @param pageObj 封裝的物件
*/
@Override
public void parsePage(Document doc, Blog pageObj) {
// 可進行二次處理
pageObj.setReadNum(pageObj.getReadNum().replace("閱讀數:", ""));
}
// 儲存資料
/**
* 可以做儲存物件的處理
* @param pageObj 頁面物件
*/
@Override
public void save(Blog pageObj) {
System.out.println("save blog summery: " + pageObj.toString());
}
}) // 自定義解析service
.build().start(); // 啟動
配置頁面資料物件的註解
@CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-title-box > h1", resultType = SelectType.TEXT)
private String title;
@CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-info-box > div > span.time", dateFormat = "yyyy年MM月dd日 HH:mm:ss")
private Date lastUpdateDate;
@CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-info-box > div > div > span", resultType = SelectType.TEXT)
private String readNum;
這裡使用比較流行的註解方式,通過cssselector來獲取節點資料可通過resultType來指定填充的是text還是html。
隨便配置一下,就能抓取一個頁面的資料
new VWCrawler.Builder().setUrl("https://www.qiushibaike.com/").setPageParser(new CrawlerService() {
@Override
public void parsePage(Document doc, Object pageObj) {
System.out.println(doc.toString());
}
@Override
public void save(Object pageObj) {
}
}).build().start();
更多
更多的示例可移步more
抓取了足夠多的資料,我們可以拿資料做很多事,比如統計各大人才網的職位分佈圖
有關ES的可移步這裡
最後
輪子造多了就想著造一個模具,程式碼寫多了就想寫個框架,一樣的道理。幫助他人,順便提升自己。框架還有很多需要完善的地方,希望使用者多多提issue,也希望大家提PR~~~