為了完成作業,所以學習了一下爬蟲Gecco,這個爬蟲集合了以往所有的爬蟲的特點,但是官方教程中關於Gecco的教程介紹的過於簡單,本篇博客是根據原博客的地址修改的,原博客中只有程序的截圖,而沒有給出一個完整的程序,本篇博客給出完整的代碼 首先:爬取數據的目標網站是:https://doutushe.com/portal/index/index/p/1(關於斗圖社)
創建maven項目,導入依賴:
<dependency> <groupId>com.geccocrawler</groupId> <artifactId>gecco</artifactId> <version>1.3.0</version>
</dependency>
爬取第一頁的數據,其中包括每個頁面每個詳細話題的鏈接以及下一頁的鏈接地址,
代碼如下: DoutuSheIndex.java
package com.chry.GeccoCSDN; import java.util.List; import com.geccocrawler.gecco.GeccoEngine; import com.geccocrawler.gecco.annotation.Gecco; import com.geccocrawler.gecco.annotation.Href; import com.geccocrawler.gecco.annotation.HtmlField; import com.geccocrawler.gecco.annotation.Request; import com.geccocrawler.gecco.request.HttpRequest; import com.geccocrawler.gecco.spider.HtmlBean; @Gecco(matchUrl="https://doutushe.com/portal/index/index/p/{page}", pipelines="doutusheIndex") public class DoutuSheIndex implements HtmlBean{ /** * */ private static final long serialVersionUID = 1L; @Request private HttpRequest request; @Href(click=true) @HtmlField(cssPath="a.link-2") private List<String> nameList; //得到的是地址 public HttpRequest getRequest() { return request; } public void setRequest(HttpRequest request) { this.request = request; } @Href(value="href") @HtmlField(cssPath="a.link-2") private List<String>idList; //得到的名稱 @HtmlField(cssPath="ul.pagination li") private List<IndexPageEntity> pageList; public List<IndexPageEntity> getPageList() { return pageList; } public void setPageList(List<IndexPageEntity> pageList) { this.pageList = pageList; } public List<String> getNameList() { return nameList; } public List<String> getIdList() { return idList; } public void setNameList(List<String> nameList) { this.nameList = nameList; } public void setIdList(List<String> idList) { this.idList = idList; } }
注意:在創建的類中必須要有一個request私有成員,並且添加他的get和set方法,這樣是為了后邊可以在proess中獲取數據。
現在詳細的介紹一下頁面中的每個不同的部分
每個里邊的成員變量都有一個與之對應的css路徑,這是與網頁中的元素對應的,當對應的css是一類時,可以用一個List對象來存儲該頁面中所有相同css的元素
FinishDoutusheIndex.java
package com.chry.GeccoCSDN; import org.apache.http.util.TextUtils; import com.geccocrawler.gecco.annotation.PipelineName; import com.geccocrawler.gecco.pipeline.Pipeline; import com.geccocrawler.gecco.request.HttpRequest; import com.geccocrawler.gecco.scheduler.SchedulerContext; @PipelineName(value="doutusheIndex") public class FinishDoutusheIndex implements Pipeline<DoutuSheIndex>{ public void process(DoutuSheIndex doutusheIndex) { //首先遍歷帖子的詳情 for(int i=0;i<doutusheIndex.getIdList().size();i++) { if(!TextUtils.isEmpty(doutusheIndex.getNameList().get(i))) { String url = doutusheIndex.getIdList().get(i); HttpRequest currRequest = doutusheIndex.getRequest(); SchedulerContext.into(currRequest.subRequest(url)); } } //跳轉到下一頁 for(int i=0;i<doutusheIndex.getPageList().size();i++) { String pageName = doutusheIndex.getPageList().get(i).getPageName(); if(pageName!=null&&pageName.equals("下一頁")) { String url = doutusheIndex.getPageList().get(i).getPageUrl(); HttpRequest currRequest = doutusheIndex.getRequest(); SchedulerContext.into(currRequest.subRequest(url)); } } } }
注意:這個java文件hi用來處理帕區到的第一個頁面的超鏈接的
這相當於一個管道類
每個管道類都應該有一個與之相對應的value值,上邊的value值正好與第一個java文件中的pipelines屬性相對應,這就表示第一個java類中獲取到的數據都會傳到這個類中,在自定義管道類中都會重寫一個process方法,用來處理數據,在上邊的proess中,處理的過程就是獲取每個論壇標題和下一頁的超鏈接,並放到配置中心去,此時,會自動匹配網址,進入到下一個類中。
DoutusheEntity.java
package com.chry.GeccoCSDN; import java.util.List; import com.geccocrawler.gecco.annotation.Gecco; import com.geccocrawler.gecco.annotation.HtmlField; import com.geccocrawler.gecco.annotation.Image; import com.geccocrawler.gecco.annotation.Request; import com.geccocrawler.gecco.request.HttpRequest; import com.geccocrawler.gecco.spider.HtmlBean; @Gecco(matchUrl="https://doutushe.com/portal/article/index/id/{content}", pipelines="doutusheEntity") public class DoutusheEntity implements HtmlBean{ /** * */ private static final long serialVersionUID = 1L; @Request private HttpRequest request; @HtmlField(cssPath="div.col-xs-12 blockquote p") private String title; public HttpRequest getRequest() { return request; } public String getTitle() { return title; } public void setRequest(HttpRequest request) { this.request = request; } public void setTitle(String title) { this.title = title; } }
這個java文件是用來獲取每個論壇詳細內容的,為了方便,這個只獲取每個論壇的標題,其中的pipelines=“doutusheEntity”中的doutusheEntity又是一個自定義的管道類,其內容為
FinishDoutusheEntity.java
package com.chry.GeccoCSDN; import com.geccocrawler.gecco.annotation.PipelineName; import com.geccocrawler.gecco.pipeline.Pipeline; @PipelineName(value="doutusheEntity") public class FinishDoutusheEntity implements Pipeline<DoutusheEntity>{ public void process(DoutusheEntity bean) { // TODO Auto-generated method stub System.out.println("抓取到的標題為:"+bean.getTitle()); } }
注:作用就是將前邊獲取的標題在控制台輸出
運行的結果如下:
在做測試時,可以不用自定義的管道類,直接用Gecco中自帶的管道類 consolePipeline(在控制台輸出結果),如下圖所示
到此,一個簡單的Gecco程序就算建立完成了,如果有什么問題,可以留言,我會持續更細。