扩展 Heritrix
我们先来分析一下 Heritrix 的总体结构和 URI 的处理链。
Heritrix 的总体结构
Heritrix 采用了模块化的设计,用户可以在运行时选择要用的模块。它由核心类(core classes)和插件模块(pluggable modules)构成。核心类可以配置,但不能被覆盖,插件模块可以由第三方模块取代。所以我们就可以用实现了特定抓取逻辑的第三方模块来取代默认的插件模块,从而满足自己的抓取需要。
Heritrix 的整体结构如图 18 所示。其中 CrawlController(下载控制器)整个下载过程的总控制者,整个抓取工作的起点,决定整个抓取任务的开始和结束。每个 URI 都有一个独立的线程,它从边界控制器(Frontier)获取新的 URI,然后传递给 Processor chains(处理链)经过一系列 Processor(处理器)处理。
图 18. Heritrix 整体结构
![图 18. Heritrix 整体结构](https://i-blog.csdnimg.cn/blog_migrate/fb940521cd172c2e31d1e3b1f288d50b.png)
URI 处理流程
处理链由多个处理器组成,共同完成对 URI 的处理,如图 19 所示。
图 19. URI 处理链
![图 19. URI 处理链](https://i-blog.csdnimg.cn/blog_migrate/d8b2bc2c1b2de22310697fdccab5ace0.png)
1)Pre-fetch processing chain( 预处理链 ),用来判断抓取时的一些先决条件,如 robot 协议、DNS 等。
2)Fetch processing chain(抓取处理链),解析网络传输协议,从远程服务器获取数据。
3)Extractor processing chain(抽取处理链),从网页中抽取新的 URL。
4)Write/index processing chain(写处理链),负责把数据写入本地磁盘。
5)Post-processing chain(后置处理链),在整个抓取解析过程结束后,进行一些扫尾工作,比如将前面 Extractor 解析出来的 URL 有条件的加入到待处理队列中去。这里我们只需要控制加入到待处理队列中的 URL,就可以控制抓取的范围。
扩展 FrontierScheduler 来抓取特定网站内容
FrontierScheduler 是 org.archive.crawler.postprocessor 包中的一个类,它的作用是将在 Extractor 中所分析得出的链接加入到 Frontier 中,以待继续处理。在该类的 innerProcess(CrawlURI) 函数中,首先检查当前链接队列中是否有一些属于高优先级的链接。如果有,则立刻转走进行处理;如果没有,则对所有的链接进行遍历,然后调用 Frontier 中的 schedule() 方法加入队列进行处理。其代码如图 20 所示。
图 20. FrontierScheduler 类中的 innerProcess() 和 schedule() 函数
![图 20. FrontierScheduler 类中的 innerProcess() 和 schedule() 函数](https://i-blog.csdnimg.cn/blog_migrate/924241a57b9479e2b5064516d9d99bab.png)
从上面的代码可以看出 innerProcess() 函数并未直接调用 Frontier 的 schedule() 方法,而是调用自己内部的 schedule() 方法,进而在这个方法中再调用 Frontier 的 schedule() 方法。而 FrontierScheduler 的 schedule() 方法实际上直接将当前的候选链接不加任何判断地直接加入到抓取队列当中了。这种方式为 FrontierScheduler 的扩展留出了很好的接口。
这里我们需要构造一个 FrontierScheduler 的派生类 FrontierSchedulerForBjfu,这个类重载了 schedule(CandidateURI caUri) 这个方法,限制抓取的 URI 必须包含“bjfu”,以保证抓取的链接都是北林内部的地址。派生类 FrontierSchedulerForBjfu 具体代码如图 21 所示。
图 21. 派生类 FrontierSchedulerForBjfu
![图 21. 派生类 FrontierSchedulerForBjfu](https://i-blog.csdnimg.cn/blog_migrate/d0a9fa0c4a57d99bd463b26724277de0.png)
然后,在 modules 文件夹中的 Processor.options 中添加一行“org.archive.crawler.postprocessor.FrontierSchedulerForBjfu|FrontierSchedulerForBjfu”,这样在爬虫的 WebUI 中就可以选择我们扩展的 org.archive.crawler.postprocessor.FrontierSchedulerForBjfu 选项。如图 22 所示。
图 22. 用 FrontierSchedulerForBjfu 代替 FrontierScheduler
![图 22. 用 FrontierSchedulerForBjfu 代替 FrontierScheduler](https://i-blog.csdnimg.cn/blog_migrate/4fd38794e0249f50c6bd69dac90745ff.png)
最终抓取的页面如图 23 所示,全部都是 http://www.bjfu.edu.cn下的页面。是不是很简单呢?当然,如果只是想实现这个抓取目标,不用修改源代码,通过在 Web UI 中设置抓取规则也可以满足要求。本文只是以此为例说明 Heritrix 如何扩展 Heritrix。
图 23. 扩展后的抓取效果
![图 23. 扩展后的抓取效果](https://i-blog.csdnimg.cn/blog_migrate/dec37b2ec36ed9662aeafb56b1853a6a.png)