zoukankan      html  css  js  c++  java
  • JAVA爬虫 WebCollector

    JAVA爬虫 WebCollector

    爬虫简介:

    WebCollector是一个无须配置、便于二次开发的JAVA爬虫框架(内核),它提供精简的的API,只需少量代码即可实现一个功能强大的爬虫。

    爬虫内核:

    WebCollector 致力于维护一个稳定、可扩的爬虫内核,便于开发者进行灵活的二次开发。内核具有很强的扩展性,用户可以在内核基础上开发自己想要的爬虫。源码中集成了 Jsoup,可进行精准的网页解析。2.x版本中集成了selenium,可以处理javascript生成的数据。

    网页正文提取:

    网页正文提取项目ContentExtractor已并入WebCollector维护。
    WebCollector的正文抽取API都被封装为ContentExtractor类的静态方法。 可以抽取结构化新闻,也可以只抽取网页的正文(或正文所在Element)。
    正文抽取效果指标 :

    • 比赛数据集CleanEval P=93.79% R=86.02% F=86.72%
    • 常见新闻网站数据集 P=97.87% R=94.26% F=95.33%
    • 算法无视语种,适用于各种语种的网页

    标题抽取和日期抽取使用简单启发式算法,并没有像正文抽取算法一样在标准数据集上测试,算法仍在更新中。


    1.x:

    WebCollector 1.x版本现已转移到http://git.oschina.net/webcollector/WebCollector-1.x维护,建议使用2.x版本。

    2.x:

    WebCollector 2.x版本特性:

    • 1)自定义遍历策略,可完成更为复杂的遍历业务,例如分页、AJAX

    • 2)内置Berkeley DB管理URL,可以处理更大量级的网页

    • 3)集成selenium,可以对javascript生成信息进行抽取

    • 4)直接支持多代理随机切换

    • 5)集成spring jdbc和mysql connector,方便数据持久化

    • 6)集成json解析器

    • 7)使用slf4j作为日志门面

    • 8)修改http请求接口,用户自定义http请求更加方便

    WebCollector 2.x官网和镜像:

    WebCollector 2.x教程:

    WebCollector 2.x教程(镜像):

    版本更新信息:

        WebCollector 2.10 发布,更新详情如下:

    • 1 ) 新增新闻网页正文自动提取算法,可自动抽取新闻网页正文、标题和日期,可参照例子:WebCollector正文提取DEMO

        WebCollector 2.09 发布,更新详情如下:

    • 1 ) 新增抽取器Extractor和用于加载抽取器的爬虫MultiExtractorCrawler,提供一种方便分工和维护的爬虫开发方案。可参照例子: WebCollector抽取器DEMO

    • 2 ) 新增FileSystemOutput,可将网页按照网站拓扑结构存储到本地。

    • 3 ) 修复https请求证书问题。



    WebCollector is an open source web crawler framework based on Java.It provides some simple interfaces for crawling the Web,you can setup a multi-threaded web crawler in less than 5 minutes. — More...

    Issues
    #10 请问如何不让日志输出到控制台 by T0ky04cti0n  2015-08-03
    #9 请问WeiboHelper的源码是否可以公开? by DongShuaike  2015-08-01
    #8 请问2.x的maven仓库在哪儿? by fishtrees  2015-06-29
    #7 是否支持Proxy? 另外如果支持的话,是否支持动态的轮换? by RangerWolf  2015-05-05
    #5 爬取ajax或者是js跳转的页面怎么设置策略? by joe1100  2015-06-06

    master分支代码最近更新:2015-08-05

    下载zip
     
     
     
     

    WebCollector

    主页: https://github.com/CrawlScript/WebCollector

    WebCollector使用了Nutch的爬取逻辑(分层广度遍历),Crawler4j的的用户接口(覆盖visit方法,定义用户操作),以及一套自己的插件机制,设计了一套爬虫内核。

    WebCollector内核构架图:

    CrawlDB: 任务数据库,爬虫的爬取任务(类似URL列表)是存放在CrawlDB中的,CrawlDB根据DbUpdater和Generator所选插件不同,可以有多种形式,如文件、redis、mysql、mongodb等。

    Injector: 种子注入器,负责第一轮爬取时,向CrawlDB中提交爬取任务。在断点续爬的时候,不需要通过Injector向CrawlDB注入种子,因为CrawlDB中已有爬取任务。

    Generator: 任务生成器,任务生成器从CrawlDB获取爬取任务,并进行过滤(正则、爬取间隔等),将任务提交给抓取器。

    Fetcher: 抓取器,Fetcher是爬虫最核心的模块,Fetcher负责从Generator中获取爬取任务,用线程池来执行爬取任务,并对爬取的网页进行链接解 析,将链接信息更新到CrawlDB中,作为下一轮的爬取任务。在网页被爬取成功/失败的时候,Fetcher会将网页和相关信息以消息的形式,发送到 Handler的用户自定义模块,让用户自己处理网页内容(抽取、存储)。

    DbUpdater: 任务更新器,用来更新任务的状态和加入新的任务,网页爬取成功后需要更新CrawlDB中的状态,对网页做解析,发现新的连接,也需要更新CrawlDB。

    Handler: 消息发送/处理器,Fetcher利用Handler把网页信息打包,发送到用户自定义操作模块。

    User Defined Operation: 用户自定义的对网页信息进行处理的模块,例如网页抽取、存储。爬虫二次开发主要就是自定义User Defined Operation这个模块。实际上User Defined Operation也是在Handler里定义的。

    RequestFactory: Http请求生成器,通过RequestFactory来选择不同的插件,来生成Http请求,例如可以通过httpclient插件来使用httpclient作为爬虫的http请求,或者来使用可模拟登陆新浪微博的插件,来发送爬取新浪微博的http请求。

    ParserFactory: 用来选择不同的链接分析器(插件)。爬虫之所以可以从一个网页开始,向多个网页不断地爬取,就是因为它在不断的解析已知网页中的链接,来发现新的未知网页,然后对新的网页进行同样的操作。

    爬取逻辑:

    WebCollector和Nutch一样,把爬虫的广度遍历拆分成了分层的操作。

    第一层:爬取一个网页,http://www.apache.org/,解析网页,获取3个链接,将3个链接保存到CrawlDB中,设置状态为未爬取。同时将http://www.apache.org/的爬取状态设置为已爬取。结束第一轮。

    第二层,找到CrawlDB中状态为未爬取的页面(第一层解析出来的3个链接),分别爬取,并解析网页,一共获得8个链接。和第一层操作一样,将解析出的链接放入CrawlDB,设置为未爬取,并将第二层爬取的三个页面,状态设置为已爬取。

    第三层,找到CrawlDB中状态为未爬取的页面(第二层解析出来的8个链接).................

    每一层都可以作为一个独立的任务去运行,所以可以将一个大型的广度遍历任务,拆分成一个一个小任务。爬虫里有个参数,设置爬取的层数,指的就是这个。

    插件机制:

    框 架图中的 Injector、Generator、Request(由RequestFactory生成)、Parser(由ParserFactory生成)、 DbUpdater、Response都是以插件实现的。制作插件往往只需要自定义一个实现相关接口的类,并在相关Factory内指定即可。

    WebCollector 内置了一套插件( cn . edu . hfut . dmic . webcollector . plugin . redis )。基于这套插件,可以把WebCollector的任务管理放到redis数据库上,这使得WebCollector可以爬取海量的数据(上亿级别)。

    用户自定义操作:

    对于用户来说,关注的更多的不是爬虫的爬取流程,而是对每个网页要进行什么样的操作。对网页进行抽取、保存还是其他操作,应该是由用户自定义的。

    假设我们有个需求,要爬取《知乎》上的所有提问。对用户来说,只需要定义对知乎的提问如何抽取。

    public class ZhihuCrawler extends BreadthCrawler{
    
      /*visit函数定制访问每个页面时所需进行的操作*/
      @Override
      public void visit(Page page) {
        String question_regex="^http://www.zhihu.com/question/[0-9]+";
        if(Pattern.matches(question_regex, page.getUrl())){
          System.out.println("正在抽取"+page.getUrl());
          /*抽取标题*/
          String title=page.getDoc().title();
          System.out.println(title);
          /*抽取提问内容*/
          String question=page.getDoc().select("div[id=zh-question-detail]").text();
          System.out.println(question);
    
        }
      }
    
      /*启动爬虫*/
      public static void main(String[] args) throws IOException{  
        ZhihuCrawler crawler=new ZhihuCrawler();
        crawler.addSeed("http://www.zhihu.com/question/21003086");
        crawler.addRegex("http://www.zhihu.com/.*");
        crawler.start(5);  
      }
    
    }

    覆盖BreadthCrawler类的visit方法,即可实现用户自定义操作,完全不用考虑爬虫的爬取逻辑。

    WebCollector的设计主要来自于Nutch,相当于将Nutch抽象成了一个爬虫内核。

     
     
     
     
     

    WebCollector是一个无须配置、便于二次开发的JAVA爬虫框架(内核),它 提供精简的的API ,只需少量代码即可实现一个功能强大的爬虫。

    如何将WebCollector导入项目请看下面这个教程:

    JAVA网络爬虫WebCollector深度解析——爬虫内核

    参数:

    WebCollector无需繁琐配置,只要在代码中给出下面几个必要参数,即可启动爬虫:

    1.种子(必要):

    种子即爬虫的起始页面。一个爬虫可添加一个或多个种子。

    2.正则(可选):

    正则是约束爬取范围的一些正则式。正则不一定要给出。如果用户没有给出正则,系统会自动将爬取范围限定在种子的域名内。

    3.线程数(可选):

    WebCollector是一个多线程的爬虫,默认使用10个线程同时工作。开发者可以自定义线程数。

    需求:

    简述一下教程里代码的功能:定制一个爬虫,对“知乎”网站进行爬取,不要求下载所有的网页和文件,而是要求对知乎中所有的“提问”页面中的”问题“进行提取。如图:

    我们需要提取问题标题:“看了《蝙蝠侠》,如果我闯进纽交所,逼迫所有人卖掉他手里的所有的股票期货债券什么的,会有什么毁灭性后果?",

    以及问题的内容:“咱不讨论这可行性,我就想听听这有什么毁灭性那个的后果么?再比如百度,58,新东方什么的在那上市的中国公司?再比如会对其他的比如伦敦交易所什么的影响?中国股市的影响?再比如对其他货币的影响之类的?“

    代码:

    代码分为两部分,爬取器和控制器。

    爬取器通过Override父类中的visit方法(即对每个正在爬取的页面需要进行的操作),来定制自己的爬取任务。

    控制器通过给爬取器设置参数(上面所说的种子、正则、线程数),启动爬取器来完成控制功能。

    1.爬取器:

    WebCollector中集成了多种爬取器(主要是遍历算法不同),最常用的遍历器是BreadthCrawler,它是基于广度遍历的算法进行爬取的。我们新建一个JAVA类ZhihuCrawler,继承BreadthCrawler,来定制我们的爬取器。

    public class ZhihuCrawler extends BreadthCrawler{	/*		visit函数定制访问每个页面时所需进行的操作	*/	@Override	public void visit(Page page) {		String question_regex="^http://www.zhihu.com/question/[0-9]+";		if(Pattern.matches(question_regex, page.url)){			System.out.println("正在抽取"+page.url);			String title=page.doc.title();			System.out.println(title);			String question=page.doc.select("div[id=zh-question-detail]").text();			System.out.println(question);					}	}}

    代码解析:

    《知乎》中有很多种网页:提问网页、用户个人信息网页、专页。我们现在只要对提问网页进行操作。

    提问网页的URL一般如下: http://www.zhihu.com/question/21962447

    question_regex是所有提问网页的正则表达式,代码中:

    if(Pattern.matches(question_regex, page.url)){//操作代码 }

    保证我们只对“提问”页面进行抽取。

    visit函数的参数Page page,是一个已经爬取并解析成DOM树的页面。Page的源码

    package cn.edu.hfut.dmic.webcollector.model;import java.util.List;import java.util.Map;import org.jsoup.nodes.Document;/***Page表示一个Web页面*/public class Page{		public String url=null;	public byte[] content=null;	public Map<String,List<String>> headers;	public String html=null;	public Document doc=null;	public int status;	public long fetchtime;		public static final int UNFETCHED=1;	public static final int FETCHED=2;	}

    url指网页的url。

    content是网页的源码字节数组(其实是网页/文件的字节码,大部分情况下可以认为是网页源码)。

    headers是爬取时的http响应头信息。

    html是网页源码字符串(如果html不为null,即为经过编码识别后转换的html源码)。

    doc(DOM树),这里的doc是JSOUP的Document,如果需要做HTML解析、抽取,使用doc是不二的选择,关于doc的使用方法,可参考JSOUP的教程:

    http://www.open-open.com/jsoup/selector-syntax.htm

    status表示网页的抓取状态,status的取值可以是UNFETCHED(未抓取)或者FETCHED(已抓取)。

    fetchtime表示网页抓取的时间,是通过 System.currentTimeMillis ()方法获取的系统时间。

    ZhihuCrawler中用到了page.url和page.doc。

    我们可以发现,《知乎》提问页面的网页标题就是问题的标题,所以通过:

    String title=page.doc.title();

    就获取了提问标题。

    抽取《知乎》提问页面的提问内容,需要从HTML源码观察规则:

    <div class="zm-editable-content">咱不讨论这可行性,我就想听听这有什么毁灭性那个的后果么?<br>再比如百度,58,新东方什么的在那上市的中国公司?<br>再比如会对其他的比如伦敦交易所什么的影响?中国股市的影响?<br>再比如对其他货币的影响之类的?<a name="edit" class="zu-edit-button" href="javascript:;"><i class="zu-edit-button-icon"></i>修改</a></div>

    对于《知乎》所有的提问界面,我们发现,提问内容都被放在一个class="zm-editable-content"的div中,这是JSOUP最适合适用的一种情况。我们只要找到这个div,将其中的文本(text)取出即可:

    String question=page.doc.select("div[id=zh-question-detail]").text();

    2.控制器:

    我们需要一个控制器来启动爬取器:

    public class Controller {public static void main(String[] args) throws IOException{ ZhihuCrawler crawler=new ZhihuCrawler();crawler.addSeed("http://www.zhihu.com/question/21003086");crawler.start(5); }}

    首先实例化刚定义的ZhihuCrawler(爬取器)。

    给爬取器一个种子: http://www.zhihu.com/question/21003086

    crawler.start(5)并不是表示开启5个线程爬取,5表示爬取的深度(广度遍历的层数)。

    运行Controller这个类,会发现不断有输出产生,但是输出比较杂乱,这是因为我们不仅输出了我们抽取的提问,还输出了爬虫的日志(爬取记录等):

    fetch:http://www.zhihu.com/people/lxjtsfetch:http://www.zhihu.com/question/24597698正在抽取http://www.zhihu.com/question/24597698小米4采用304不锈钢除了提升质感和B格,还有其他的实际好处么? - 知乎信号会不会跟ip4一样悲剧了……fetch:http://www.zhihu.com/topic/20006139fetch:http://www.zhihu.com/topic/19559450fetch:http://www.zhihu.com/question/20014415#fetch:http://www.zhihu.com/collection/31102864fetch:http://www.zhihu.com/topic/19663238fetch:http://www.zhihu.com/collection/20021567

    上面的输出片段中,我们可以看到一次visit函数的执行,访问了 http://www.zhihu.com/question/24597698 ,对问题的标题进行了抽取:“小米4采用304不锈钢除了提升质感和B格,还有其他的实际好处么? - 知乎”,同时也抽取了问题的内容:“信号会不会跟ip4一样悲剧了……“。

    "fetch:http://www.zhihu.com/question/24597698"是日志的输出,表示一个已经爬取的网页。

    如果您想看到干净的爬取结果,有下面几种解决方案:

    1.在ZhihuCrawler的visit方法里,添加代码,将title和question字符串输出到文件中。

    2.在ZhihuCrawler的visit方法里,添加代码,将title和question字符串提交到数据库(推荐)。

    可能有人会疑问,为什么我们给爬虫添加种子的时候不添加《知乎》的首页,这是因为《知乎》首页在不登录的情况下会默认返回登录页面。

    动态网页爬取例子(WebCollector+selenium+phantomjs)http://www.2cto.com/kf/201506/407058.html

    包含了一套爬虫的内核和一套完整的爬虫。内核具有很强的扩展性,用户可以在内核基础上开发自己想要的爬虫。源码中集成了Jsoup,可进行精准的网页解析。

  • 相关阅读:
    农场灌溉问题(回溯)
    六数码问题(广搜_队列)
    求图像周长(回溯)
    六数码问题(回溯)
    花生米(四)
    活动安排(贪心算法)
    自我介绍
    三位老师
    培训期间
    工作十个月感触
  • 原文地址:https://www.cnblogs.com/timssd/p/4719822.html
Copyright © 2011-2022 走看看