用WebCollector製做一個爬取《知乎》並進行問題精準抽取的爬蟲(JAVA)

簡單介紹:html

WebCollector是一個無須配置、便於二次開發的JAVA爬蟲框架(內核),它提供精簡的的API。僅僅需少許代碼就能夠實現一個功能強大的爬蟲。java

怎樣將WebCollector導入項目請看如下這個教程:node

JAVA網絡爬蟲WebCollector深度解析——爬蟲內核ajax


參數:算法

WebCollector無需繁瑣配置。僅僅要在代碼中給出如下幾個必要參數,就能夠啓動爬蟲:數據庫

1.種子(必要):網絡

種子即爬蟲的起始頁面。一個爬蟲可加入一個或多個種子。多線程

2.正則(可選):框架

正則是約束爬取範圍的一些正則式。ide

正則不必定要給出。假設用戶沒有給出正則,系統會本身主動將爬取範圍限定在種子的域名內。

3.線程數(可選):

WebCollector是一個多線程的爬蟲,默認使用10個線程同一時候工做。開發人員可以本身定義線程數。


需求:

簡述一下教程裏代碼的功能:定製一個爬蟲,對「知乎」站點進行爬取。不要求下載所有的網頁和文件,而是要求對知乎中所有的「提問」頁面中的」問題「進行提取。如圖:

咱們需要提取問題標題:「看了《蝙蝠俠》,假設我闖進紐交所,逼迫所有人賣掉他手裏的所有的股票期貨債券什麼的,會有什麼毀滅性後果?",

以及問題的內容:「咱不討論這可行性,我就想聽聽這有什麼毀滅性那個的後果麼?再比方百度。58,新東方什麼的在那上市的中國公司?再比方會對其它的比方倫敦交易所什麼的影響?中國股市的影響?再比方對其它貨幣的影響之類的?「


代碼:

代碼分爲兩部分,爬取器和控制器。

爬取器經過Override父類中的visit方法(即對每個正在爬取的頁面需要進行的操做),來定製本身的爬取任務。

控制器經過給爬取器設置參數(上面所說的種子、正則、線程數)。啓動爬取器來完畢控制功能。

1.爬取器:

WebCollector中集成了多種爬取器(主要是遍歷算法不一樣),最常常使用的遍歷器是BreadthCrawler,它是基於廣度遍歷的算法進行爬取的。咱們新建一個JAVA類ZhihuCrawler,繼承BreadthCrawler,來定製咱們的爬取器。


public class ZhihuCrawler extends BreadthCrawler{

    /*visit函數定製訪問每個頁面時所需進行的操做*/
    @Override
    public void visit(Page page) {
        String question_regex="^http://www.zhihu.com/question/[0-9]+";
        if(Pattern.matches(question_regex, page.getUrl())){
            System.out.println("正在抽取"+page.getUrl());
            /*抽取標題*/
            String title=page.getDoc().title();
            System.out.println(title);
            /*抽取提問內容*/
            String question=page.getDoc().select("div[id=zh-question-detail]").text();
            System.out.println(question);

        }
    }


