通過上一節開發環境搭建中的百度新聞的爬蟲例子,相信你們已經對GuozhongCrawler簡潔的API產生濃厚興趣了。不過這個還不算一個入門例子。只是完成了簡單的下載和解析。如今咱們來完成一個比較完整的爬蟲吧。html
爲了體現GuozhongCrawler適應業務靈活性。咱們以抓取西刺代理(http://www.xici.net.co/nn/1)的代理IP爲需求。須要遍歷每一頁全部的IP並抓取下來,直到抓完全部的IP爲止。java
網頁以下:數據庫
一、新建一個Java項目命名爲XiciCrawler而且添加依賴項目爲GuozhongCrawler或者直接加入GuozhongCrawler.jar爲依賴庫。若是你們不知道怎麼建依賴項目請看個人GuozhongCrawler開發環境搭建。ide
二、新建一個爬蟲入口Class名爲StartCrawXici.java。包名自行擬定。這裏命名爲guozhong.crawler.impl。選中public static void main(String[]args)生成main方法。StartCrawXici.java代碼以下編碼
public class StartCrawXici {
/**
* @param args
*/
public static void main(String[] args) {
CrawlTask task = new CrawlTask("西刺抓代理IP");//給任務取個名字
CrawlManager.prepareCrawlTask(task)
.withThread(5)//設置下載線程數5. 默認值是5
.withStartUrl("http://www.xici.net.co/nn/1", "utf-8")//設置入口URL 並設置頁面編碼
.addPageProccess(new ParseProxyIpPage())//抓取過程當中的頁面解析器
.withPipeline(new XiciPipeLine())//離線管道
.start();//啓動
}
}
url
三、ParseProxyIpPage.java是處理頁面的實現類。須要實現一個PageProcessor Interface。PageProcessor接口設計以下:.net
/**
* 網頁處理接口
* @author Administrator
*
*/
public interface PageProcessor {
/**
* 標記這個PageProcessor,應該處理哪一種Request請求的頁面 初始URL能夠返回null
* @return
*/
public String getTag();
/**
* 若是須要頁面動態交互JS,定義一個PageScript返回
* @return
*/
public PageScript getJavaScript();
/**
* 當啓動代理Ip訪問時須要重寫此方法,返回正常網頁應該帶有的字符串標識。好比www.baidu.com帶有「百度」
* @return
*/
public Pattern getNormalContain();
/**
* 處理一個頁面
* @param page
* @param context
* @return
*/
public void process(OkPage page,StartContext context,List<Proccessable> result)throws Exception;
/**
* 處理錯誤頁面
* @param page
* @param context
*/
public void proccessErrorPage(Page page,StartContext context)throws Exception;
}線程
由於這裏是處理入口URL頁面。且不須要使用到JS和代理IP。因此getTag()、getJavaScript()和getNormalContain()都不須要實現。本節重點解釋process()方法如何使用。至於proccessErrorPage()方法實現和process大同小異。無非是處理錯誤的內容的html罷了。process()實現以下:設計
@Override
public void process(OkPage page, StartContext context,
List<Proccessable> result) throws Exception {
System.out.println("該頁面的URL:"+page.getRequest().getUrl());
Document doc = Jsoup.parse(page.getContent());
Pattern pattern = Pattern.//抽取代理IP的正則
compile("([\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3})\\s*(\\d+)\\s*([^\\s]+)\\s*([^\\s]+)\\s*([^\\s]+)");
Matcher matcher = pattern.matcher(doc.text());
XiciProxy proxy = null;
while(matcher.find()){
proxy = new XiciProxy();
proxy.setIp(matcher.group(1));
proxy.setPort(matcher.group(2));
proxy.setPosition(matcher.group(3));
proxy.setAnonymity("高匿".equals(matcher.group(4)));
proxy.setType(matcher.group(5));
result.add(proxy);//加入到界面處理結果的集合中
}
//判斷有沒有下一頁的URL。有則取得下一頁的URL
Element next_a = doc.select("a[class=next_page]").first();
if(next_a != null){
String next_url = next_a.attr("href");
Request req = context.createRequest(next_url, null, 0, "utf-8");//第二個參數傳Tag由於這裏一直是用初始頁面處理器也就是ParseProxyIpPage自己。因此能夠傳null
//第三個參數是設置request的優先級只有使用PriorityRequestQueue或者DelayedPriorityRequestQueue纔有效
result.add(req);//添加到跟進URL隊列
}
}
代理
4、XiciPipeLine是實現離線存儲的管道類。須要實現一個PipeLine Interface。PipeLine接口設計以下:
public interface Pipeline extends Serializable{
/**
* 全部的結構化數據將流向這裏。在這裏存儲你的bean
* @param procdata
*/
public void proccessData(List<Proccessable> procdata);
}
XiciPipeLine.java實現以下;
public class XiciPipeLine implements Pipeline {
@Override
public void proccessData(List<Proccessable> arg0) {
if(ProccessableUtil.instanceOfClass(arg0, XiciProxy.class)){//判斷集合類型是不是XiciProxy
List<XiciProxy> list = ProccessableUtil.convert(arg0, XiciProxy.class);//轉換
for (XiciProxy proxy : list) {
//在這裏存儲到你想要的任何數據庫
System.out.println("save:"+proxy);
}
}
}
}
至此完成了一個花刺代理的爬蟲。如今把項目圖貼出來給你們看看吧
是的4個類完成一個爬蟲。屌不屌!
在這裏補充XiciProxy.java實體類的代碼
public class XiciProxy implements Proccessable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String ip;
private String port;
private String position;
private boolean isAnonymity;
private String type;
//後面getter setter忽略...
}
注:全部實體類都要實現Proccessable接口。只是爲了標記做用。讓引擎能夠統一處理。無其餘做用