zoukankan      html  css  js  c++  java
  • 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 语法

  • 相关阅读:
    malloc函数具体解释
    Linux pipe函数
    秒杀多线程第四篇 一个经典的多线程同步问题
    LayoutInflater
    D3DXMatrixMultiply 函数
    用qsort排序
    Memcahce(MC)系列(一)Memcache介绍、使用、存储、算法、优化
    ANDROID L——Material Design综合应用(Demo)
    图像切割之(五)活动轮廓模型之Snake模型简单介绍
    uva 10054 The Necklace(欧拉回路)
  • 原文地址:https://www.cnblogs.com/Jason-Xiang/p/10021241.html
Copyright © 2011-2022 走看看