刘晓东 林凤德 朱文欢
摘 要:网络爬虫是实现数据分析的重要基础,通过网络爬虫可实现对数据的获取。针对爬虫的渠道广、数量多且杂、单点效率低的问题,引入了轻量级的多线程爬虫框架Crawler4j和分布式定时任务调度框架Quartz,文章主要基于这两个框架来搭建稳定、高效的分布式爬虫系统。
关键词:网络爬虫;分布式;Crawler4j;Quartz
Abstract: Web crawler is an important foundation of data analysis, through which data can be acquired. Aiming at the problem of crawler's wide channel, large number and miscellaneous, and low efficiency of single point, the lightweight multi-threaded crawler framework Crawler4j and the distributed timed task scheduling framework Quartz are introduced. This paper mainly builds a stable and efficient distributed crawler system based on these two frameworks.
网络爬虫(Web Crawler)是指按照特定的方式,自动获取网络中大量数据(包括结构化数据、半结构化数据,以及非结构化数据)的程序或者脚本。在大数据时代,数据就是财富,得数据者得天下,所以作为获取网络数据的网络爬虫技术将越来越受到重视。网络爬虫技术不仅涉及到网络知识、网页前后端知识,而且还包含各种辅助工具,是个综合的技术[1]。本文通过开源框架Crawler4j[2]和Quartz[3]来构建定时循环、稳定、快速的多线程分布式爬虫系统,最终实现爬虫的高效数据采集功能。
2 技术选型
2.1 Quartz中集成Crawler4j
Crawler4j是一款基于Java的轻量级单机开源爬虫框架[2],该框架的特点是实现简单、速度快、容易上手,同时该框架支持多线程、过滤重复url、垂直获取数据等功能。在使用Crawler4j框架时,需要关注两个重要的类,一个类是:WebCrawler类,它负责匹配url规则、解析html页面和提取所需数据;另外一个类为:Controller类,它用来控制爬虫的各种状态。对于Crawler4j的配置,需要根据不同的爬虫任务来进行定制化设计,如setMaxDepthOfCrawling()[2]就是配置最大深度,setMaxPagesToFetch()[2]就是页面抓取的最大数量,对于不同的配置,需要查看官方文档[2]。
Quartz是任务调度领域的一个开源项目[3],其最大的特点是拥有丰富的功能,它可以用来创建或者运行少则几个,多则十个、百个、甚至几万个复杂任务。Quartz框架中定时任务部分是在Job类的void execute(JobExecutionContextcontext)[3]方法中执行,如果想要集成Crawler4j爬虫框架,只需在execute()方法中构造Crawler4j配置及启动对应配置爬虫线程,这样就能够实现定时爬虫任务了。启动爬虫任务后,用Crawler4j自带的解析特性来解析对应url返回的页面。但是这种方法不是通用的,所以对于一些特殊页面还需要采取自定义解析类来解析。
2.2 分布式实现原理
需要获取的数据来源渠道众多,有门户网站、快讯、自媒体等等。各渠道的数据结构也不统一,这样便导致每一个任务都很个性化,需要做定制化处理来满足需求。依托Quartz不仅可以实现成百上千个任务的运行和管理,而且每一个任务都可以做定制化处理[4]。单个节点运行众多任务的时候,存在着运行效率低、获取数据不及时、无法高可用等问题。通过引入分布式系统可以有效地提高系统的整体运行效率,同时解决高可用问题,保证系统的稳定运行。
在集群中,每个节点能和数据库组成一个独立且完整的应用。Quartz通过数据库来调度当前节点与其他节点进行协作,每个节点的启动或停止是相互独立的行为,它们之间没有任何通信。Quartz集群在同一个数据库下,由数据库中保存状态来判断调度任务是否正在执行,并且其他节点不能执行正在执行中的任务,这样就保证了该任务的实例在集群中是单实例运行的,并且集群中分配任务是按照负载均衡策略来进行[5,6]。当任务在其中一个节点中运行失败,数据库中会有状态的记录,并且马上重新分配到另外一个节点中启动运行,这样便保证了任务的高可用性。
3 分布式爬虫系统
3.1 分布式系统搭建
搭建基于Quartz的集群,首先要建立数据库表结构。运行官方网站docs/dbTables[3]路径下的脚本文件,在mysql中创建对应的11张表,如图1所示,它是实现集群的基础。
其次需要编写Quartz对应的配置文件,可以在quartz.properties配置,也可以把配置文件写到对应的configuration中。在配置中特別需要注意isClustered 必须设置为True,否则不能实现分布式集群。
最后就是定义实现Job接口的爬虫任务类,配置Crawler4j,把对应的配置放在数据库中。如图2所示,当任务启动时就去数据库获取对应任务Crawler4j配置,添加到Crawler4j的框架中。用SpringBoot来集成Quartz,启动SpringBoot就能实现对应的定时任务。
3.2 定制化任务实现
为了满足定制化任务[7]的需要,以及实现管理端对爬虫任务的管理和监控,在数据库表中设计了t_crawler_task(任务)表和t_sched_card(令牌)表。利用这两张表可以实现对任务的增删改查,同时满足对任务的定制化,比如需要对定时实现定制化,只需在cron字段填上定制化的时间就能实现定时任务的定制化。
Quartz实现定时调度系统是将任务开发和任务调度进行分离[6]。开发人员不需要考虑任务的调度问题,只需要考虑任务需要爬取什么数据,然后实现Job接口即可。任务调度可以根据任务自身的情况进行设置,可以在爬虫管理系统中配置,也可以直接配置在数据库中。当SpringBoot容器启动后,系统自动检测所有实现Job接口的类,并将其初始化为实例,在初始化过程中,系统会读取每个Job任务已经设置好的调度信息,而后根据配置好的调度信息进行有序调度[7]。
4 结束语
本文通过Crawler4j和Quartz来搭建分布式定时爬虫系统,分布式节点数量理论上不受限制,且每个节点中的代码、配置和部署都一模一样。在集群中任务的数目可以成百上千,同时每一个任务可以在Crawler4j中配置多线程,从而大大提高了爬虫的效率。目前实现的分布式系统稳定,超过半年没有出现过宕机的情况,而且开发简单,高效。
当然该分布式系统依然存在一些不足需要改进:
(1)本系统还需要开发爬虫管理系统,用来监控和管理爬虫任务。
(2)爬虫系统需要设计更加通用的解析页面方式,以便能够快速地通过修改配置文件而不是重新修改对应的代码来解决众多渠道改版所带来的爬虫实现问题。
参考文献:
[1]王敏.分布式网络爬虫的研究与实现[D].东南大学,2017.
[2]https://github.com/yasserg/crawler4j[EB/OL].
[3]http://www.quartz-scheduler.org/[EB/OL].
[4]张康.基于Quartz的分布式定时任务调度模块的设计与实现[D].南京大学,2019.
[5]段子飞.支持Ajax的Deep Web网络爬虫系统的设计与实现[D].华南理工大学,2015.
[6]魏丽娟.基于hadoop的網络爬虫技术研究[D].武汉理工大学,2013.
[7]于成龙,于洪波.网络爬虫技术研究[J].东莞理工学院学报,2011,18(3):25-29.