java爬虫抓取动态网页(Java垂直爬虫框架(一)——webmagic)

优采云 发布时间: 2022-03-11 17:14

  java爬虫抓取动态网页(Java垂直爬虫框架(一)——webmagic)

  webmagic 是一个开源的 Java 垂直爬虫框架。其目标是简化爬虫的开发过程,让开发者专注于逻辑功能的开发。webmagic的核心很简单,但是涵盖了爬虫的全过程,也是学习爬虫开发的好资料。

  网络爬虫是一种技术,webmagic致力于降低这项技术的实现成本,但出于对资源提供者的尊重,webmagic不会做防阻塞的事情,包括:验证码破解、代理切换、自动登录等...

  作者黄宜华()曾在原公司从事垂直履带开发工作一年。Webmagic 是为解决爬虫开发的一些重复性工作而生成的框架。

  webmagic的架构和设计参考了以下两个项目,感谢以下两个项目的作者:

  python爬虫scrapy

  Java爬虫蜘蛛侠

  webmagic 遵循 Apache 2.0 协议,您可以自由使用和修改它。如果您有任何不便或问题,欢迎您在 github 上提交问题,或在 oschina 讨论模块中提问。

  使用maven下载安装

  webmagic 使用 maven 来管理依赖,你可以通过在项目中添加相应的依赖来使用 webmagic:

  

us.codecraft

webmagic-core

0.4.2

us.codecraft

webmagic-extension

0.4.2

  项目结构

  webmagic主要包括两个包:

  webmagic 还包括两个可用的扩展包。因为这两个包依赖于比较重量级的工具,所以是从主包中提取出来的。这些包需要在源码之后自行下载编译:

  在您的项目中,您可以根据需要依赖不同的包。

  不使用maven

  不使用maven的用户可以下载带有二进制jar包的版本(感谢oschina):

   git clone http://git.oschina.net/flashsword20/webmagic.git

  在 bin/lib 目录下,可以在 IDE 中直接导入项目所依赖的所有 jar 包。

  第一个爬虫自定义PageProcessor

  PageProcessor 是 webmagic-core 的一部分,您可以通过自定义 PageProcessor 来实现自己的爬虫逻辑。下面是一段爬取 osc 博客的代码:

   public class OschinaBlogPageProcesser implements PageProcessor {

private Site site = Site.me().setDomain("my.oschina.net")

.addStartUrl("http://my.oschina.net/flashsword/blog");

@Override

public void process(Page page) {

List links = page.getHtml().links().regex("http://my\\.oschina\\.net/flashsword/blog/\\d+").all();

page.addTargetRequests(links);

page.putField("title", page.getHtml().xpath("//div[@class='BlogEntity']/div[@class='BlogTitle']/h1").toString());

page.putField("content", page.getHtml().$("div.content").toString());

page.putField("tags",page.getHtml().xpath("//div[@class='BlogTags']/a/text()").all());

}

@Override

public Site getSite() {

return site;

}

public static void main(String[] args) {

Spider.create(new OschinaBlogPageProcesser())

.pipeline(new ConsolePipeline()).run();

}

}

  这里要爬取的URL是通过page.addTargetRequests()方法添加的,提取结果通过page.putField()保存。page.getHtml().xpath() 按照一定的规则提取结果,提取支持链式调用。调用后,toString() 表示转换为单个 String,all() 表示将其转换为 String 列表。

  Spider 是爬虫的入口类。Pipeline 是结果输出和持久化的接口,其中 ConsolePipeline 表示将结果输出到控制台。

  执行这个main方法,可以在控制台看到抓取结果。默认情况下,webmagic 的抓取间隔为 3 秒,请耐心等待。您可以使用 site.setSleepTime(int) 修改此值。该站点还具有一些用于修改爬网属性的方法。

  使用注释

  webmagic-extension 包括通过注解编写爬虫的方法。只需要基于POJO添加注解即可完成爬虫。下面依然是一段抓取oschina博客的代码,功能和OschinaBlogPageProcesser完全一样:

   @TargetUrl("http://my.oschina.net/flashsword/blog/\\d+")

