zoukankan      html  css  js  c++  java
  • 转 Java爬虫(webmagic)

    webMaigc学习地址(强烈推荐):http://www.oschina.net/p/webmagic

    本篇博客只是整理笔记。

      webmagic的是一个无须配置、便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫。webmagic采用完全模块化的设计,功能覆盖整个爬虫的生命周期(链接提取、页面下载、内容抽取、持久化),支持多线程抓取,分布式抓取,并支持自动重试、自定义UA/cookie等功能。

    一、概览

      WebMagic项目代码分为核心和扩展两部分。核心部分(webmagic-core)是一个精简的、模块化的爬虫实现,而扩展部分则包括一些便利的、实用性的功能(例如注解模式编写爬虫等)。 
      WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。这四大组件对应爬虫生命周期中的下载、处理、管理和持久化等功能。而Spider则将这几个组件组织起来,让它们可以互相交互,流程化的执行,可以认为Spider是一个大的容器,它也是WebMagic逻辑的核心。 
       
    WebMagic总体架构图如下: 
    这里写图片描述

    1.1 WebMagic的四个组件

     1.Downloader

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

     2.PageProcessor

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

     3.Scheduler

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

     4.Pipeline

    Pipeline负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。

    1.2 用于数据流转的对象

     1. Request

    Request是对URL地址的一层封装,一个Request对应一个URL地址。它是PageProcessor与Downloader交互的载体,也是PageProcessor控制Downloader唯一方式。

     2. Page

    Page代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。Page是WebMagic抽取过程的核心对象,它提供一些方法可供抽取、结果保存等。

     3. ReusltItems

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

    1.3 控制爬虫运转的引擎—Spider

      Spider是WebMagic内部流程的核心。Downloader、PageProcessor、Scheduler、Pipeline都是Spider的一个属性,这些属性是可以自由设置的,通过设置这个属性可以实现不同的功能。Spider也是WebMagic操作的入口,它封装了爬虫的创建、启动、停止、多线程等功能。 
      对于编写一个爬虫,PageProcessor是需要编写的部分,而Spider则是创建和控制爬虫的入口。

    1.4 webMagic项目组成

    WebMagic项目代码包括几个部分,在根目录下以不同目录名分开。它们都是独立的Maven项目。 
    WebMagic主要包括两个包,这两个包经过广泛实用,已经比较成熟:

     1.webmagic-core 
    webmagic-core是WebMagic核心部分,只包含爬虫基本模块和基本抽取器。

     2.webmagic-extension 
    webmagic-extension是WebMagic的主要扩展模块,提供一些更方便的编写爬虫的工具。包括注解格式定义爬虫、JSON、分布式等支持。

     3.实验性包 
     包括webmagic-samples、webmagic-scripts、webmagic-selenium等;

    二、使用webMagic

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

    <dependency>
        <groupId>us.codecraft</groupId>
        <artifactId>webmagic-core</artifactId>
        <version>0.5.3</version>
    </dependency>
    <dependency>
        <groupId>us.codecraft</groupId>
        <artifactId>webmagic-extension</artifactId>
        <version>0.5.3</version>
    </dependency>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    不使用maven的用户,可以去http://webmagic.io中下载最新的jar包。

    三、基本的爬虫

      在WebMagic里,实现一个基本的爬虫只需要编写一个类,实现PageProcessor接口即可。这个类基本上包含了抓取一个网站,你需要写的所有代码。

    1 实现PageProcessor

    a、爬虫的配置

    // 部分一:抓取网站的相关配置,包括编码、抓取间隔、重试次数等
        private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
    • 1
    • 2

    b、页面元素的抽取 
      对于下载到的Html页面,你如何从中抽取到你想要的信息?WebMagic里主要使用了三种抽取技术:XPath、正则表达式和CSS选择器。另外,对于JSON格式的内容,可使用JsonPath进行解析。 
       
    b-1、XPath

    XPath本来是用于XML中获取元素的一种查询语言,但是用于Html也是比较方便的。例如:

    page.getHtml().xpath("//h1[@class='entry-title public']/strong/a/text()")
    • 1

    这段代码使用了XPath,它的意思是“查找所有class属性为’entry-title public’的h1元素,并找到他的strong子节点的a子节点,并提取a节点的文本信息”。

    b-2、CSS选择器

    CSS选择器是与XPath类似的语言。如果大家做过前端开发,肯定知道$(‘h1.entry-title’)这种写法的含义。客观的说,它比XPath写起来要简单一些,但是如果写复杂一点的抽取规则,就相对要麻烦一点。

    b-3、正则表达式

    正则表达式则是一种通用的文本抽取语言。  

    page.addTargetRequests(page.getHtml().links().regex("(https://github\.com/\w+/\w+)").all());
    • 1

    这段代码就用到了正则表达式,它表示匹配所有”https://github.com/code4craft/webmagic“这样的链接。

    b-4、JsonPath

    JsonPath是于XPath很类似的一个语言,它用于从Json中快速定位一条内容。WebMagic中使用的JsonPath格式可以参考这里:https://code.google.com/p/json-path/

    c、链接的延伸

    一个站点的页面是很多的,一开始我们不可能全部列举出来,于是如何发现后续的链接,是一个爬虫不可缺少的一部分。

    page.addTargetRequests(page.getHtml().links().regex("(https://github\.com/\w+/\w+)").all());
    • 1

    这段代码的分为两部分,page.getHtml().links().regex(“(https://github.com/w+/w+)”).all()用于获取所有满足”(https:/ /github.com/w+/w+)”这个正则表达式的链接,page.addTargetRequests()则将这些链接加入到待抓取的队列中去。

    2 使用Selectable的链式API

      Selectable相关的链式API是WebMagic的一个核心功能。使用Selectable接口,你可以直接完成页面元素的链式抽取,也无需去关心抽取的细节。 
      实现Selectable接口,这个接口包含一些重要的方法,我将它分为两类:抽取部分和获取结果部分。 
       
    a-1 抽取部分API 
      这里写图片描述 
    例如,我现在要抓取github上所有的Java项目,这些项目可以在https://github.com/search?l=Java&p=1&q=stars%3A%3E1&s=stars&type=Repositories搜索结果中看到。为了避免抓取范围太宽,我指定只从分页部分抓取链接。这个抓取规则是比较复杂的,我会要怎么写呢? 
    这里写图片描述

    首先看到页面的html结构是这个样子的: 
    这里写图片描述 
    那么我可以先用CSS选择器提取出这个div,然后在取到所有的链接。为了保险起见,我再使用正则表达式限定一下提取出的URL的格式,那么最终的写法是这样子的:

    List<String> urls = page.getHtml().css("div.pagination").links().regex(".*/search/?l=java.*").all();
    • 1

    然后,我们可以把这些URL加到抓取列表中去:

    List<String> urls = page.getHtml().css("div.pagination").links().regex(".*/search/?l=java.*").all();
    page.addTargetRequests(urls);
    • 1
    • 2

    a-2 获取结果的API

      当链式调用结束时,我们一般都想要拿到一个字符串类型的结果。这时候就需要用到获取结果的API了。我们知道,一条抽取规则,无论是XPath、CSS选择器或者正则表达式,总有可能抽取到多条元素。WebMagic对这些进行了统一,你可以通过不同的API获取到一个或者多个元素。 
      这里写图片描述 
       
    3 保存结果

      WebMagic用于保存结果的组件叫做Pipeline。如我们通过“控制台输出结果”可以通过一个内置的ConsolePipeline来完成。想要把结果用Json的格式保存下来,可以将Pipeline的实现换成”JsonFilePipeline”。 
      通过定制Pipeline,我们还可以实现保存结果到文件、数据库等一系列功能。

    4 爬虫的配置、启动和终止

    a-1 Spider

    Spider是爬虫启动的入口。在启动爬虫之前,我们需要使用一个PageProcessor创建一个Spider对象,然后使用run()进行启动。同时Spider的其他组件(Downloader、Scheduler、Pipeline)都可以通过set方法来进行设置。 
    这里写图片描述 
    这里写图片描述

    a-2  Site

    对站点本身的一些配置信息,例如编码、HTTP头、超时时间、重试策略等、代理等,都可以通过设置Site对象来进行配置。 
    这里写图片描述

    5 抽取工具简介

    WebMagic的抽取主要用到了Jsoup和我自己开发的工具Xsoup。

    a-1 Jsoup

    Jsoup是一个简单的HTML解析器,同时它支持使用CSS选择器的方式查找元素。为了开发WebMagic,我对Jsoup的源码进行过详细的分析,具体文章参见Jsoup学习笔记

    a-2 Xsoup

    Xsoup是我基于Jsoup开发的一款XPath解析器。

    a-3 3 Saxon

    Saxon是一个强大的XPath解析器,支持XPath 2.0语法。webmagic-saxon是对Saxon尝试性的一个整合,但是目前看来,XPath 2.0的高级语法,似乎在爬虫开发中使用者并不多。

    6 爬虫的监控

    你可以查看爬虫的执行情况——已经下载了多少页面、还有多少页面、启动了多少线程等信息。该功能通过JMX实现,你可以使用Jconsole等JMX工具查看本地或者远程的爬虫信息。

    注意: 如果你自己定义了Scheduler,那么需要用这个类实现MonitorableScheduler接口,才能查看“LeftPageCount”和“TotalPageCount”这两条信息。

    6.1 为项目添加监控

    添加监控非常简单,获取一个SpiderMonitor的单例SpiderMonitor.instance(),并将你想要监控的Spider注册进去即可。你可以注册多个Spider到SpiderMonitor中。

    public class MonitorExample {
    
        public static void main(String[] args) throws Exception {
    
            Spider oschinaSpider = Spider.create(new OschinaBlogPageProcessor())
                    .addUrl("http://my.oschina.net/flashsword/blog");
            Spider githubSpider = Spider.create(new GithubRepoPageProcessor())
                    .addUrl("https://github.com/code4craft");
    
            SpiderMonitor.instance().register(oschinaSpider);
            SpiderMonitor.instance().register(githubSpider);
            oschinaSpider.start();
            githubSpider.start();
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.2 查看监控信息

    WebMagic的监控使用JMX提供控制,你可以使用任何支持JMX的客户端来进行连接。我们这里以JDK自带的JConsole为例。我们首先启动WebMagic的一个Spider,并添加监控代码。然后我们通过JConsole来进行查看。

    我们按照4.6.1的例子启动程序,然后在命令行输入jconsole(windows下是在DOS下输入jconsole.exe)即可启动JConsole。 
    这里写图片描述 
    这里我们选择启动WebMagic的本地进程,连接后选择“MBean”,点开“WebMagic”,就能看到所有已经监控的Spider信息了!

    6.3 扩展监控接口

    除了已有的一些监控信息,如果你有更多的信息需要监控,也可以通过扩展的方式来解决。你可以通过继承SpiderStatusMXBean来实现扩展,具体例子可以看这里: 定制扩展demo

    四、使用注解编写爬虫

    WebMagic支持使用独有的注解风格编写一个爬虫,引入webmagic-extension包即可使用此功能。

    注解模式的开发方式是这样的:

    1.首先定义你需要抽取的数据,并编写类。 
    2.在类上写明@TargetUrl注解,定义对哪些URL进行下载和抽取。 
    3.在类的字段上加上@ExtractBy注解,定义这个字段使用什么方式进行抽取。 
    4.定义结果的存储方式。 
    代码如:

    @TargetUrl("https://github.com/\w+/\w+")
    @HelpUrl("https://github.com/\w+")
    public class GithubRepo {
    
        @ExtractBy(value = "//h1[@class='entry-title public']/strong/a/text()", notNull = true)
        private String name;
    
        @ExtractByUrl("https://github\.com/(\w+)/.*")
        private String author;
    
        @ExtractBy("//div[@id='readme']/tidyText()")
        private String readme;
    
        public static void main(String[] args) {
            OOSpider.create(Site.me().setSleepTime(1000)
                    , new ConsolePageModelPipeline(), GithubRepo.class)
                    .addUrl("https://github.com/code4craft").thread(5).run();
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    具体参考:http://webmagic.io/docs/zh/posts/ch5-annotation/README.html

  • 相关阅读:
    hibernate update部分更新
    strtus2.0实现下载
    cookie和session机制之间的区别与联系
    生成随机数字验证码
    ssh生成随机数字验证码
    ASP一句话轻松获取域上的用户名
    SQL server 日志文件清除
    Entity Framework中使用DbMigrator更新数据库至最新结构
    进程间通信
    asp备份SQL数据库
  • 原文地址:https://www.cnblogs.com/lyf906522290/p/8085990.html
Copyright © 2011-2022 走看看