这篇博文主要分享下,如何为中小企业在短时间内搭建出一套爬虫采集系统,技术选型时候应该注意什么,有哪些公开资料可以参考。
本篇博客的目标读者主要是一些有爬虫需求、正在准备组建爬虫团队,从零构建爬虫系统的中小企业或数据部门,整篇博客阅读时间大约十分钟。
笔者供职的公司是一家从事财税行业的技术公司,目前融资轮次在D轮,主要业务是为代帐公司提供报税服务。目前已为百万家企业提供了报税服务。
在2020年1月时候,笔者所在的数据部门Leader开始提出要为这些企业提供更广泛的数据方面服务,需要抓取相关企业的互联网公开信息,提供给其他应用部门使用。
这类爬虫需求其实在一些初创企业中很常见,爬虫系统并不难做,但想要做好,至少要从以下几个方面评估需求:
在初创企业中,人力资源往往很有限,因此在动手设计系统前,一定要理解企业的整体发展方向、主要经营业务,以及为什么需要抓取数据。只有评估好需求,才有可能避免返工,构建出一个可交付的爬虫系统。
笔者认为中小公司在做技术选型时,应至少考虑三个方面:以业务为导向的数据架构,以技术栈为基础的应用架构,以公司内部实际情况的整体技术架构。
首先还是要理解公司想通过爬虫解决什么样的业务问题。比如大多数企业的爬虫需求是通过更多的维度补充自身数据,展示给用户进行查看,而有一些企业则需要将抓取来的数据做二次处理,比如做與情预警、做行业关系图谱、知识图谱、生成行业报告等。
无论是哪种业务需求,我们都需要以业务需求为导向,确定好需求方需要抓取哪些信息,目标网站的数据需求是否真实有效。然后对目标网站的抓取信息做分类,区分出哪些抓取的信息适合存储在一个结果集中,哪些信息适合做结果集中的主键。
这里主要指合理挑选、编排爬虫的技术栈。目前做爬虫主要的工具栈包括以Java语言为主的Webmagic、Apache Nutch,以Python语言为主的Scrapy、PySpider。
Webmagic基本可以满足单机类爬虫,使用多线程的方式完成爬虫请求。如果是小公司,需求不复杂,没有Python技术栈的员工、也没有招人的打算,可以考虑使用Webmagic。他的开发比较简单,只要写好相应的页面解析Processor组件、存储组件Pipeline即可完成一个爬虫。
Apache Nutch相比于Webmagic则要重型得多。其实相比于爬虫,Apache Nutch更适合做一个搜索引擎,抓取和存储半结构化和非结构化的网页数据。Apache Nutch的存储主要有Apache Solr、Apache Hadoop、ES等,解析库有Apache Tika。Apache Nutch解决的需求主要是针对目标网站先进行深度抓取,放在本地的存储后,再使用Tika/Solr进行解析与检索。
相比于Java技术栈,Scrapy是中小企业做爬虫最划得来的技术栈选择。只需要编写Spider中parse方法、pipeline方法,即可完成一个单机版本的爬虫。Scrapy提供的技术栈生态非常丰富,使用Scrapy-redis可以通过共享内存队列的方式实现分布式爬虫,使用scrapyd可以更好的托管爬虫、实现种子列表的接口调度,甚至还有Scrapy-cluster提供开箱即用的整套爬虫服务。
使用Scrapy及相关的技术栈,能基本实现以下功能:
基本上,选择的技术栈能支持以上几个功能,就可以满足中小企业的日常爬虫需求了。
这一部分主要要从两个角度进行考虑,一个是需要与爬虫发生数据交换的应用系统角度,另一个是公司的DevOps与运维成熟度角度。
我们首先说第一个角度。
做爬虫系统一定是要关注它的输入与输出的,因为抓取到的数据只有能被用起来,才能体现出它的价值。
一般比较简单的开源爬虫框架,输入的种子列表都是一个文件,然后通过命令行启动完成抓取。但是这远远不能满足日常的抓取需求,因为不可能说日常抓取都需要以文本文件的形式,上传到爬虫服务器然后手工启动爬虫运行,这显然不够灵活。目前中小互联网公司在各个应用系统间完成调度无非是两种方式,一个是被调用方提供restful api接口,另一种方式是以消息队列(如mq,kafka)进行消息传递。这里无论哪种方式,我们都假设这里采用异步方式进行调度。
对于爬虫系统来说,两种方式都可以,但是通过restful api的形式接受会相对更容易、更灵活一些。如果使用消息队列的方式传递种子列表,我们就要考虑爬虫端需要有一个consumer不断从消息队列中取消息,然后将消息转换为种子列表的形式,再放入到爬虫的种子列表队列中。这在实现上可能会比较麻烦,因为涉及到了一个消息的转化过程,而且对爬虫框架的二次开发能力也有一定要求。
比较简单的方法是通过restful api的方式。使用Flask/Django Restful/Spring Boot增加一层service,将接口设计好,外部应用根据需求调度接口,接口将请求转化为特定的url,插入到爬虫的种子队列存储介质中,比如redis,这样就可以较好的完成种子列表的输入。
输出方面,要按照企业的实际情况来看。一般来说爬虫的pipeline只负责很简单的清洗与存储,对于比较复杂、繁琐的清洗需求,一般是放在后边应用来做。比如,如果是只给一个应用系统的Mysql数据库提供数据的话,那可以直接在爬虫中写一个Mysql的Pipeline。如果是需要给多个系统提供数据的话,那就要考虑将爬虫数据统一存储,然后对外提供查询能力。如果抓取的数据更加复杂,那就要考虑增加一层缓存如mq或kafka,然后通过kettle,python脚本或流式工具比如Apache NIFI/Apache Storm/Apache Flink/Apache Spark等进行数据处理,将数据处理结果推送到大数据平台,再对外提供查询能力。
总结下来,爬虫系统的输入端最好能提供一个restful的能力,要便于外部应用灵活调度。输出端要根据清洗难度、项目背景做好设计,使用合理的方式清洗、存储数据。
另一方面,公司的DevOps与运维能力对爬虫系统的研发也至关重要。
爬虫系统的研发很有可能是一个持续开发、持续集成的工作。目标网站的页面变动,反爬手段都有可能涉及到爬虫代码的重构与上线。
如果公司有一定的运维能力,使用docker/k8s发布应用,要尽量使用这些工具进行爬虫代码的构建。同时爬虫的ip代理、服务器、网络资源等成本的控制也应该与公司运维部门做好沟通,防止成本超标。
爬虫的日志也应该做好管理,因为一个目标网站的页面变动往往是事后通过分析日志来定位发现的。如果能做好爬虫错误日志的监控和预警,能尽早定位到问题,修改代码,然后重构上线,避免影响线上业务。
完成一个爬虫系统需要考虑的东西有很多,在需求方面,要从公司的实际业务入手,在技术选型方面,要从数据架构、应用架构、整体技术架构三个方面进行考虑。做好以上两个方面,才能较好的完成一个稳定的、健壮的爬虫系统。
1、崔庆才的书籍、以及夜幕团队的一些文章。
2、Scrapy 官方文档。