WebMagic寫的網絡爬蟲


一、前言

  最近因為有爬一些招聘網站的招聘信息的需要,而我之前也只是知道有“網絡爬蟲”這個神奇的名詞,具體是什么、用什么實現、什么原理、如何實現比較好都不清楚,因此最近大致研究了一下,當然,研究的並不是很深入,畢竟一個高大上的知識即使站在巨人的肩膀上,也不能兩三天就融會貫通。在這里先做一個技術儲備吧,具體的疑難知識點、細節等以后一點一點的完善,如果現在不趁熱打鐵,以后再想起來恐怕就沒印象了,那么以我的懶惰的性格估計就要拋棄對它的愛情了。廢話不多說,讓我們開始在知識的海洋里遨游吧。哎,等等,說到這我突然想到昨天新記的一首詩感覺挺好,給大家分享一下,緩解一下氣氛,再給大家講爬蟲吧:

         君生我未生,我生君已老 君恨我生遲,我恨君生早
                   君生我未生,我生君已老 恨不生同時,日日與君好
                   我生君未生,君生我已老 我離君天涯,君隔我海角
                   我生君未生,君生我已老 化蝶去尋花,夜夜棲芳草  

二、什么是網絡爬蟲

  是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本。

三、優點

  簡單易理解,管理方便。

四、WebMagic總體架構 

  

五、如何用WwbMagic

  1.5.1 WebMagic的四個組件   

1.Downloader

Downloader負責從互聯網上下載頁面,以便后續處理。WebMagic默認使用了Apache HttpClient作為下載工具。

2.PageProcessor

PageProcessor負責解析頁面,抽取有用信息,以及發現新的鏈接。WebMagic使用Jsoup作為HTML解析工具,並基於其開發了解析XPath的工具Xsoup

在這四個組件中,PageProcessor對於每個站點每個頁面都不一樣,是需要使用者定制的部分。

3.Scheduler

Scheduler負責管理待抓取的URL,以及一些去重的工作。WebMagic默認提供了JDK的內存隊列來管理URL,並用集合來進行去重。也支持使用Redis進行分布式管理。

除非項目有一些特殊的分布式需求,否則無需自己定制Scheduler。

4.Pipeline

Pipeline負責抽取結果的處理,包括計算、持久化到文件、數據庫等。WebMagic默認提供了“輸出到控制台”和“保存到文件”兩種結果處理方案。

Pipeline定義了結果保存的方式,如果你要保存到指定數據庫,則需要編寫對應的Pipeline。對於一類需求一般只需編寫一個Pipeline

1.5.2  爬蟲項目簡單例子 

依賴:

 1 <dependency>
 2     <groupId>us.codecraft</groupId>
 3     <artifactId>webmagic-core</artifactId>
 4     <version>0.6.1</version>
 5 </dependency>
 6 <dependency>
 7     <groupId>us.codecraft</groupId>
 8     <artifactId>webmagic-extension</artifactId>
 9     <version>0.6.1</version>
10 </dependency>

 

簡單代碼:  

 1 import us.codecraft.webmagic.Page;
 2 import us.codecraft.webmagic.Site;
 3 import us.codecraft.webmagic.Spider;
 4 import us.codecraft.webmagic.processor.PageProcessor;
 5 
 6 public class GithubRepoPageProcessor implements PageProcessor {
 7 
 8     private Site site = Site.me().setRetryTimes(3).setSleepTime(100);
 9 
10     @Override
11     public void process(Page page) {
12         page.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all());
13         page.putField("author", page.getUrl().regex("https://github\\.com/(\\w+)/.*").toString());
14         page.putField("name", page.getHtml().xpath("//h1[@class='entry-title public']/strong/a/text()").toString());
15         if (page.getResultItems().get("name")==null){
16             //skip this page
17             page.setSkip(true);
18         }
19         page.putField("readme", page.getHtml().xpath("//div[@id='readme']/tidyText()"));
20     }
21 
22     @Override
23     public Site getSite() {
24         return site;
25     }
26 
27     public static void main(String[] args) {
28         Spider.create(new GithubRepoPageProcessor()).addUrl("https://github.com/code4craft").thread(5).run();
29     }

 

 如果仔細分析這段代碼的邏輯,將其弄明白了,那么對於一個簡單的爬蟲項目,你就可以自己寫了。