 代碼解析: 
 

《知乎》中有很是多種網頁:提問網頁、用戶我的信息網頁、專頁。咱們現在僅僅要對提問網頁進行操做。

提問網頁的URL通常例如如下:http://www.zhihu.com/question/21962447

question_regex是所有提問網頁的正則表達式,代碼中:

if(Pattern.matches(question_regex, page.getUrl())){
          //操做代碼 
}

保證咱們僅僅對「提問」頁面進行抽取。

visit函數的參數Page page,是一個已經爬取並解析成DOM樹的頁面。Page的參數:

page.getUrl() returns the url of the downloaded page

page.getContent() returns the origin data of the page

page.getDoc() returns an instance of org.jsoup.nodes.Document

page.getResponse() returns the http response of the page

page.getFetchTime() returns the time this page be fetched at generated by System.currentTimeMillis()


特別要注意的是page.getDoc()(DOM樹)。這裏的page.getDoc()是JSOUP的Document,假設需要作HTML解析、抽取。使用page.getDoc()是不二的選擇。關於jsoup的用法,可參考JSOUP的教程:

http://www.brieftools.info/document/jsoup/



ZhihuCrawler中用到了page.getUrl()和page.getDoc()。

咱們可以發現,《知乎》提問頁面的網頁標題就是問題的標題,因此經過:

String title=page.getDoc().title();
就獲取了提問標題。

抽取《知乎》提問頁面的提問內容,需要從HTML源代碼觀察規則:

<div data-action="/question/detail" data-resourceid="965792" class="zm-item-rich-text" id="zh-question-detail">
    <div class="zm-editable-content">咱不討論這可行性,我就想聽聽這有什麼毀滅性那個的後果麼?<br>
      再比方百度,58,新東方什麼的在那上市的中國公司?<br>
      再比方會對其它的比方倫敦交易所什麼的影響?中國股市的影響?<br>再比方對其它貨幣的影響之類的?
    </div>
</div>


對於《知乎》所有的提問界面。咱們發現,提問內容都被放在一個id="zh-question-detail"的div中。這是JSOUP最適合適用的一種狀況。咱們僅僅要找到這個div,將當中的文本(text)取出就能夠:

String question=page.getDoc().select("div[id=zh-question-detail]").text();


2.控制器:

咱們需要一個控制器來啓動爬取器:


public class Controller {
    
    public static void main(String[] args) throws IOException{   
        ZhihuCrawler crawler=new ZhihuCrawler();
        crawler.addSeed("http://www.zhihu.com/question/21003086");
        crawler.addRegex("http://www.zhihu.com/.*");
        crawler.start(5);   
    }
}


首先實例化剛定義的ZhihuCrawler(爬取器)。

給爬取器一個種子:http://www.zhihu.com/question/21003086

crawler.start(5)並不是表示開啓5個線程爬取,5表示爬取的深度(廣度遍歷的層數)。

執行Controller這個類,會發現不斷有輸出產生。但是輸出比較雜亂。這是因爲咱們不只輸出了咱們抽取的提問。還輸出了爬蟲的日誌(爬取記錄等):

fetch:http://www.zhihu.com/people/lxjts
fetch:http://www.zhihu.com/question/24597698
正在抽取http://www.zhihu.com/question/24597698
小米4採用304不鏽鋼除了提高質感和B格。還有其它的實際優勢麼? - 知乎
信號會不會跟ip4同樣悲劇了……
fetch:http://www.zhihu.com/topic/20006139
fetch:http://www.zhihu.com/topic/19559450
fetch:http://www.zhihu.com/question/20014415#
fetch:http://www.zhihu.com/collection/31102864
fetch:http://www.zhihu.com/topic/19663238
fetch:http://www.zhihu.com/collection/20021567
上面的輸出片斷中,咱們可以看到一次visit函數的運行,訪問了 http://www.zhihu.com/question/24597698 ,對問題的標題進行了抽取:「小米4採用304不鏽鋼除了提高質感和B格。還有其它的實際優勢麼? - 知乎」。同一時候也抽取了問題的內容:「信號會不會跟ip4同樣悲劇了……「。
"fetch:http://www.zhihu.com/question/24597698"是日誌的輸出,表示一個已經爬取的網頁。


假設您想看到乾淨的爬取結果,有如下幾種解決方式:

1.在ZhihuCrawler的visit方法裏,加入代碼。將title和question字符串輸出到文件裏。

2.在ZhihuCrawler的visit方法裏。加入代碼,將title和question字符串提交到數據庫(推薦)。


可能有人會疑問。爲何咱們給爬蟲加入種子的時候不加入《知乎》的首頁,這是因爲《知乎》首頁在不登陸的狀況下會默認返回登陸頁面。

相關文章
相關標籤/搜索