Java爬虫框架WebMagic学习
一、认识WebMagic
简介:一款简单灵活的爬虫框架
官方中文文档: http://webmagic.io/docs/zh
1.总体架构
WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件。
1.1.四大组件
- Downloader:负责从互联网上下载页面,以便后续处理。
- PageProcessor:负责解析页面,抽取有用信息,以及发现新的链接。对于每个站点每个页面都不一样,是需要使用者定制的部分。
- Scheduler:负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理。
- Pipeline:负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。
1.2.数据流转的对象
- Page:从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。
- ResultItems:相当于一个Map,它保存PageProcessor处理的结果,供Pipeline使用。它的API与Map很类似,值得注意的是它有一个字段skip,若设置为true,则不应被Pipeline处理。
二、WebMagic爬虫项目简单Demo
介绍:以爬取起点中文网为例[https://www.qidian.com/all]
1.网页分析
1).具体某一个作品的链接
2.具体某一个作品的详情,书名,作者和章节等等
2.代码实现
2.1.添加依赖
注:由于我的代码中有打印日志,故排除了WebMagic包自带的slf4j-log4j12日志包。
<!--导入WebMagic相关依赖-->
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.7.2</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.7.2</version>
</dependency>
2.2.实现PageProcessor
PageProcessor的定制分为三个部分,分别是爬虫的配置、页面元素的抽取和链接的发现。
site:抓取网站的相关配置,包括编码、抓取间隔、重试次数等;
process:定制爬虫逻辑的核心接口,在这里编写抽取逻辑;根据正则表达式和XPath1语法抽取页面元素,以及深度挖掘url加入队列进行再次爬取。
package com.novelread.webmagic.processor;
import com.novelread.webmagic.pipeline.ConsolePipeline;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.JsonFilePipeline;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Selectable;
/**
* @author Administrator
* @since 2018/11/28 14:20
*/
public class NovelRepoPageProcessor implements PageProcessor {
final static Logger logger = LoggerFactory.getLogger(NovelRepoPageProcessor.class);
/**
* 主域名
*/
public static final String BASE_URL = "http://www.qidian.com/";
/**
* 正则表达式\\. \\转义java中的\ \.转义正则中的.
* 匹配作品URL 如:https://book.qidian.com/info/1010468795#Catalog
* //book.qidian.com/info/1004608738
*/
public static final String NOVEL_URL = "//book\\.qidian\\.com/info/\\d+";
/**
* 初始地址, 起点地址:中文网所有作品
*/
public static final String START_URL = "https://www.qidian.com/all";
/***
* 部分一:抓取网站的相关配置,包括编码、抓取间隔、重试次数等
*/
private Site site = Site.me().setRetryTimes(3).setSleepTime(1000)
.addHeader("Accept-Encoding", "/")
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36");
/**
* process 是定制爬虫的逻辑的核心接口,在这里编写抽取逻辑
*
* @param page
*/
@Override
public void process(Page page) {
// 部分二:定义如何抽取页面信息,并保存下来
// 根据url判断页面类型
if (page.getUrl().regex(START_URL).match()) {
logger.info("作品总数XPath------>" + page.getHtml().xpath("//div[@id='sort-count']/div/span/text()").toString());
// 爬取作品url加入队列
Selectable links = page.getHtml().xpath("//div[@class=\"book-img-box\"]").links().regex(NOVEL_URL);
page.addTargetRequests(page.getHtml().xpath("//div[@class=\"book-img-box\"]").links().regex(NOVEL_URL).all());
} else {
page.putField("name", page.getHtml().xpath("//div[@class=\"book-info\"]/h1/em/text()").toString());
page.putField("author", page.getHtml().xpath("//div[@class=\"book-info\"]/h1/span/a/text()").toString());
}
}
@Override
public Site getSite() {
return site;
}
}
2.3.编写ConsolePipeline
Pileline是抽取结束后,进行处理的部分,它主要用于抽取结果的保存,也可以定制Pileline可以实现一些通用的功能。
package com.novelread.webmagic.pipeline;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;
import java.util.Map;
/**
* @author Administrator
* @since 2018/11/28 15:21
*/
public class ConsolePipeline implements Pipeline {
/**
* 将结果保存到控制台
* @param resultItems
* @param task
*/
@Override
public void process(ResultItems resultItems, Task task) {
System.out.println("get page: " + resultItems.getRequest().getUrl());
// 遍历所有结果,输出到控制台
for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) {
System.out.println("爬取结果" + entry.getKey() + " :\t " + entry.getValue());
}
}
}
2.4.爬虫的配置、启动和终止
Spider:是爬虫启动的入口,使用一个PageProcessor创建一个Spider对象,然后使用run()进行启动。同时Spider的其他组件(Downloader、Scheduler、Pipeline)都可以通过set方法来进行设置。
/**
* 使用Pipeline保存结果
*/
public static void main(String[] args) {
Spider.create(new NovelRepoPageProcessor())
//从"https://www.qidian.com/all"开始抓
.addUrl("https://www.qidian.com/all")
// .addPipeline(new JsonFilePipeline("D:\\webmagic\\"))
.addPipeline(new ConsolePipeline())
//开启5个线程抓取
.thread(5)
//启动爬虫
.run();
}
2.5.运行结果
三、总结
本文只是根据文档写的一个简单的Demo实现简单爬虫,要想真正爬取自己想要的内容,还有一段很长的落要走。例如:对页面更详细分析,抽取内容;以及增量式抓取内容等等。
更多的参考:
1.https://blog.csdn.net/weixin_39650971/article/details/79570038
2.https://blog.csdn.net/jibaole/article/details/52212886