1. 什么是WebMagic
WebMagic一款简单灵活的爬虫框架。WebMagic项目代码分为核心和扩展两部分。核心部分(webmagic-core)是一个精简的、模块化的爬虫实现,而扩展部分则包括一些便利的、实用性的功能。
核心部分提供了一些常用API,直接调用即可完成一个爬虫。扩展部分则提供了一些便捷功能,如实现了在注解模式下开发爬虫。
1.1WebMagic的架构组成:
WebMagic由: Downloader(下载器)、PageProcessor(页面处理器)、Scheduler(URL管理器)、Pipeline(结果处理器)四组件组成,并由Spider引擎来调度这四个部分。
Downloader | Downloader负责从互联网上下载页面,以便后续处理。WebMagic默认使用了Apache HttpClient作为下载工具。 |
---|---|
PageProcessor | PageProcessor负责解析页面,抽取有用信息,以及发现新的链接。 PageProcessor对于每个站点每个页面都不一样,需要根据业务需求自行修改。 |
Scheduler | Scheduler负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重,在新版本中,去重已经默认关闭了,交由使用者自动控制。也支持使用Redis进行分布式管理。 |
Pipeline | Pipeline负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。 Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。 |
1.2数据传输对象:
Request | Request是对URL地址的一层封装,一个Request对应一个URL地址。 |
---|---|
Page | Page代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。 |
ResultItems | ResultItems相当于一个Map,它保存PageProcessor处理的结果,供Pipeline使用。 它的API与Map很类似,ResultItems有一个字段skip,若设置为true,则不会被Pipeline处理。 |
1.3爬虫引擎–Spider:
Spider是WebMagic内部流程的核心。Downloader、PageProcessor、Scheduler、Pipeline都是Spider的一个属性,这些属性是可以自由设置的,通过设置这个属性可以实现不同的功能。Spider也是WebMagic操作的入口,它封装了爬虫的创建、启动、停止、多线程等功能。
1.4项目组成:
WebMagic的项目代码主要由两个包组成:webmagic-core和webmagic-extension。
2. 构建一个简单的WebMagic项目
以爬取程序员DD官网的归档笔记为例。
由简入繁,先来爬取任意一个页面中的标题和文章内容,操作如下:
2.1首先通过maven添加jar包:
导入core坐标:
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.7.3</version>
</dependency>
在日志方面,webMagic使用log4j来实现日志管理。因此,同样需要log4j的jar包依赖:
<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>
2.2实现PageProcessor页面处理器。
PageProcessor是用来处理页面的,因此需要实现其中的process()方法和getSite()方法.
其中process用来设置页面的抽取逻辑,然后通过page.putField()将数据保存到ResultItems中。
Site是用来设置爬虫的信息的。如域名,请求间隔等。
代码如下:
public class DemoMyself implements PageProcessor {
// 1. 设置爬虫的参数信息
Site site = Site.me()
// 指定域名
.setDomain("blog.didispace.com")
// 重新尝试次数
.setRetryTimes(3)
// 每次请求间隔2秒
.setSleepTime(2000)
// 对于某些网站,如京东等,需要设置useragent,否则无法爬取。这个在浏览器中可以查看。
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
@Override
public void process(Page page) {
// 2. 定义页面抽取逻辑,并进行保存
// 通过XPath的方式抽取数据,获取id为post-body的header标签下的h1标签中的text
page.putField("article-title", page.getHtml().xpath("//*[@id=\"post-body\"]/header/h1/text()").toString());
// 通过XPath的方式抽取数据,获取id为post-body的第二个div标签下的p标签或h2标签或blockquote标签内容
page.putField("article-entry", page.getHtml().xpath("//*[@id=\"post-body\"]/div[2]/p|h2|blockquote").toString());
}
@Override
public Site getSite() {
return site;
}
// 通过main方法启动
public static void main(String[] args) {
Spider.create(new DemoMyself())
.addUrl("http://blog.didispace.com/transactional-not-rollback/")
// 处理爬取结果
.addPipeline