public class OschinaBlog {

@ExtractBy("//title")

private String title;

@ExtractBy(value = "div.BlogContent",type = ExtractBy.Type.Css)

private String content;

@ExtractBy(value = "//div[@class='BlogTags']/a/text()", multi = true)

private List tags;

@Formatter("yyyy-MM-dd HH:mm")

@ExtractBy("//div[@class='BlogStat']/regex('\\d+-\\d+-\\d+\\s+\\d+:\\d+')")

private Date date;

public static void main(String[] args) {

OOSpider.create(

Site.me().addStartUrl("http://my.oschina.net/flashsword/blog"),

new ConsolePageModelPipeline(), OschinaBlog.class).run();

}

}

  本例定义了一个Model类,Model类的“title”、“content”、“tags”字段都是要提取的属性。这个类在 Pipeline 中是可重用的。

  有关如何使用注释的详细信息,请参阅下面的 webmagic-extension 注释模块。

  模块详情 webmagic-core

  webmagic-core是爬虫的核心框架,只收录了爬虫各个功能模块的核心功能。webmagic-core 的目标是成为网络爬虫的教科书实现。

  本节部分内容摘自作者的博文 Webmagic Design Mechanism and Principle - How to Develop a Java Crawler。

  webmagic-core的模块划分

  webmagic-core指scrapy的模块划分,分为Spider(整个爬虫的调度框架)、Downloader(页面下载)、PageProcessor(链接提取和页面分析)、Scheduler(URL管理)、Pipeline(离线分析和持久化) ) 几个部分。只是scrapy是通过中间件扩展的,而webmagic是通过定义这些接口,将它们不同的实现注入到主框架类Spider中来扩展的。

  

  蜘蛛类(核心调度)

  Spider是爬虫的入口类。爬虫的接口调用采用链式API设计,其他所有功能都通过接口注入到爬虫中。以下是启动更复杂爬虫的示例。

   Spider.create(sinaBlogProcessor)

.scheduler(new FileCacheQueueScheduler("/data/temp/webmagic/cache/"))

.pipeline(new FilePipeline())

.thread(10).run();

  Spider的核心处理流程非常简单,代码如下:

   private void processRequest(Request request) {

Page page = downloader.download(request, this);

if (page == null) {

sleep(site.getSleepTime());

return;

}

pageProcessor.process(page);

addRequest(page);

for (Pipeline pipeline : pipelines) {

pipeline.process(page, this);

}

sleep(site.getSleepTime());

}

  Spider还包括一个方法test(String url),只爬取单个页面,用于测试提取效果。

  PageProcessor(页面分析和链接提取)

  页面分析是垂直爬虫中需要定制的部分。在 webmagic-core 中,通过实现 PageProcessor 接口来实现自定义爬虫。PageProcessor 有两个核心方法:public void process(Page page) 和 public Site getSite()。

  Selector 是 webmagic 为简化页面提取和开发而开发的一个独立模块,是 webmagic-core 的主要关注点。它集成了 CSS Selector、XPath 和正则表达式,并且可以进行链式提取。

   //content是用别的爬虫工具抽取到的正文

List links = page.getHtml()

.$("div.title") //css 选择,Java里虽然很少有$符号出现,不过貌似$作为方法名是合法的

.xpath("//@href") //提取链接

.regex(".*blog.*") //正则匹配过滤