addUrl是定義從哪一個頁面開始爬取;

addTargetRequests(page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all());是指定抓取html頁面的符合此正則表達式的所有鏈接url;

page.getHtml().xpath("//h1[@class='entry-title public']/strong/a/text()").toString是指定抓取h1標簽下的class屬性值為entry-title public的子標

簽strong下的a標簽下的文本內容;

   tidyText()所有的直接和間接文本子節點,並將一些標簽替換為換行,使純文本顯示更整潔。當然這也就要求大家也要對正則表達式熟悉了。本文用的是xsoup,Xsoup是
基於Jsoup開發的一款XPath 解析器,之前WebMagic使用的解析器是HtmlCleaner,使用過程存在一些問題。主要問題是XPath出錯定位不准確,並且其不太合理的代碼結構
也難以進行定制。而Xsoup更加符  合爬蟲開發的需 要。令人欣喜的是,經過測試,Xsoup的性能比HtmlCleaner要快一倍以上。 
  通過注解將值賦給model屬性的實體類:
      
 1 @TargetUrl("https://github.com/\\w+/\\w+")
 2 @HelpUrl("https://github.com/\\w+")
 3 public class GithubRepo {
 4 
 5     @ExtractBy(value = "//h1[@class='entry-title public']/strong/a/text()", notNull = true)
 6     private String name;
 7 
 8     @ExtractByUrl("https://github\\.com/(\\w+)/.*")
 9     private String author;
10 
11     @ExtractBy("//div[@id='readme']/tidyText()")
12     private String readme;
13 }

 

 
提示:
HelpUrl/TargetUrl是一個非常有效的爬蟲開發模式,TargetUrl是我們最終要抓取的URL,最終想要的數據都來自這里;而HelpUrl則是為了發現這個最終URL,我們需要訪問的頁面。幾乎所有垂直爬蟲的需求,都可以歸結為對這兩類URL的處理:
  • 對於博客頁,HelpUrl是列表頁,TargetUrl是文章頁。
  • 對於論壇,HelpUrl是帖子列表,TargetUrl是帖子詳情。
  • 對於電商網站,HelpUrl是分類列表,TargetUrl是商品詳情。

模擬瀏覽器請求:
  
 1     public VideoSpider(String url, String proxyStr) {
 2         this.client_url = url;
 3         String[] tmp = proxyStr.split(":");
 4         HttpHost proxy = new HttpHost(tmp[1].substring(2), Integer.parseInt(tmp[2]), tmp[0]);
 5         Site site = Site.me().setRetryTimes(3).setHttpProxy(proxy).setSleepTime(100).setTimeOut(10 * 1000).setCharset("UTF-8")
 6                 .setUserAgent("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36");
 7 
 8         GPHttpClientDownloader downloader = new GPHttpClientDownloader();
 9         Request request = new Request(this.client_url);
10 
11         this.setCookie(request, site, downloader);
12         this.setParameters(request, site, downloader);
13     }

 

  中setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"),jobInfoDaoPipeline, LieTouJobInfo.class)

 是模擬火狐、蘋果、谷歌等瀏覽器進行請求將通過實體類LieTouJobInfo來抓取指定的內容並通過數據庫訪問層jobInfoDaoPipeline將相關屬性存入數據庫。

六、思考

  簡單的爬蟲用以上代碼基本就可以實現,但是我們要知道,要想真正爬取自己想要的內容,還有一段很長的落要走。因為我們在抓取數據的時候要考慮到去重、動態頁面的產生、快速的更新頻率、巨大的數據量等等的問題。針對這些問題我們該怎么做才能有效簡單的去解決,這是
一個特別值得探討的問題。就先寫到這吧,如果我研究的有進展了,足以在公司項目中穩定投入使用了,再來完善吧。

下載:

最新版:WebMagic-0.6.1

Maven依賴:

<dependency> <groupId>us.codecraft</groupId> <artifactId>webmagic-core</artifactId> <version>0.6.1</version> </dependency> <dependency> <groupId>us.codecraft</groupId> <artifactId>webmagic-extension</artifactId> <version>0.6.1</version> </dependency> 

文檔:

源碼:

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM