WebMagic簡介和使用


概覽

WebMagic是一款簡單靈活的爬蟲框架。基於它你可以很容易的編寫一個爬蟲。

WebMagic項目代碼分為核心和擴展兩部分。

  • 核心部分(webmagic-core)是一個精簡的、模塊化的爬蟲實現,而擴展部分則包括一些便利的、實用性的功能。WebMagic的架構設計參照了Scrapy,目標是盡量的模塊化,並體現爬蟲的功能特點。這部分提供非常簡單、靈活的API,在基本不改變開發模式的情況下,編寫一個爬蟲。
  • 擴展部分(webmagic-extension)提供一些便捷的功能,例如注解模式編寫爬蟲等。同時內置了一些常用的組件,便於爬蟲開發。

 

總體架構

WebMagic的結構分為DownloaderPageProcessorSchedulerPipeline四大組件,並由Spider將它們彼此組織起來。

WebMagic總體架構圖如下:

image

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. Request:Request是對URL地址的一層封裝,一個Request對應一個URL地址。它是PageProcessor與Downloader交互的載體,也是PageProcessor控制Downloader唯一方式。除了URL本身外,它還包含一個Key-Value結構的字段extra。你可以在extra中保存一些特殊的屬性,然后在其他地方讀取,以完成不同的功能。例如附加上一個頁面的一些信息等。
  2. Page:Page代表了從Downloader下載到的一個頁面——可能是HTML,也可能是JSON或者其他文本格式的內容。Page是WebMagic抽取過程的核心對象,它提供一些方法可供抽取、結果保存等。
  3. ResultItems:ResultItems相當於一個Map,它保存PageProcessor處理的結果,供Pipeline使用。它的API與Map很類似,值得注意的是它有一個字段skip,若設置為true,則不應被Pipeline處理。

 

實例

Maven坐標

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

爬取安居客房價信息實例

需求是獲取所有小區的房價,先看一下頁面截圖:

代碼:

public class AnjukeProcessor implements PageProcessor {
    //抓取網站的相關配置,包括編碼、抓取間隔、重試次數等
    private Site site = Site.me().setRetryTimes(3).setSleepTime(100);
    private static int count = 0;
    private static List<String> urlList = new ArrayList<>();

    @Override
    public void process(Page page) {
        //從頁面發現后續的url地址來抓取
        page.addTargetRequests(
                page.getHtml().xpath("//div[@class='page-content']/div[@class='multi-page']/a/@href").all());

        //判斷鏈接是否符合"https://qd.anjuke.com/community/p任意個數字"格式
        if (page.getUrl().regex("https://qd.anjuke.com/community/p[0-9]+").match()) {
            //定義如何抽取頁面信息,並保存下來
            List<Selectable> selectableList = page.getHtml().xpath("//div[@class='list-content']/div[@class='li-itemmod']").nodes();
            List<HousePrice> list = new ArrayList<>();
            for(Selectable selectable : selectableList){
                String name = selectable.xpath("//div[@class='li-info']/h3/a/text()").toString();
                String price = selectable.xpath("//div[@class='li-side']/p[1]/strong/text()").toString();
                HousePrice housePrice = new HousePrice();
                housePrice.setName(name.trim());
                housePrice.setPriceStr(price.trim());
                list.add(housePrice);
            }

            page.putField("housePriceList",list);
            urlList.add(page.getUrl().toString());
            count++;
        }
    }

    @Override
    public Site getSite() {
        return site;
    }

    public static void main(String[] args) {
        Spider.create(new AnjukeProcessor())
                .addUrl("https://qd.anjuke.com/community/") //從https://qd.anjuke.com/community/開始爬取
                .addPipeline(new HousePricePipeline())  //使用自定義的Pipeline
                .thread(5)
                .run();
        System.out.println("----------抓取了"+count+"條記錄");
    }
}
public class HousePricePipeline implements Pipeline {
    @Override
    public void process(ResultItems resultItems, Task task) {
        System.out.println("----------get page: " + resultItems.getRequest().getUrl());
        List<HousePrice> list = resultItems.get("housePriceList");
        System.out.println("----------list size:" + list.size());
    }
}

 

注意事項

在0.7.3版本中,爬取只支持TLS1.2https站點的時候會報錯:

javax.net.ssl.SSLException: Received fatal alert: protocol_version

解決辦法:https://github.com/code4craft/webmagic/issues/701

 

相關文檔

官方文檔

XPath 語法

 


免責聲明!

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



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