.all(); //转换为string列表

  webmagic 收录一个 SmartContentSelector 类,它会自动提取页面的正文。相信 Evernote Clearly 会对它的自动文本提取技术印象深刻。这项技术也称为可读性。当然,webmagic 对 Readability 的实现还是比较粗糙的,但是还是有一些学习价值的。

  webmagic的XPath解析使用了作者的另一个开源项目:Xsoup,一个基于Jsoup的XPath解析器。Xsoup 扩展了 XPath 的语法并支持一些自定义函数。这些函数通过在 XPath 末尾添加 /name-of-function() 来使用,例如:"//div[@class='BlogStat']/regex('\\d+-\\d+-\\ d+ \\s+\\d+:\\d+')"。

  功能

  阐明

  文本(n)

  第 n 个文本节点(0 表示全取)

  全部文本()

  所有文本,包括子节点

  整洁的文本()

  使用智能换行收录子节点的所有文本

  html()

  内部 html(不包括当前标签本身)

  外部HTML()

  外部 html(包括当前标签本身)

  正则表达式(@attr,expr,组)

  正则表达式,@attr为提取属性(可省略),expr为表达式内容,group为捕获组(可省略,默认为0)

  基于 Saxon,webmagic 提供对 XPath2.0 语法的支持。XPath2.0 语法支持内部函数、逻辑控制等,是一门完整的语言。如果你熟悉 XPath2.0 语法,不妨一试(需要引入 webmagic-saxon 包)。

  webmagic-samples 包有一些为站点定制的 PageProcessor 用于学习目的。

  下载器(页面下载)

  Downloader 是 webmagic 中下载页面的接口。主要方法有:

  Downloader 目前有几种实现方式:

  调度程序(URL 管理)

  调度器是webmagic的管理模块。您可以通过实施调度程序自定义您自己的 URL 管理器。调度器主要包括两个方法:

  webmagic 目前有调度器的三种实现:

  管道(后续处理和持久化)

  Pipeline 是输出和持久化最终提取结果的接口。它只包括一种方法:

  webmagic 收录以下 Pipeline 的实现:

  webmagic 目前不支持持久化到数据库,但是结合其他工具,持久化到数据库很容易。这里,我们来看一段webmagic结合JFinal持久化到数据库的代码。因为 JFinal 目前不支持 maven,所以这段代码没有放在 webmagic-samples 中。

  webmagic 扩展

  webmagic-extension是为了方便开发爬虫而实现的一些功能模块。这些功能完全基于webmagic-core框架,包括编写爬虫、分页、以注解形式分发等功能。

  注释模块

  webmagic-extension 收录注释模块。为什么会有注释?

  因为 PageProcessor 的方式灵活而强大,它并没有解决两个问题:

  注解的核心是Model类,它本身就是一个POJO。这个 Model 类用于传递和保存页面,最后获取结果数据。注解方式直接将提取和数据绑定,方便编写和维护。

  注解方法其实是通过一个PageProcessor--ModelPageProcessor的实现来完成的,所以对webmagic-core代码没有影响。还是以抓取OschinaBlog的程序为例:

   @TargetUrl("http://my.oschina.net/flashsword/blog/\\d+")

public class OschinaBlog {

@ExtractBy("//title")

private String title;

@ExtractBy(value = "div.BlogContent",type = ExtractBy.Type.Css)

private String content;

@ExtractBy(value = "//div[@class='BlogTags']/a/text()", multi = true)

private List tags;

@Formatter("yyyy-MM-dd HH:mm")

@ExtractBy("//div[@class='BlogStat']/regex('\\d+-\\d+-\\d+\\s+\\d+:\\d+')")

private Date date;

public static void main(String[] args) {

OOSpider.create(

Site.me().addStartUrl("http://my.oschina.net/flashsword/blog"),

new ConsolePageModelPipeline(), OschinaBlog.class).run();

}

}

  注释部分包括以下内容:

  类型转换

  webmagic的注解方式支持提取结果的类型转换,使得提取结果不需要是String类型,可以是任意类型。webmagic 内置了对基本类型的支持(需要保证提取结果可以转换为对应的类型)。

   @ExtractBy("//ul[@class='pagehead-actions']/li[1]//a[@class='social-count js-social-count']/text()")

private int star;

  提取结果也可以是 java.util.Date 类型,但您需要指定日期的格式:

   @Formatter("yyyy-MM-dd HH:mm")

@ExtractBy("//div[@class='BlogStat']/regex('\\d+-\\d+-\\d+\\s+\\d+:\\d+')")

private Date date;

  您还可以编写一个实现 ObjectFormatter 接口的类来执行您自己的类型解析。要使用您自己的类,您需要调用 ObjectFormatters.put() 来注册该类。

   OOSpider.create(

Site.me().addStartUrl("http://www.oschina.net"),

new ConsolePageModelPipeline(),

OschinaBlog.clas,OschinaAnswer.class).run();

   OOSpider会根据TargetUrl调用不同的Model进行解析。

  分散式

  在 webmagic-extension 中,通过 redis 管理 URL 以达到分布式的效果。但是对于分布式爬虫来说,只有程序可以分布式运行,不能满足*敏*感*词*爬取的需要。Webmagic 以后可能会添加一些任务管理和监控功能。也欢迎用户提交代码并为 webmagic 做出贡献。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线