Java爬虫框架WebMagic

WebMagic的架构设计参照了Scrapy,而实现则应用了HttpClient、Jsoup等Java成熟的工具。
在这里插入图片描述
WebMagic由四个组件(Downloader、PageProcessor、Scheduler、Pipeline)构成:

  • Downloader : 下载器
  • PageProcessor: 页面解析器
  • Scheduler: 任务分配、url去重
  • Pipeline:数据存储、处理

WebMagic数据流转的对象:

  • Request : 一个Request对应一个URL地址 。它是是PageProcessor控制Downloader唯一方式。
  • Page : 代表了从Downloader下载到的内容
  • ResultItems : 相当于一个Map,它保存PageProcessor处理的结果,供Pipeline使用。

爬虫引擎--Spider

  • Spider是WebMagic内部流程的核心,上面的四个组件都相当于Spider的一个属性,通过设置这个属性可以实现不同的功能。
  • Spider也是WebMagic操作的入口,它封装了爬虫的创建、启动、停止、多线程等功能

使用 Maven来安装WebMagic

<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>

在这里插入图片描述
WebMagic使用slf4j-log4j12作为slf4j的实现.如果你自己定制了slf4j的实现,需要项目中去掉此依赖。

<dependency>
    <groupId>us.codecraft</groupId>
    <artifactId>webmagic-extension</artifactId>
    <version>0.7.3</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
    </exclusions>
</dependency>

如果不使用Maven的话,可以去http://webmagic.io中下载最新的jar包,下载之后进行解压,然后在项目中import即可。


开始开发第一个爬虫

项目中添加了WebMagic的依赖之后,即可开始第一个爬虫的开发了!
下面是一个测试,点击main方法,选择“运行”,查看是否正常运行。

package com.example.demo;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;

public class DemoPageGet implements PageProcessor {
    private Site site = Site.me();

    @Override
    public void process(Page page) {
        System.out.println(page.getHtml());
    }

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

    public static void main(String[] args) {
        Spider.create(new DemoPageGet()).addUrl("http://httpbin.org/get").run();
    }
}

编写基本的爬虫

在WebMagic里,实现一个基本的爬虫只需要编写一个类,实现PageProcessor接口即可。

这部分我们直接通过GithubRepoPageProcessor这个例子来介绍PageProcessor的编写方式。

PageProcessor的定制分为三个部分,分别是爬虫的配置、页面元素的抽取和链接的发现。

public class GithubRepoPageProcessor implements PageProcessor {

    // 部分一:抓取网站的相关配置,包括编码、抓取间隔、重试次数等
    private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);

    @Override
    // process是定制爬虫逻辑的核心接口,在这里编写抽取逻辑
    public void process(Page page) {
        // 部分二:定义如何抽取页面信息,并保存下来
        page.putField("author", page.getUrl().regex("https://github\\.com/(\\w+)/.*").toString());
        page.putField("name", page.getHtml().xpath("//h1[@class='entry-title public']/strong/a/text()").toString());
        if (page.getResultItems().get("name") == null) {
            //skip this page
            page.setSkip(true);
        }
        page.putField("readme", page.getHtml().xpath("//div[@id='readme']/tidyText()"));

        // 部分三:从页面发现后续的url地址来抓取
        page.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/[\\w\\-]+/[\\w\\-]+)").all());
    }

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

    public static void main(String[] args) {

        Spider.create(new GithubRepoPageProcessor())
                //从"https://github.com/code4craft"开始抓
                .addUrl("https://github.com/code4craft")
                //开启5个线程抓取
                .thread(5)
                //启动爬虫
                .run();
    }
}

追加请求的链接

先把链接通过正则匹配出来或者拼接出来,比如: page.getHtml().links().regex("").all()
再通过addTargetRequests方法 page.addTargetRequests(url) 则将这些链接加入到待抓取的队列中去。


爬虫的配置

Spider: 爬虫程序的入口,Spider的其他组件(Downloader、Scheduler、Pipeline)都可以通过set方法来进行设置。
在这里插入图片描述
Site: 对站点本身的一些配置信息,例如编码、HTTP头、超时时间、重试策略等、代理等,都可以通过设置Site对象来进行配置。
在这里插入图片描述
配置http代理,在0.7.1版本开始,WebMagic开始使用了新的代理APIProxyProvider,因为相对于Site的“配置”,ProxyProvider定位更多是一个“组件”,所以代理不再从Site设置,而是由HttpClientDownloader设置。

更多内容见官方文档


页面元素的抽取

WebMagic里主要使用了三种数据抽取技术:

  • XPath
  • 正则表达式
  • CSS选择器
  • 另外,对于JSON格式的内容,可使用JsonPath进行解析

    使用Pipeline保存结果

    WebMagic用于保存结果的组件叫做Pipeline。

例如我们通过“控制台输出结果”这件事也是通过一个内置的Pipeline完成的,它叫做ConsolePipeline。

那么,我现在想要把结果用Json的格式保存下来,怎么做呢?

我只需要将Pipeline的实现换成"JsonFilePipeline"就可以了。

public static void main(String[] args) {
    Spider.create(new GithubRepoPageProcessor())
            //从"https://github.com/code4craft"开始抓
            .addUrl("https://github.com/code4craft")
            .addPipeline(new JsonFilePipeline("./webmagic"))
            //开启5个线程抓取
            .thread(5)
            //启动爬虫
            .run();
}

模拟POST请求方法

0.7.1版本之后,废弃了老的nameValuePair的写法,采用在Request对象上添加Method和requestBody来实现。

Request request = new Request("http://xxx/path");
request.setMethod(HttpConstant.Method.POST);
request.setRequestBody(HttpRequestBody.json("{'id':1}","utf-8"));

HttpRequestBody内置了几种初始化方式,支持最常见的表单提交、json提交等方式。

在这里插入图片描述


点赞

发表回复