WebMagic的学习

发布于:2022-12-29 ⋅ 阅读:(698) ⋅ 点赞:(0)

概览

  1. 设计思想 :功能性让步简单性,微内核,高可拓展性,注重实用性

  2. 总体架构:

    分为四层:Downloader,PageProcessor,Scheduler,Pipeline四个组件,对应爬虫生命周期中的下载,处理,管理和持久化等功能

    1. Downloader负责从互联网上下载页面,以便后续处理,默认使用Apache HttpClient作为下载工具

    2. PageProcessor负责解析页面,抽取有用信息,以及发现新的链接,使用Jsoup作为HTML解析工具 并基于他开发了解析Xpath的工具Xsoup

    3. Scheduler负责管理待抓取的URL,以及去重的工作,默认提供了JDK的内存队列来管理URL,并且用集合来去重

    4. Pipeline负责抽取结果的处理,包括计算,持久化到文件,数据库等,默认提供了输出到控制台和保存到文件两种结果处理方案

      控制爬虫运转的引擎--Spider:Spider是WebMagic内部流程的核心。Downloader、PageProcessor、Scheduler、Pipeline都是Spider的一个属性,这些属性是可以自由设置的,通过设置这个属性可以实现不同的功能。Spider也是WebMagic操作的入口,它封装了爬虫的创建、启动、停止、多线程等功能。

      PageProcessor是需要编写的部分,而Spider则是创建和控制爬虫的入口。

      第一个爬虫程序

package com.lzj.pojo;

import us.codecraft.webmagic.Page;

import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.ConsolePipeline;
import us.codecraft.webmagic.processor.PageProcessor;

import java.util.List;

public class GithubRepoPageProcessor implements PageProcessor {
    //抓取网站的相关配置
    private Site site=Site.me().setRetryTimes(3).setSleepTime(100).setDomain("my.oschina.net");
    @Override
    public void process(Page page) {
     List<String > links= page.getHtml().links().regex("http://my\\\\.oschina\\\\.net/flashsword/blog/\\\\d+").all();
     page.addTargetRequests(links);
      //xpath是一种html网页的访问方式,类似于css
     page.putField("title", page.getHtml().xpath("//div").toString());
     page.putField("context",page.getHtml().$("div.content").toString());
     page.putField("tags",page.getHtml().xpath("//div/a").all());
    }

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

    public static void main(String[] args) {
        //这里采用控制台输出,使用.addPipeline(new JsonFilePipeline("D:\\webmagic\\")),可以以Json格式存放到D盘下的WebMagic目录下,一个Spider可以有多个Pipeline
        Spider.create(new GithubRepoPageProcessor()).addUrl("https://www.bilibili.com/").addPipeline(new ConsolePipeline()).run();
    }
}

Spider的一些具体方法

 

Site的具体方法

 

爬虫的监控

功能通过JMX实现,可以使用Jconsole等JMX工具查看本地或者远程的爬虫信息

配置代理

//设置代理
HttpClientDownloader.setProxyProvider(ProxyProvider proxyProvider)

 

ProxyProvider有一个默认实现:SimpleProxyProvider。它是一个基于简单Round-Robin的、没有失败检查的ProxyProvider。可以配置任意个候选代理,每次会按顺序挑选一个代理使用。它适合用在自己搭建的比较稳定的代理的场景。

实例

单一代理,设置用户名和密码

 HttpClientDownloader httpClientDownloader = new HttpClientDownloader();
    httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(new Proxy("101.101.101.101",8888,"username","password")));
    spider.setDownloader(httpClientDownloader);

 代理池

HttpClientDownloader httpClientDownloader = new HttpClientDownloader();
    httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(
    new Proxy("101.101.101.101",8888)
    ,new Proxy("102.102.102.102",8888)));

注解编写爬虫(友情提醒:注解一时爽,运维火葬场)

@HelpUrl与TargetUrl

HelpUrl/TargetUrl是一个非常有效的爬虫开发模式,TargetUrl是我们最终要抓取的URL,最终想要的数据都来自这里;而HelpUrl则是为了发现这个最终URL,我们需要访问的页面

@TargetUrl("GitHub: Where the world builds software · GitHub\w+/\w+")

  • 括号里的内容使用正则表达式,但做了改动

  • 将URL中常用的 “ .” 做了转义,变成了 .

  • 将“ *” 替换成了“.”,直接使用可表示通配符

  • 支持定义sourceRegion,这个参数是XPath表达式

@ExtractBy

@ExtractBy注解主要作用于字段,它表示“使用这个抽取规则,将抽取到的结果保存到这个字段中”。支持使用多个抽取方式,但是需要声明类型,且里面还有一个属性,notnull,将它设置为true,可以过滤掉无用的页面

当一个页面上有多条数据,在类上使用这个标签,可以只扫描这一块区域,当然,类里面如果再次使用这个注解则也是在当前区域选择,如果想要在整个页面选择,需要设置source=RawHtml

@ExtractBy("//h1[@name='ls']/text()")
private String title;

@ExtractByUrl

@ExtractByUrl`是一个单独的注解,它的意思是“从URL中进行抽取”。它只支持正则表达式作为抽取规则

@Formatter

可以将结果类型转换成指定类型例如

@Formatter("yyyy-MM-dd HH:mm")
@ExtractBy("//div[@class='BlogStat']/regex('\\d+-\\d+-\\d+\\s+\\d+:\\d+')")
private Date date;

一般情况下,Formatter会根据字段类型进行转换,但是特殊情况下,我们会需要手动指定类型。这主要发生在字段是List类型的时候。

@Formatter(value = "",subClazz = Integer.class)
@ExtractBy(value = "//div[@class='id']/text()", multi = true)
private List<Integer> ids;

支持自定义结果

注解爬虫的创建与启动

注解模式的入口是OOSpider,它继承了Spider类,提供了特殊的创建方法,其他的方法是类似的。创建一个注解模式的爬虫需要一个或者多个Model类,以及一个或者多个PageModelPipeline——定义处理结果的方式。

public static OOSpider create(Site site, PageModelPipeline pageModelPipeline, Class... pageModels);

AfterExtractor接口

当解无法满足要求时,重写这个类的方法,完成操作,这个方法会在抽取结束,字段都初始化完毕之后执行

Pipeline

 

Scheduler

DuplicateRemover接口

实现去重的功能

 

 所有默认的Scheduler都使用HashSetDuplicateRemover来进行去重,(除开RedisScheduler是使用Redis的set进行去重)。如果你的URL较多,使用HashSetDuplicateRemover会比较占用内存,所以也可以尝试以下BloomFilterDuplicateRemover。


网站公告

今日签到

点亮在社区的每一天
去签到