前言
防砸聲明:此文僅僅能保證入門,不保證商業(yè)生產(chǎn)。
引用錢洋博士課程的部分內(nèi)容(有刪改):
網(wǎng)絡(luò)爬蟲技術(shù),有效的獲取網(wǎng)絡(luò)數(shù)據(jù)資源的重要方式。簡單的理解,比如您對百度貼吧的一個(gè)帖子內(nèi)容特別感興趣,而帖子的回復(fù)卻有1000多頁,這時(shí)采用逐條復(fù)制的方法便不可行。而采用網(wǎng)絡(luò)爬蟲便可以很輕松地采集到該帖子下的所有內(nèi)容。
網(wǎng)絡(luò)爬蟲的作用,我總結(jié)為以下幾點(diǎn):
- 輿情分析:企業(yè)或政府利用爬取的數(shù)據(jù),采用數(shù)據(jù)挖掘的相關(guān)方法,發(fā)掘用戶討論的內(nèi)容、實(shí)行事件監(jiān)測、輿情引導(dǎo)等。
- 企業(yè)的用戶分析:企業(yè)利用網(wǎng)絡(luò)爬蟲,采集用戶對其企業(yè)或商品的看法、觀點(diǎn)以及態(tài)度,進(jìn)而分析用戶的需求、自身產(chǎn)品的優(yōu)劣勢、顧客抱怨等。
- 科研工作者的必備技術(shù):現(xiàn)有很多研究都以網(wǎng)絡(luò)大數(shù)據(jù)為基礎(chǔ),而采集網(wǎng)絡(luò)大數(shù)據(jù)的必備技術(shù)便是網(wǎng)絡(luò)爬蟲。利用網(wǎng)絡(luò)爬蟲技術(shù)采集的數(shù)據(jù)可用于研究產(chǎn)品個(gè)性化推薦、文本挖掘、用戶行為模式挖掘等。
按照陳樹義前輩在《聊聊整體性學(xué)習(xí)方法》一文中提到的思想,本文思路如下:
獲取:目前都有哪些爬蟲技術(shù)?
理解:這些爬蟲技術(shù)的特色是什么?
擴(kuò)展:快速上手一下cdp4j爬蟲技術(shù)。
糾錯(cuò):解析網(wǎng)頁過程中踩過的坑與填坑之路。
應(yīng)用:實(shí)戰(zhàn)爬取網(wǎng)易新聞評論內(nèi)容。
正文
一、目前都有哪些爬蟲技術(shù),及其特色都是什么?
? 先說一句我不是專業(yè)搞爬蟲的,從2019-07-06到2019-07-11累計(jì)學(xué)習(xí)5天。這篇文章是對我這5天學(xué)習(xí)的總結(jié)。以我淺顯的了解,在此我列出我曾經(jīng)嘗試過后來又放棄了的框架,最后壓軸(zhoù)再寫我正在使用的框架。目前有以下流行的爬蟲框架技術(shù):
- Apache Nutch(高大上)
Nutch這個(gè)框架運(yùn)行需要Hadoop,Hadoop需要開集群,對于想要快速入門爬蟲的我是望而卻步了......
一些資源地址列在這里,說不定以后會(huì)學(xué)習(xí)呢。
- Crawler4j(感覺很強(qiáng))
從它的包名上可以看出這個(gè)框架來自加州大學(xué)歐文分校。我下載下來Demo運(yùn)行了一下,感覺很強(qiáng)!但他的官方文檔介紹很簡潔,Demo只是運(yùn)行了一下沒看懂怎么用。之所以感覺很強(qiáng),是看見了好的厲害的API,當(dāng)然也有一些加州大學(xué)的名氣影響。
- WebMagic(國產(chǎn))
根據(jù)網(wǎng)上介紹,這個(gè)框架產(chǎn)自曾就職于大眾點(diǎn)評的黃億華大佬,但是,無論GitHub還是碼云上這個(gè)倉庫已經(jīng)兩年沒有更新了,其中有一個(gè)致命的“Bug”,不能爬https的鏈接。作者在GitHub的issue中明確說明會(huì)在下一個(gè)版本(0.7.4)中修復(fù)此“Bug”,但是,兩年過去了,依然沒有發(fā)布下一個(gè)版本,截止2019年7月11號,GitHub上依然是0.7.3版本,可能作者遇到了某種不可抗拒力量,導(dǎo)致無法維護(hù)下去。下圖來自GitHub issues
- Spiderman2(國產(chǎn))
這個(gè)聽名字就挺霸氣的,和蜘蛛俠電影齊名。我也是下載下來Demo運(yùn)行了一下,但是運(yùn)行啥啥報(bào)錯(cuò)......
而且官方庫也沒有提供文檔。
但是,之所以列出來這個(gè)庫,是因?yàn)樽髡咴诖a云的issue中現(xiàn)場教學(xué)感動(dòng)了我。
- WebController(國產(chǎn)·合肥工業(yè)大學(xué))
當(dāng)我根據(jù)這個(gè)庫的包名搜索出合肥工業(yè)大學(xué)時(shí),心中只有兩個(gè)字:牛X!
維護(hù)這個(gè)庫的兄弟還煞費(fèi)苦心的把README.md全英文書寫。不過同樣是因?yàn)槲臋n過于簡陋。Demo運(yùn)行了幾個(gè),不知道運(yùn)行出來個(gè)啥。
之所以貼出來這個(gè),確實(shí)是因?yàn)樗贕itHub上2000+star震驚到我了,同樣身為大學(xué)生的我,求學(xué)三年,毫無產(chǎn)出,甚是慚愧。定當(dāng)以前輩勵(lì)志,再加努力。
- HtmlUnit(經(jīng)典·適合靜態(tài)網(wǎng)頁)
這個(gè)框架堪稱經(jīng)典,也是我們暑期實(shí)訓(xùn)老師講解的框架。有近乎完整的文檔介紹。
但是,HtmlUnit中webClient.getPage("url")只能get到靜態(tài)網(wǎng)頁內(nèi)容。但是,當(dāng)今世界,靜態(tài)網(wǎng)頁已經(jīng)寥寥可數(shù)了,大都是與后臺交互的動(dòng)態(tài)網(wǎng)頁,很多數(shù)據(jù)都是經(jīng)過后臺獲取,渲染之后才能呈現(xiàn)在網(wǎng)頁上。據(jù)我5天淺顯的學(xué)習(xí),發(fā)現(xiàn)單純的HtmlUnit無法爬取動(dòng)態(tài)網(wǎng)頁內(nèi)容。
大家可以試一下,打開一篇網(wǎng)易新聞,然后右鍵查看源代碼,你會(huì)發(fā)現(xiàn),你所看到的頁面和源代碼內(nèi)容并不是一一對應(yīng)的。
- Jsoup(經(jīng)典·適合靜態(tài)網(wǎng)友)
這個(gè)框架堪稱經(jīng)典,也是我們暑期實(shí)訓(xùn)老師講解的框架。有近乎完整的文檔介紹。
和HtmlUnit同樣,只能get到靜態(tài)內(nèi)容。
不過,這個(gè)框架有個(gè)有個(gè)優(yōu)點(diǎn),具有很強(qiáng)大的解析網(wǎng)頁的功能。
- selenium(Google多名大佬參與開發(fā))
感覺很厲害,實(shí)際真的很厲害,看官網(wǎng)以及其他人的介紹,說是真正模擬瀏覽器。GitHub1.4w+star,你沒看錯(cuò),上萬了。但是我硬是沒配好環(huán)境。入門Demo就是沒法運(yùn)行成功,所以就放棄了。
- cdp4j(今天的主角)
使用前提:
安裝Chrome瀏覽器,即可。
簡單介紹:
HtmlUnit的優(yōu)點(diǎn)在于,可以方便的爬取靜態(tài)網(wǎng)友;缺點(diǎn)在于,只能爬取靜態(tài)網(wǎng)頁。
selenium的優(yōu)點(diǎn)在于,可以爬取渲染后的網(wǎng)頁;缺點(diǎn)在于,需要配環(huán)境變量等等。
將二者整合,取長補(bǔ)短,就有了cdp4j。
之所以選用它,是因?yàn)檎娴姆奖愫糜茫夜俜轿臋n詳細(xì),Demo程序基本都能跑起來,類名起的見名知意。想當(dāng)年學(xué)軟件工程的時(shí)候,一直在納悶,為什么要寫文檔啊,我程序能實(shí)現(xiàn)功能不就得了?現(xiàn)如今,看著如此詳實(shí)的文檔,留下了激動(dòng)而又悔恨的淚水......
cdp4j有很多功能:
a. 獲得渲染后的網(wǎng)頁源碼
b. 模擬瀏覽器點(diǎn)擊事件
c. 下載網(wǎng)頁上可以下載的文件
d. 對網(wǎng)頁進(jìn)行截屏或轉(zhuǎn)PDF打印
e. 等等
更多詳細(xì)信息可以自行去如下三個(gè)地址中探索發(fā)現(xiàn):
小結(jié)
我在正文列出了9個(gè)爬蟲框架。有強(qiáng)如Apache、Google大佬開發(fā)維護(hù),也有諸如我國合肥工業(yè)大學(xué)學(xué)生的作品。其實(shí)各有各自的特色,弱水三千,我想全喝,但沒有那個(gè)能力。所以目前只飲一瓢,就是cdp4j了。
二、快速上手一下cdp4j爬蟲技術(shù)
首先,再強(qiáng)調(diào)一點(diǎn):使用前提是安裝了Chrome瀏覽器
當(dāng)然,不能憑空使用,還需要Maven依賴
<dependency>
<groupId>io.webfolder</groupId>
<artifactId>cdp4j</artifactId>
<version>3.0.12</version>
</dependency>
<!-- 2.2.1 版本的cdp4j不用導(dǎo)入winp;3.0+ 版本的cdp4j需要導(dǎo)入此包 -->
<!-- https://mvnrepository.com/artifact/org.jvnet.winp/winp -->
<dependency>
<groupId>org.jvnet.winp</groupId>
<artifactId>winp</artifactId>
<version>1.28</version>
</dependency>
先看一下官網(wǎng)給出的HelloWorld
看出來我貼的是一張圖片了嗎?所以先別著急敲,因?yàn)檫@個(gè)程序還需要稍作修改,如下:
import io.webfolder.cdp.Launcher;
import io.webfolder.cdp.session.Session;
import io.webfolder.cdp.session.SessionFactory;
import static java.util.Arrays.asList;
public class HelloWorld {
public static void main(String[] args) {
Launcher launcher = new Launcher();
try (SessionFactory factory = launcher.launch(asList("--disable-gpu",
"--headless"))) {
String context = factory.createBrowserContext();
try (Session session = factory.create(context)) {
// 設(shè)置要爬的網(wǎng)站鏈接,必須要有http://或https://
session.navigate("https://www.baidu.com");
// 默認(rèn)timeout是10*1000 ms,也可以像下面這樣手動(dòng)設(shè)置
session.waitDocumentReady(15 * 1000);
// 通過session得到渲染后的html內(nèi)容
String html = session.getContent();
System.out.println(html);
}// session創(chuàng)建結(jié)束
// 處理瀏覽器上下文,源碼:contexts.remove(browserContextId)
// 意思應(yīng)該是將后臺瀏覽器進(jìn)程關(guān)閉
// 我曾經(jīng)嘗試將此舉注釋,只保留下面的launcher.getProcessManager().kill();
// 依然可以關(guān)閉后臺進(jìn)程,但是官方給的代碼有這句,那就帶著吧,或許有其他作用。
factory.disposeBrowserContext(context);
}// factory創(chuàng)建結(jié)束
// 真正的關(guān)閉后臺進(jìn)程
launcher.getProcessManager().kill();
}// main方法結(jié)束
}
上面的代碼你可以手動(dòng)敲一遍,當(dāng)然一般都是復(fù)制粘貼的。
與截圖不同的是:
這里的factory和session是在兩個(gè)不同的try-with-resource語句中創(chuàng)建的,
創(chuàng)建factory時(shí)多了一句 asList("--disable-gpu","--headless") 這個(gè)作用就是不啟用GPU加速,不彈出瀏覽器
在最后對BrowserContex以及l(fā)auncher進(jìn)行了關(guān)閉操作以達(dá)到回收內(nèi)存的目的。
大家如果不理解這段代碼的作用,可以自行運(yùn)行一下兩種代碼,然后打開任務(wù)管理器,查看IDEA進(jìn)行下的子進(jìn)程。
運(yùn)行結(jié)束后再看一下任務(wù)管理器,如果執(zhí)行了關(guān)閉操作,那么IDEA下的子進(jìn)程會(huì)被關(guān)閉,否則,有兩種情況:
創(chuàng)建factory時(shí)候,沒有加上 asList("--disable-gpu","--headless") 這樣會(huì)彈出一個(gè)Chrome瀏覽器,需要手動(dòng)進(jìn)行關(guān)閉
創(chuàng)建factory時(shí)候,加上了 asList("--disable-gpu","--headless") 這樣IDEA進(jìn)程的子進(jìn)程,也就是上圖的Google Chrome會(huì)駐留在后臺,占據(jù)內(nèi)存資源。
小結(jié)
? 說白了,cdp4j就是一個(gè)模擬瀏覽器,區(qū)別于HtmlUnit,這里是真的用到了瀏覽器,如果代碼寫的不對,還會(huì)彈出瀏覽器,嚇你一跳 : )
? 目前只是簡簡單單的獲取到了渲染后的html,真正的爬蟲可不僅僅就這。
三、解析網(wǎng)頁過程中踩過的坑與填坑之路
- 啥是xPath?
詳細(xì)介紹可以參考W3cSchool XPath 簡介 或者 Runoob XPath 簡介
我在這里簡單總結(jié)一下:xPath是用來遍歷DOM樹的。
你要是敢問我啥是DOM樹,我可就舉起來拖鞋抽你了 : ) 哈哈,開玩笑,同樣也是看一下W3CSchool HTML DOM 簡介 或者 Runoob HTML DOM 簡介
- 如何快速獲取一個(gè)節(jié)點(diǎn)的xPath?
我們暑期實(shí)訓(xùn)老師是按下F12,然后找到對應(yīng)節(jié)點(diǎn),再從上到下一個(gè)一個(gè)的數(shù)出來的xPath。
第一次見這樣操作的時(shí)候,由于新鮮感過于強(qiáng)烈,所以也就沒有感到有多麻煩。不過,數(shù)的次數(shù)多了,總覺得這樣不行。應(yīng)該有更快更好的方法獲取xPath。
還記得SpiderMan2嗎?自風(fēng)老師在碼云的issue里面親身教學(xué):Chrome獲取XPath的方法
整了半天,原來人家Chrome瀏覽器早就替我們實(shí)現(xiàn)好了,就知道我們要用到xPath干壞事。
- xPath具體怎么用?
自風(fēng)老師教的copy xPath直接用的話,只能是一個(gè)節(jié)點(diǎn)。
實(shí)際上,有時(shí)候我們需要一次性拿到很多節(jié)點(diǎn),比如說xPath路徑都是div/p,這時(shí)候我們可以寫成“//div/p”,又有時(shí)候,我們需要拿到指定class的div下的p,那么語法就是“//div[@class='classname']/p”
更詳細(xì)的用法可以參考 Runoob XPath 語法
- 怎樣快速解析一個(gè)html,拿到想要的內(nèi)容?
雖說cdp4j自帶xPath解析功能,但要說解析html,還要屬Jsoup最專業(yè):Jsoup中文教程
Jsoup支持xPath和CSS選擇器,學(xué)前端的同學(xué)看到CSS選擇器應(yīng)該會(huì)很激動(dòng)吧,我頭一次看到內(nèi)心是:竟然還有這種操作!
小結(jié)
? xPath、Jsoup這些新名詞,很多人(比如我)大學(xué)上了3年,還是頭一次聽說,所以需要一些時(shí)間去接近,熟悉最終才能掌握。
四、實(shí)戰(zhàn)爬取網(wǎng)易新聞評論內(nèi)容
先發(fā)一下,詳情待更......
【項(xiàng)目源碼】 進(jìn)去找 News163CommentCrawlerDemo 或者 News163CommentCrawlerDemo.zip
注意:Maven需要指定Java1.8 否則try-with-resource中不能使用外部數(shù)據(jù)。