web爬虫系列(三)– WebMagic介绍

837 阅读5分钟

一、WebMagic

1、总体介绍及设计思想

webmagic是一个开源的Java垂直爬虫框架,目标是简化爬虫的开发流程,让开发者专注于逻辑功能的开发。

webmagic采用完全模块化的设计,功能覆盖整个爬虫的生命周期(链接提取、页面下载、内容抽取、持久化),支持多线程抓取,分布式抓取,并支持自动重试、自定义UA/cookie等功能。

webmagic包含页面抽取功能,开发者可以使用css selector、xpath和正则表达式进行链接和内容的提取,支持多个选择器链式调用。

2、架构简介

WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。这四大组件对应爬虫生命周期中的下载、处理、管理和持久化等功能。WebMagic的设计参考了Scapy,但是实现方式更Java化一些。

而Spider则将这几个组件组织起来,让它们可以互相交互,流程化的执行,可以认为Spider是一个大的容器,它也是WebMagic逻辑的核心。


  • 组件

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

PageProcessor负责解析页面,抽取有用信息,以及发现新的链接。WebMagic使用Jsoup作为HTML解析工具,并基于其开发了解析XPath的工具Xsoup。在这四个组件中,PageProcessor对于每个站点每个页面都不一样,是需要使用者定制的部分。

Scheduler负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理。除非项目有一些特殊的分布式需求,否则无需自己定制Scheduler。

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

Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。

  • 数据流转的对象

Request是对URL地址的一层封装,一个Request对应一个URL地址。

它是PageProcessor与Downloader交互的载体,也是PageProcessor控制Downloader唯一方式。

除了URL本身外,它还包含一个Key-Value结构的字段extra。你可以在extra中保存一些特殊的属性,然后在其他地方读取,以完成不同的功能。例如附加上一个页面的一些信息等

Page代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。

Page是WebMagic抽取过程的核心对象,它提供一些方法可供抽取、结果保存等。

ResultItems相当于一个Map,它保存PageProcessor处理的结果,供Pipeline使用。它的API与Map很类似,值得注意的是它有一个字段skip,若设置为true,则不应被Pipeline处理。

  • 爬虫运转的引擎

Spider是WebMagic内部流程的核心。Downloader、PageProcessor、Scheduler、Pipeline都是Spider的一个属性,这些属性是可以自由设置的,通过设置这个属性可以实现不同的功能。Spider也是WebMagic操作的入口,它封装了爬虫的创建、启动、停止、多线程等功能。下面是一个设置各个组件,并且设置多线程和启动的例子。

3、依赖介绍

包含两个jar包:webmagic-core-{version}.jar和webmagic-extension-{version}.jar。在项目中添加这两个包的依赖,即可使用WebMagic。

二、实战演练

1、爬取可见页面

可见即可得,实战演练直接上手全套流程,直接看代码比抄那么多概念更有说服力。以爬电影天堂为例,见web爬虫系列(一)- 爬取电影天堂迅雷地址

2、爬取ajax渲染出的页面

可见不一定可得,有一些网站我们查看元素发现找不到想要的内容,这个时候需要分析数据来源,会发现有些数据是通过触发一个接口返回了这样的内容。如果返回的是json我们可以直接反序列化得到想要的DTO,如果返回的是dom,我们可以转成HTML然后同01示例步骤得到想要的结果。

public void process(Page page) {
       String responseJson = page.getField(Constant.RESPONSE_JSON).toString();
       PingWestResponseDTO response = JsonUtil.toObject(responseJson, PingWestResponseDTO.class);
       if (response == null || StringUtils.isEmpty(response.getData())) {
           return;
       }
       Html html = Html.create(response.getData());
       if (html == null) {
           return;
       }

       String xpathStr = "//*[@class=\"date-category\"]";
       List<Selectable> newsViewList = html.xpath(xpathStr).nodes();
       List<NewsDTO> newsList = new ArrayList<>();
       for (Selectable newsView : newsViewList) {
           //do somethings
       }

   }

三、乱弹琴

写到这里突然觉得没什么意思了,很多东西就像带你入门一样,如果感兴趣的小伙伴肯定会继续去钻研,不感兴趣的只是花3秒走马观花了一篇博文而已,所以后面更多的内容可以参考官方文档webmagic.io继续学习,我也没必要从官网抄来抄去,也可以跟我一起讨论,毕竟我们都还是小白。该系列总共四篇,前三篇带大家了解入门,最后一篇将介绍哒耳文科技简报相关架构。如果对科技资讯感兴趣可以帮忙分享一下小程序,将不胜感激!