Java开发语言是业界使用最广泛的编程语言之一,在互联网行业中拥有众多使用者。Java网络爬虫能够帮助开发人员以快捷、简单且多样化的方式抓取各种数据。谈到网络爬虫,许多人会首先想到Python语言,因为Python拥有丰富的网络爬虫资源和框架,使得上手更加便捷。然而,实际上Java网络爬虫领域也有许多优秀的开源框架和库可供使用。图1-1展示了某网站在某一年度评选出的最受欢迎的50个网络爬虫开源框架或库,从该排名可以看出Java网络爬虫的应用同样非常广泛。
接下来简单介绍几款Java开源网络爬虫框架,感兴趣的读者可以自行下载、安装,并阅读相关源代码。
图1-1 开源爬虫框架列表
Heritrix是一款历史悠久的Java网络爬虫框架。它曾被广泛使用,许多开发人员和研究人员都依赖Heritrix来采集数据,以便为后续的数据分析和数据挖掘工作做准备。接下来将以1.0.0版本为基础,介绍Heritrix的整体架构和工作流程。Heritrix的主要组件包括Web Administrative Console、CrawlJob、CrawlController、Frontier、ToeThreads和Processor等。其整体结构如图1-2所示。
当用户在Heritrix的Web界面上配置完爬取任务信息后,对应的CrawlJob对象会被创建,CrawlJobHandler会将CrawlJob对象提交给CrawlController对象,CrawlController对象从CrawlJob对象中提取出CrawlOrder并初始化爬取任务相关的所有其他模块。
Heritrix采用了良好的模块化设计,这些模块由一个采集控制器类(CrawlController)来协调调度。CrawlController在架构中处于核心地位,在CrawlController的调度管理下,一次完整的数据爬取流程示例如图1-3所示。
图1-2 Heritrix整体架构
图1-3 Heritrix爬取任务处理流程
如图1-3所示,Heritrix爬取任务的处理流程如下:
(1)Frontier组件从CrawlScope组件中获取种子URL列表。
(2)ToeThread组件根据调度规则从Frontier组件中获取下一个需要处理的CrawlURI对象。
(3)ToeThread组件与CrawlScope组件进行交互,检查待处理CrawlURI对象是否在处理范围内。
(4)爬取任务进入处理链处理环节。prefetch processors会再次根据过滤器中的过滤规则检查CrawlURI对象是否符合过滤规则。
(5)fetch processors访问网页内容,并且将获取到的网页内容添加到CrawlURI对象中。
(6)extract processors会从网页内容中提取业务需要的内容或数据,同时将提取到的URLs添加到CrawlURI对象中。
(7)write processors对爬取到的内容进行持久化存储,并将数据流继续传递给post processors。
(8)post processors检查extract processors提取到的URLs是否在爬取任务规定的爬取范围内。如果URL在爬取范围内,则会将其提交给Frontier组件。
(9)ToeThread将CrawlURI处理结果提交给Frontier组件。
Norconex是一款非常优秀的开源企业级爬虫框架。笔者认为,Norconex Web Crawler有两个功能值得关注:
(1)支持多种类型的HTML文档下载器。当我们要采集网页中的特定信息时,首先要能够下载网页的内容。Norconex提供了GenericHttpFetcher来满足大部分场景的需求,但在某些情况下,可能需要更专业的方式来获取网络资源。例如,对于通过JavaScript异步加载的网页内容,用WebDriverHttpFetcher来获取网页内容更合适。当然,我们也可以开发自定义的HTML文档下载器。
(2)提供了HTTP请求头和HTTP响应头的监听器和修改器。Norconex基于BrowserMobProxy实现了HTTP请求头和HTTP响应头的监听器和修改器(HttpSniffer)。HttpSniffer使得对WebDriverHttpFetcher请求和响应内容的监控更加方便,也可以帮助开发者动态修改HTTP请求内容和响应内容。
Crawler4j是一个用Java开发语言编写的开源项目,Crawler4j为使用者提供了简单易用的API,依赖该框架,开发者可以很方便地配置和启动一个Web网页爬虫项目。Crawler4j的主要功能由两个核心类实现:WebCrawler和CrawlerController。WebCrawler类实现了Runnable接口,开发者可以对WebCrawler类进行扩展,从而实现自定义的爬取任务。每一个自定义的WebCrawler实例都可以独立运行在各自的线程中,但是这些WebCrawler实例会共享由CrawlController管理的配置信息。CrawlController负责管理整个爬取任务会话,其主要功能包括:
(1)CrawlController会创建线程并启动指定数量的WebCrawler实例,从而实现爬取任务的并发执行。
(2)CrawlController会创建一个monitor线程来监控各个WebCrawler实例的工作状态和整个爬取任务的爬取进度。
(3)CrawlController负责管理种子URL列表,这些种子URL是整个爬取任务的起点。
(4)CrawlController支持各种爬取任务的参数配置,例如礼貌等待时间、最大爬取深度、最大爬取数量等。
它的主要工作流程如图1-4所示。
Crawler4j的主要缺点是不支持动态网页的抓取,但是我们可以基于Crawler4j进行二次开发,通过扩展PageFetcher,使它支持动态网页内容的抓取。
图1-4 Crawler4j工作流程