不久前使用 webMagic開發了一款爬蟲
爬取對象爲四川政務網,使用JFinal持久化數據
如果你正在學習爬蟲,或者業務與我類似,那麼你可以下載源碼學習
也可向我提出改進意見
參考源碼:在這裏
列表頁:
http://www.sczwfw.gov.cn/app/index?flag=2&areaCode=510000000000
抓取頁:
http://www.sczwfw.gov.cn/app/scworkguide/detail?id=3952148991995600896&shardKey=5100
簡單講下系統設計,具體的請參考代碼
目錄結構
entity 網頁字段對應的實體類
main 爬蟲入口
utils 工具類
Admin : 對所有提取到的數據進行集中管理
UrlCache: 網頁緩存的抽象
生命週期
如圖所示,保存數據只是附屬的流程
鏈接發現
這是爬蟲的開始,對鏈接進行發現和更新
例如:已經抓取了500個成都的事項,但是現在需要更新500個事項爲其他地區的
按照生命週期,你需要在這裏重新更新鏈接
在這一步,我們需要確認要抓取的網頁是哪些,並觀察網頁是否有對外暴露的查詢接口,經過調試,找到了這個接口:
http://mss.sczwfw.gov.cn/app/powerDutyList/getThImplement
他支持的參數:
eventNam: 事項名稱
areaCode : 區域碼
eventType : 行政類型
打開PostMan測試接口,並查看返回參數:
它返回了事項的基本信息,其中還有父級事項的名稱
循環調用這個接口,然後將其返回的數據進行保存,具體請參考utils包下的InsertItems類,看我如何抽離數據
將其保存至數據庫
OOSpider
當數據準備就緒,需要使用OOSpider類進行網頁數據抓取
OOSpider是註解式爬蟲的入口,有這些方法
方法
getCollectorPipeline() : 看了下源碼,這個和AfterExtractor接口的功能一樣,都是在運行時返回數據抽取結果。建議使用AfterExtractor接口,面向接口編程嘛
兩個create方法: 對構造方法的簡單封裝,因爲構造方法是protected!
addPageModel(): 文檔
setIsExtractLinks(): 是否提取網頁鏈接
這個需要搭配TargetUrl與HelpUrl註解使用,本質就是鏈接發現.我們已經發現過了,所以設置爲false
具體的你可以看ModelPageProcessor源碼
TargetUrl和HelpUrl註解文檔
入參
ModelPageProcessor : 註解網頁對象 在網頁抓取章節裏詳解介紹
PageProcessor: 普通網頁對象 這個是給傳統方式使用的,看 這裏
Site : http請求對象 , http嘛肯定是配置cookies、header、超時時間、重試次數等等...亂七八糟參數的地方
PageModelPipeline : 看 文檔
網頁抓取
下面我分成兩個部分講述
1. 創建OOSpider時 發生了什麼
2.如何設計映射關係(實體類)
先看一段代碼:
public class GithubRepo {
@ExtractBy("//div[@id='readme']/tidyText()")
private String readme;
public static void main(String[] args) {
OOSpider.create(Site.me().setSleepTime(1000)
, GithubRepo.class)
.addUrl("https://github.com/code4craft").thread(5).run();
}
}
這段代碼描述了:
1 . GithubRepo 擁有的字段readme 被@ExtractBy 註釋,它的抽取規則爲//div[@id='readme']/tidyText()
2.創建一個爬蟲 OOSpider.create()
3. 爬蟲傳入了兩個類 : Site類 和 擁有抽取規則的類
4.使用addUrl(),規定了抓取的頁面
5.創建線程並運行
代碼內部過程:
1.將Url pull 到 Scheduler 接口
2.初始化組件:
創建HttpClient、創建線程池、通過Scheduler獲取Request集合
3.請求頁面
4.抽取數據 ,被@ExtractBy註釋的字段都會被PageModelExtractor類,注入對應數據
5.存放數據
存放的數據有二種方式獲取
一。Pipeline 接口 可在線程運行和結束時可獲取數據
二。AfterExtractor接口 單個線程結束時 可獲取數據,我使用這種方式保存數據
回到我們代碼本身,肯定不能將需要抓取的字段和接口實現放置到一起,但是數據要統一管理
Admin類正是爲此而設計
它繼承了擁有@ExtractBy註解的實體類,同時要求實現類需要實現AfterExtractor類的方法
Laws類圖:
在程序入口,需要繼承Admin類,實現afterProcess方法
數據拼裝
實現afterProcess方法後,爲我們傳過來一個Page對象,這裏面的數據爲:實體類@ExtractBy規則抓取的數據
當拿到數據後,就可以按照你自己的業務,進行處理了,比如像這樣
感想
隨着業務的增加,勢必需要監控爬蟲,實現前後端交互
現在有兩種監控方式
一.通過JConsole
二 繼承 SpiderStatusMXBean
這個還是比較不錯的,可以取到錯誤網頁 還支持啓動和停止