WebMagic基本使用

1.架构介绍

WebMagic 的结构分为Downloader(下载)、PageProcessor(处理)、Scheduler(管理)、Pipeline(持久)四大组件,并由Spider将它们彼此组织起来。这四大组件对应爬虫生命周期中的下载处理管理持久化等功能。WebMagic的设计参考了Scapy,但是实现方式更Java化一些。
Spider则将这几个组件组织起来,让它们可以互相交互,流程化的执行,可以认为Spider是一个大的容器,它也是WebMagic 逻辑的核心。.
在这里插入图片描述

  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处理。

所需依赖

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
<!--            <scope>test</scope>-->
        </dependency>

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

2.1 实现PageProcessor

2.1.1 抽取元素Selectable

WebMagic里主要使用了三种抽取技术:XPath、正则表达式和CSS选择器。另外,对于JSON格式的内容,可使用JsonPath进行解析。.

1. XPath:

w3cSchool Xpath语法教程

// Xpath解析
        page.putField("div2",page.getHtml().xpath("//div[@id=shortcut-2014]/div/ul/li/a"));
2.使用CSS选择器(主要使用方式):
// 解析返回的数据page,并且把解析的结果放到ResultItems中
        page.putField("div",page.getHtml().css("ul.fr li a.link-login").all());
3.使用正则表达式(难度较大):

如果想要使用,自行百度正则表达式使用规则

