優雅的使用WebMagic框架,爬取唐詩別苑網的詩人詩歌數據html
同時在幾種動態加載技術(HtmlUnit、PhantomJS、Selenium、JavaScriptEngine)中對比做選擇jquery
WebMagic雖然差很少兩年沒有維護,但其自己是一個優秀的爬蟲框架的實現,源碼中有不少值得參考的地方,特別是對爬蟲多線程的控制。另外,因爲頁面爬取到的是非結構化數據,因此數據保存到MongoDB。
涉及技術:git
pom.xml文件中的依賴很是簡單,並無使用到Spring系列的框架,因此有些地方本身編碼實現了Spring提供的功能
根據需求將數據保存到MongoDB數據庫,所以在程序運行前必須設置好resources/mongodb.properties
文件github
最好保證MongoDB的版本是4.0以上。另外MongoDB的用戶管理比較麻煩,過程大體以下:首先須要建立存儲數據的數據庫,如命名爲user_tangpoem,並存入隨便一條數據(集合)使數據庫有效化,而後建立一個
admin數據庫的root用戶,繼續建立一個能夠讀寫應用數據庫user_tangpoem的用戶,而後修改MongoDB配置文件使其以安全認證模式啓動。重啓數據庫,選擇admin數據庫(use admin)
用剛剛建立的用戶(非root用戶)使用db.auth()進行登陸,返回1說明驗證成功,選擇user_tangpoem數據庫(use user_tangpoem),輸入show collections,若是看到最初建立數據庫時的集合,則說明用戶建立成功。
詳細可參考 MongoDB4.0.0 遠程鏈接及用戶名密碼認證登錄配置——windows
爬蟲以多線程的方式運行,在resources/spider.properties
文件中能夠設置線程數和線程睡眠時間,在設置好數據庫配置的基礎上,直接運行Main.main(),爬蟲就會開始爬取。web
線程睡眠,是WebMagic框架源碼中每線程爬取完一個url後必然經歷的過程,但做者文檔並無對此進行說明,請根據實際狀況調整
WebMagic底層已經很好的使用了HttpClient加載靜態頁面,對於動態頁面,也有PhantomJSDownloader和SeleniumDownloader兩個經常使用的利用
瀏覽器內核模擬瀏覽器行爲的實現,其中,PhantomJS須要指定phantomjs.exe和進行爬取的JS文件,而seleniumDownloader須要指定chromedriver.exe,須要自行下載對應操做系統的版本,
使用起來並不難,本項目很少做討論。這裏關鍵說明HtmlUnitmongodb
一款開源的Java頁面分析工具,讀取頁面後,能夠有效的使用HtmlUnit分析頁面上的內容。使用純Java實現的模擬瀏覽器,不須要指定外部文件。chrome
雖然其對JS的支持並不徹底,但整體而言HtmlUnit的內存消耗、CPU消耗和效率都比PhantomJS和Selenium好,值得進行使用數據庫
本項目使用2.25版本的HtmlUnit並無出現JS加在不成功的問題,但使用2.3x的版本會沒法加載
由於JavaScriptEngine是有侷限性的,最明顯就是其不支持jquery的語法,由於jquery使用了瀏覽器內置的對象,而JS引擎自己是沒有瀏覽器對象的windows
固然能夠,只要分析過頁面的加載邏輯,若是不涉及瀏覽器對象的使用,或者將JS邏輯進行轉化,仍是可以使用JS引擎的,但犧牲了泛用性。本項目經分析後使用JS引擎加載瀏覽器
通過測試,三者比較以下
PhantomJS使用外置的程序,因此JVM沒法管理這部分的硬件資源,須要打開任務管理器
通過分析,爬取步驟分爲4步:
顯然,如上描述,採用的是寬度優先遍歷,因此當執行到第3步時,纔會有數據入庫優化後使用Java8的nashorn JS引擎執行JS代碼,不須要動態加載JS,因此不會出現4的問題
根據爬取過程分析,忽略程序啓動時間和調用獲取詩人id接口的時間
在開啓8線程的併發模式下(使用HtmlUnit進行動態加載):
一共須要: 2529 / 8 5 + 48000 (1 + 0.01)/ 8 * 10 ≈ 62596秒 ≈ 1043分鐘 ≈ 17.4小時
上述數據是在本地測試中獲得的,配置爲 win10 8G i5-4210M 4核
優化後,用JS引擎取代模擬瀏覽器動態加載JS,獲取詩歌信息的耗時明顯縮短,由10秒縮短到6秒左右,所以從新計算耗時以下:
2529 / 8 5 + 48000 / 8 6 ≈ 37185秒 ≈ 620分鐘 ≈ 10.3小時
當使用模擬瀏覽器動態加載JS時,觀察JVM的使用狀況,發現爬取詩歌階段頻繁發生Minor GC(新生代GC),差很少10秒一次,以下圖所示,
後判明是多線程模擬瀏覽器加載頁面行爲很是的耗內存(參考同時打開8個瀏覽器加載網頁),對象頻繁建立,頻繁消耗,
建議運行時經過-Xms -Xmx把JVM內存設置得大些,至少1G,而後把新生代的比例設大,如-Xms2048M -Xmx2048M -XX:+UseParallelOldGC -XX:NewRatio=1
後來,用JS引擎取代模擬瀏覽器動態加載JS,不只速度獲得明顯提高,並且內存的消耗大幅度下降,Minor GC平均1分鐘發生一次,以下圖所示,
最後附上GitHub項目地址:https://github.com/Kanarienvogels/spider-tangpoem