WebMagic
Posted roadlandscape
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebMagic相关的知识,希望对你有一定的参考价值。
WebMagic是一款爬虫框架,其底层使用的是HttpClient和Jsoup,让我们能够更方便的开发爬虫。
WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。这四大组件对应爬虫生命周期中的下载、处理、管理和持久化等功能。WebMagic的设计参考了Scapy(Python的爬虫框架),但是实现方式更Java化一些。 而Spider则将这几个组件组织起来,让它们可以互相交互,流程化的执行,可以认为Spider是一个大的容器,它也是WebMagic逻辑的核心。
WebMagic的四个组件:
1.Downloader
负责从互联网上下载页面,以便后续处理。WebMagic默认使用了Apache HttpClient作为下载工具。
2.PageProcessor
负责解析页面,抽取有用信息,以及发现新的链接。WebMagic使用Jsoup作为html解析工具,并基于其开发了解析XPath的工具Xsoup。 在这四个组件中,PageProcessor对于每个站点每个页面都不一样,是需要使用者定制的部分。
3.Scheduler
负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理
4.Pipeline
负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。
用于数据流转的对象:
1. Request
是对URL地址的一层封装,一个Request对应一个URL地址。它是PageProcessor与Downloader交互的载体,也是PageProcessor控制Downloader唯一方式。 除了URL本身外,它还包含一个Key-Value结构的字段extra。你可以在extra中保存一些特殊的属性,然后在其他地方读取,以完成不同的功能。例如附加上一个页面的一些信息等。 2. Page
代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。Page是WebMagic抽取过程的核心对象,它提供一些方法可供抽取、结果保存等。
3. ResultItems
相当于一个Map,它保存PageProcessor处理的结果,供Pipeline使用。它的API与Map很类似,值得注意的是它有一个字段skip,若设置为true,则不应被Pipeline处理。
快速入门:
1.创建工程,引入依赖
注意:0.7.3版本对SSL的并不完全,如果是直接从Maven中央仓库下载依赖,在爬取只支持SSL v1.2的网站会有SSL的异常抛出。
解决方案:1.等作者的0.7.4的版本发布 2.直接从github上下载最新的代码,安装到本地仓库
也可以参考以下资料自己修复 https://github.com/code4craft/webmagic/issues/701
2.加入日志配置文件 log4j.properties
WebMagic使用slf4j-log4j12作为slf4j的实现。
3.测试
public class JobProcessor implements PageProcessor { // 解析页面 @Override public void process(Page page) { // 解析返回的数据page,并且把解析的结果放ResultItems中 page.putField("div", page.getHtml().css("div#shortcut #ttbar-login a").all()); } @Override public Site getSite() { return Site.me(); } public static void main(String[] args) { Spider.create(new JobProcessor()) .addUrl("https://www.jd.com/") // 设置爬取数据的页面 .run(); // 执行 } }
WebMagic里主要使用了三种解析页面技术:XPath、正则表达式和CSS选择器。另外,对于JSON格式的内容,可使用JsonPath进行解析。
1.XPath 详细使用教程 https://www.w3school.com.cn/xpath/index.asp
// XPath page.putField("div2", page.getHtml().xpath("//div[@id=J_cate]/ul/li/a"));
2. CSS选择器
.css("div#shortcut")
.css("div#shortcut", "text").toString() :获取指定元素的纯文本
3.正则表达式
// 正则表达式 page.putField("div3", page.getHtml().css("div#shortcut #ttbar-login a").regex(".*注册.*").all());
抽取元素API:
这部分抽取API返回的都是一个Selectable接口,意思是说,是支持链式调用的。
获取结果API:
page.getHtml().css("ul").nodes(); 获取ul下的所有节点
当有多条数据的时候,使用get()和toString()都是获取第一条。
// 处理结果API page.putField("div4", page.getHtml().css("div#shortcut #ttbar-login a").get()); page.putField("div5", page.getHtml().css("div#shortcut #ttbar-login a").toString()); page.putField("div6", page.getHtml().css("div#shortcut #ttbar-login a").all());
获取链接,把链接放到待抓取的队列中
// 获取连接 // page.addTargetRequest("http://www.xingdali.com/"); page.addTargetRequests(page.getHtml().css("ul.wide > li").links().all()); page.putField("nav", page.getHtml().css("div.tx-title1 > strong").all());
使用Pipeline保存结果:
WebMagic用于保存结果的组件叫做Pipeline。我们不做任何操作就可以看到“控制台输出结果”是通过一个内置的Pipeline完成的,它叫做ConsolePipeline。
那么,如果想要把结果保存到文件中,怎么做呢?只需将Pipeline的实现换成"FilePipeline"就可以了。
public static void main(String[] args) { Spider.create(new JobProcessor()) // .addUrl("https://www.jd.com/") // 设置爬取数据的页面 .addUrl("http://www.xingdali.com/") .addPipeline(new FilePipeline("D:aaa")) .thread(5) // 设置多线程 .run(); // 执行 }
WebMagic的配置、启动和终止:
1.Spider
Spider是启动的入口。在启动之前,我们需要使用一个PageProcessor创建一个Spider对象,然后使用run()进行启动。 同时Spider的其他组件(Downloader、Scheduler、Pipeline)都可以通过set方法来进行设置。
2.Site
Site.me()可以对请求进行一些配置,包括编码、抓取间隔、超时时间、重试次数等。
@Override public Site getSite() { return Site.me() .setCharset("utf8") .setTimeOut(1000) // 设置超时时间 单位ms .setRetrySleepTime(10000) // 设置重试的间隔时间 .setRetryTimes(3); // 设置失败的重试次数 }
Scheduler组件:
Scheduler是WebMagic中进行URL管理的组件。一般来说,Scheduler包括两个作用: 1.对抓取的URL队列进行管理 2.对已抓取的URL进行去重。
WebMagic内置了几个常用的Scheduler。如果你只是在本地执行规模比较小的爬虫,那么基本无需定制Scheduler,但是了解一下已经提供的几个Scheduler还是有意义的。
去重部分被单独抽象成了一个接口:DuplicateRemover,从而可以为同一个Scheduler 选择不同的去重方式,以适应不同的需要,目前提供了两种去重方式。
RedisScheduler 是使用 Redis 的 set 进行去重,其他的 Scheduler 默认都使用HashSetDuplicateRemover 来进行去重。
如果要使用 BloomFilter,必须要加入以下依赖:
<!--WebMagic 对布隆过滤器的支持--> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>16.0</version> </dependency>
public static void main(String[] args) { Spider spider = Spider.create(new JobProcessor()) // .addUrl("https://www.jd.com/") // 设置爬取数据的页面 .addUrl("http://www.xingdali.com/") .addPipeline(new FilePipeline("D:aaa")) .thread(5) // 设置多线程 .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(1000000))); // 参数设置对多少条数据进行去重 Scheduler scheduler = spider.getScheduler(); spider.run(); }
三种去重方式:
HashSet
使用 java 中的 HashSet 不能重复的特点去重。优点是容易理解。使用方便。
缺点:占用内存大,性能较低。
Redis 去重
使用 Redis 的 set 进行去重。优点是速度快(Redis 本身速度就很快),而且去重不会占用爬虫服务器的资源(单独部署redis),可以处理更大数据量的数据爬取。
缺点:需要准备 Redis 服务器,增加开发和使用成本。
布隆过滤器(BloomFilter )
使用布隆过滤器也可以实现去重。优点是占用的内存要比使用 HashSet要小的多,也适合大量数据的去重操作。
缺点:有误判的可能。没有重复可能会判定重复,但是重复数据一定会判定重复。
以上是关于WebMagic的主要内容,如果未能解决你的问题,请参考以下文章