// 使用正则表达式
        page.putField("div3",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").all());

以上三种方法可以组合使用,例如使用正则表达式的那一节

2.1.2抽取部分API:

方法说明示例
xpath(String xpath)使用XPath选择html.xpath("//div[@class=‘title’]")
$(String selector)使用Css选择器选择html.$(“div.title”)
$(String selector,String attr)使用Css选择器选择html.$(“div.title”,“text”)
css(String selector)功能同$(),使用Css选择器选择html.css(“div.title”)
links()选择所有链接html.links()
regex(String regex)使用正则表达式抽取html.regex("(.*?)")
regex(String regex,int group)使用正则表达式抽取,并指定捕获组html.regex("(.*?)",1)
replace(String regex, String replacement)替换内容html.replace("","")

2.1.3 获得结果API

当链式调用结束时,我们一般都想要拿到一个字符串类型的结果。这时候就需要用到获取结果的API了。

我们知道,一条抽取规则,无论是XPath、CSS选择器或者正则表达式,总有可能抽取到多条元素。WebMagic对这些进行了统一,你可以通过不同的API获取到一个或者多个元素。

方法说明示例
get()返回一条String类型的结果String link= html.links().get()
toString()功能同get(),返回一条String类型的结果String link= html.links().toString()
all()返回所有抽取结果List links= html.links().all()
match()是否有匹配结果if (html.links().match()){ xxx; }

测试:

// 处理结果的api
        page.putField("div3",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").all());
		page.putField("div4",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").get());
        page.putField("div5",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").toString());
        page.putField("div6",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").match());

结果:
在这里插入图片描述

2.1.4 获取链接

目的: 爬取页面当中的链接信息,抓取下来,并且自动进行download操作,在对打开的链接信息进行分析
例如: 爬取京东快报的这个信息
在这里插入图片描述
在这里插入图片描述

使用webmagic自动的爬取这个链接中的网址在这里插入图片描述
爬取失败,抓取不到页面的信息

// 这里因为京东的反爬虫做的太好了,爬取不下来

// 这里可以自动执行多次链接的内容,只需要放入到page当中就可以自动执行,可以用于小说章节的爬取
        page.addTargetRequests(page.getHtml().css("div._3oESJEbA6EDqNUcNu8namk ul#list-646 li._22Oix1ELZz1MDoP6GMIm0F").links().all());

        page.putField("url",page.getHtml().css("div._2CD7_2MZBYElpXw5FMiwuK h3[clstag]").all());

3.2 使用和定制Pipeline

3.2.1 简单使用Pipeline

WebMagic用于保存结果的组件叫做Pipeline。例如我们通过“控制台输出结果”这件事也是通过一个内置的Pipeline完成的,它叫做ConsolePipeline。那么,我现在想要把结果用文件的格式保存下来,怎么做呢?我只需要将Pipeline的实现换成"FilePipeline"就可以了

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

3.2.2 WebMagic已经提供的几个Pipeline

WebMagic中已经提供了将结果输出到控制台、保存到文件和JSON格式保存的几个Pipeline:
在这里插入图片描述

3.2.3 定制Pipeline,保存结果到数据库中

定制Pipeline: 需要定义一个类,实现Pipeline接口,例如:
MybatisPipeline.java

@Component
public class MybatisPipeline implements Pipeline {

    @Autowired
    private JobInfoService jobInfoService;


    @Override
    public void process(ResultItems resultItems, Task task) {
        // 获取封装好的招聘详情对象
        JobInfo jobInfo = resultItems.get("jobInfo");
        // 判断数据是否不为空
        if (jobInfo != null){
            // 如果不为空,则将其保存到数据库当中
            jobInfoService.save(jobInfo);
        }
    }
}

则在PageProcessor中 引入定制的 Pipeline,并且在Spider添加进去

 //将自定义的 PipeLine注入到Process中
    @Autowired
    private MybatisPipeline mybatisPipeline;


    // 开启定时任务(initialDelay: 初始化的任务开启时间(项目启动多久后开启这个任务),fixedDelay:间隔多久再次开启)
    @Scheduled(initialDelay = 1000, fixedDelay = 100 * 1000) // 单位毫秒 1000毫秒 = 1秒
    public void process() {
        Spider.create(new JobProcessor())
                .addUrl(url)
                // 设置Scheduler和布隆过滤器
                .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000)))
                .thread(10) //10个线程进行爬取
                // 添加Pipeline
                .addPipeline(mybatisPipeline)
                .run();
    }

3.3 爬虫的配置、启动和终止

3.3.1 Spider

Spider是爬虫启动的入口。在启动爬虫之前,我们需要使用一个PageProcessor创建一个Spider对象,然后使用run()进行启动。同时Spider的其他组件(Downloader、Scheduler、Pipeline)都可以通过set方法来进行设置。

方法说明示例
create(PageProcessor)创建SpiderSpider.create(new GithubRepoProcessor())
addUrl(String…)添加初始的URLspider .addUrl(“http://webmagic.io/docs/”)
addRequest(Request…)开启n个线程spider.thread(5)
run()启动,会阻塞当前线程执行spider.run()
start()/runAsync()异步启动,当前线程继续执行spider.start()
stop()停止爬虫spider.stop()
addPipeline(Pipeline)添加一个Pipeline,一个Spider可以有多个Pipelinespider .addPipeline(new ConsolePipeline())
setScheduler(Scheduler)设置Scheduler,一个Spider只能有个一个Schedulerspider.setScheduler(new RedisScheduler())
setDownloader(Downloader)设置Downloader,一个Spider只能有个一个Downloaderspider .setDownloader(new SeleniumDownloader())
get(String)同步调用,并直接取得结果ResultItems result = spider .get(“http://webmagic.io/docs/”)
getAll(String…)同步调用,并直接取得一堆结果List results = spider .getAll(“http://webmagic.io/docs/”, “http://webmagic.io/xxx”)

3.3.2 爬虫配置Site

对站点本身的一些配置信息,例如编码、HTTP头、超时时间、重试策略等、代理等,都可以通过设置Site对象来进行配置。

方法说明示例
setCharset(String)设置编码site.setCharset(“utf-8”)
setUserAgent(String)设置UserAgentsite.setUserAgent(“Spider”)
setTimeOut(int)设置超时时间,单位是毫秒site.setTimeOut(3000)
setRetryTimes(int)设置重试次数site.setRetryTimes(3)
setCycleRetryTimes(int)设置循环重试次数site.setCycleRetryTimes(3)
addCookie(String,String)添加一条cookiesite.addCookie(“dotcomt_user”,“code4craft”)
setDomain(String)设置域名,需设置域名后,addCookie才可生效site.setDomain(“github.com”)
addHeader(String,String)添加一条addHeadersite.addHeader(“Referer”,“https://github.com”)
setHttpProxy(HttpHost)设置Http代理site.setHttpProxy(new HttpHost(“127.0.0.1”,8080))
    private Site site = new Site()
            .setCharset("utf8") //设置编码格式
            .setTimeOut(10000) //单位是毫秒
            .setRetrySleepTime(3000) // 设置重试间隔时间(单位是毫秒)
            .setRetryTimes(3) // 设置重试次数
            ;

3.4 代理的使用

有些网站不允许爬虫进行数据爬取,因为会加大服务器的压力。其中一种最有效的方式是通过ip+时间进行鉴别,因为正常人不可能短时间开启太多的页而,发起太多的请求。
我们使用的WebMagic可]以很方便的设置爬取数据的时间。但是这样会大大降低我们爬取数据的效率,如果不小心ip 被禁了,会让我们无法爬去数据,那么我们就有必要使用代理服务器来爬取数据。.

3.4.1 代理服务器

代理(英语:Proxy),也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。
提供代理服务的电脑系统或其它类型的网络终端称为代理服务器(ProxyServer)。一个完整的代理请求过程为:客户端首先与代理服务器创建连接,接着根据代理服务器所使用的代理协议,请求对目标服务器创建连接、或者获得目标服务器的指定资源

具体流程:
在这里插入图片描述
测试用: 免费代理服务器:
https://proxy.mimvp.com/freesecret

3.4.2 使用代理

从0.7.1版本开始,WebMagic开始使用了新的代理APIProxyProvider。因为相对于Site的“配置”,ProxyProvider定位更多是一个“组件”,所以代理不再从Site设置,而是由HttpClientDownloader设置。
在这里插入图片描述
ProxyProvider有一个默认实现:SimpleProxyProvider。它是一个基于简单Round-Robin的、没有失败检查的ProxyProvider。可以配置任意个候选代理,每次会按顺序挑选一个代理使用。它适合用在自己搭建的比较稳定的代理的场景。

如果需要根据实际使用情况对代理服务器进行管理(例如校验是否可用,定期清理、添加代理服务器等),只需要自己实现APIProxyProvider即可。
设置代理

    @Scheduled(fixedDelay = 1000)
    public void process(){
        //创建下载器Downloader
        HttpClientDownloader httpClientDownloader= new HttpClientDownloader();
        //给下载器设置代理服务器信息
        httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(new Proxy("112.192.146.102",32261)));

        Spider.create(new ProxyTest())
                .addUrl("http://ip.chinaz.com/")
                    //设置下载器
                .setDownloader(httpClientDownloader)
                .run();

    }

入门程序:

JobProcessor.java

package cn.itcast.webmagic.test;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.FilePipeline;
import us.codecraft.webmagic.pipeline.JsonFilePipeline;
import us.codecraft.webmagic.processor.PageProcessor;

public class JobProcessor implements PageProcessor {

    //解析页面
    @Override
    public void process(Page page) {
        // 解析返回的数据page,并且把解析的结果放到ResultItems中
        page.putField("div",page.getHtml().css("ul.fr li a.link-login").all());

        // Xpath解析
        page.putField("div2",page.getHtml().xpath("//div[@id=shortcut-2014]/div/ul/li/a"));

        // 使用正则表达式
        page.putField("div3",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").all());

        // 处理结果的api
        page.putField("div4",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").get());
        page.putField("div5",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").toString());
        page.putField("div6",page.getHtml().css("div#shortcut-2014 a").regex(".*我的.*").match());

        // 获取链接
        //page.getHtml().css("div._3oESJEbA6EDqNUcNu8namk ul#list-646 li._22Oix1ELZz1MDoP6GMIm0F a[href]")
        //page.putField("div7",page.getHtml().css("li").all());
        // 这里因为京东的反爬虫做的太好了,爬取不下来

        // 这里可以自动执行多次链接的内容,只需要放入到page当中就可以自动执行,可以用于小说章节的爬取
        //page.addTargetRequests(page.getHtml().css("div._3oESJEbA6EDqNUcNu8namk ul#list-646 li._22Oix1ELZz1MDoP6GMIm0F").links().all());

        //page.putField("url",page.getHtml().css("div._2CD7_2MZBYElpXw5FMiwuK h3[clstag]").all());
    }

    private Site site = new Site()
            .setCharset("utf8") //设置编码格式
            .setTimeOut(10000) //单位是毫秒
            .setRetrySleepTime(3000) // 设置重试间隔时间(单位是毫秒)
            .setRetryTimes(3) // 设置重试次数
            ;
    @Override
    public Site getSite() {
        return site;
    }

    //主函数执行爬虫
    public static void main(String[] args) {
        Spider.create(new JobProcessor())
                .addUrl("https://kuaibao.jd.com/?ids=238170687,238297163,174072062,238048103") //设置爬取数据的页面
                //.addPipeline(new FilePipeline("C:\\Users\\ZRE\\Desktop\\result")) // 将结果以json文件的方式输出到指定路径
                .thread(5) // 使用多线程方式,设置用5个线程处理
                .run(); //执行爬虫
    }
}
  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
WebMagic 是一个基于 Java 的简单灵活的爬虫框架,支持多线程抓取,支持分布式抓取,支持自定义扩展。WebMagic使用非常灵活,可以通过编写 Java 代码来实现各种网站的爬取。下面是一个使用 WebMagic 抓取网页并将结果以 JSON 格式输出的例子: ```java import us.codecraft.webmagic.*; import us.codecraft.webmagic.pipeline.JsonFilePipeline; import us.codecraft.webmagic.processor.PageProcessor; import us.codecraft.webmagic.selector.Selectable; public class MyPageProcessor implements PageProcessor { private Site site = Site.me().setRetryTimes(3).setSleepTime(1000); @Override public void process(Page page) { Selectable title = page.getHtml().xpath("//title/text()"); Selectable content = page.getHtml().xpath("//div[@class='content']/text()"); page.putField("title", title.get()); page.putField("content", content.get()); } @Override public Site getSite() { return site; } public static void main(String[] args) { Spider.create(new MyPageProcessor()) .addUrl("http://www.example.com") .addPipeline(new JsonFilePipeline("D:\\webmagic\\")) .run(); } } ``` 在这个例子中,我们定义了一个 `MyPageProcessor` 类,实现了 `PageProcessor` 接口,重写了 `process` 方法和 `getSite` 方法。在 `process` 方法中,我们使用WebMagic 提供的 `Selectable` 类来选择需要抓取的内容,并将结果保存到 `Page` 对象中。在 `getSite` 方法中,我们设置了一些爬虫的配置信息,例如重试次数和抓取间隔时间。在 `main` 方法中,我们创建了一个 `Spider` 对象,指定了需要抓取的网址和输出结果的格式,然后运行爬虫

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值