Skip to content

yitian-reevo/skyhook

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

skyhook - 天钩计划

背景

大背景是参与了一个知识图谱商业项目,旨在构建一套加密领域中有关人、公司、项目的知识图谱,涉及到150+种不同来源的结构或非结构化数据的采集和存储、NLP、实体识别、关系抽取、图谱构建以及各种基于图谱的分析得出的报告。通过图谱可以迅速的获取如人事变动、项目信息、项目进展等直观信息,也可以基于人与人、人与项目的关系作出一些分析报告供投资人参考。

那图谱项目的数据层是我自己基于另外一套爬虫框架琢磨出来的一个优化方案,目前也运行了将近1年多,基本能够满足稳定、可扩展、高效的需求。涉及到的项目包含爬虫核心(也就是本项目的完整版)、代理池、Cookies池、定时任务调度(定时调度用于维护或收集信息的脚本)、实时内容解析(提供一些RESTful的API用于封装处理一些特殊环境下的需求);另外,还有一些图谱项目特有的需求,比如说针对新闻网站主体的内容解析、针对Twitter的KOL定点爬取和关注关系监控等。

这里放一个完整版的爬虫框架逻辑的架构:

其中Core的详细逻辑架构是这样的:

本项目是完整版的爬虫框架的一个极简版本,只留了必要的模块并改成了单机单进程的版本(也就是第二张图里标红的部分),事实上我就是从这个版本出发,慢慢一步一步走过来的。后面我也会简单说下如何在这个基础上加入各种模块让爬虫框架可以支撑起一个商业项目。

一些说明

本项目不是按照“一键式pip安装”使用来设计的,它基于Scrapy项目二次开发,所以要使用本项目,必须对Scrapy有一些基本了解:当一个新需求出现时,是否能立刻意识到应该在那个地方着手修改代码?

在整个框架的设计过程中,Scrpay框架本身其实只占了大概一半的比重,它可以被看作一个任务执行单元,通过scrapy提供的core API,我们可以在代码层次上按照实际的业务需求对单个spider进行调度。这样做的好处是可以将某个spider执行失败所造成的影响降到最低。如果一个spider执行失败了(比如说某个项目的主页爬取失败了,可能是网络原因,也可能是代码问题),对于调度器来说只是其调度过的无数任务中的某个失败了,不会造成什么影响。

调度器是整个框架的核心,也是最需要时间思考和编写的。我这里提供了一个单机版本的定时任务调度器,参考skyhook/schedulers/cronjob.py。不复杂,但是如果后续要支持定时任务调度或循环任务调度,或者只是单纯的数据量增大,调度器性能不够了,这些情况都会需要更加强力的调度器。这也是后续项目扩大后需要重点关注的一个地方。

除了以上这些,图中还标注了一些side projects,有些比较简单,比如说用于监控的Grafana,只需要简单的把需要统计的数据写入influxDB,然后部署配置一下即可,sentry同理,sentry可以用来收集整个项目的logging信息,用来定位问题。架构中还提到了一个spider-frontend/backend,我的想法是给后续动态维护爬虫用的,到时候对于一些爬虫的增删改查,可以直接从web端操作,会方便很多。

在此基础上,我又尝试做了一个通用性型spider,它会解析一个精心设计的json配置文件以达到解析不同源的目的。配置分两种:一种就是一个完整的rule,它描述了一个完整的爬虫任务,参考resource/coincenter_blog_rule.json,根据这份json文件的要求,调度器会每1分钟调度一次这个爬虫任务,依次访问其中的startUrl并根据policies字段的解析,最终返回包含title、url、author等字段的爬取结果,然后通过pipeline进行进一步处理;另一种情况是这样的,假设我们要爬取很多用户的Medium文章,可以先编写一个爬取medium文章的模板,然后传入不同的用户名即可,这种情况可以参考resource/medium_rule.jsonresource/medium_template.json

除了基本的爬取规则,配置文件里也可以包含对代理、Cookie的使用规则以及一些很基础的字段预处理函数,这些如果有需要我另外详细再说,但代码已经包含了,可以参考skyhook/middlewares/httpproxy.pyskyhook/plugins/businessskyhook/plugins/processor

综上,整个业务流程大概是这样的:

  1. 调度器(Scheduler)会是整个项目的入口,它会根据某个执行逻辑找到下一个要执行的spider(一个列表),并将其各自对应的类型和配置文件作为参数返回;
  2. 程序通过Core API启动调度器返回的spider,相当于给scrapy分发了一个爬取任务,具体的配置文件会作为参数传入。
  3. Scrapy项目中的spider会依次接收并解析每个配置文件,然后按照其逻辑进行抓取并返回一些数据结果。
  4. 完成后,调度器会进行下一次轮询调度。

如何使用

数据库配置

数据库目前在代码中强制使用mongoDB,具体的配置项在settings.py填写。Redis和Influxdb可以暂时不管,保持默认即可。

数据库中需要新建两张表:ruletemplate,然后将resource下的json文件作为记录分别加入表中,注意,如果是template形式,那么rule中其对应的template的id需要填写正确。如图:

框架运行

需要 python 3.7+,并根据实际情况调整settings.py中的配置项,比如MONGODB_CON_STRMONGODB_DB_NAMEREDIS_HOSTREDIS_PORTREDIS_DBREDIS_KEY等。

直接运行

只需要在命令行执行(建议在虚拟环境下执行):

pip install -r requirements.txt
cd skyhook && python main.py

Docker运行

docker build -t skyhook .
docker run -d --name skyhook_1 skyhook

如何扩展

如何加入代理池、Cookie池?

在目前的项目里已经包含了一个proxy中间件(需要到settings.py中配置打开)。如果爬虫配置的json文件里包含proxy_policies字段:

proxy_policies = {
    'domain': '.github.com',
    'weight': 0.8,
    'delay': 180,
}

中间件就会根据这个规则从数据库中(也可以是其他来源)读取一个对应的代理,解释如下:

  • domain,如果需要可以对代理池按照域名进行分割,代理池只会从带有某 domain 标记的代理中选择。不同域名对 IP 的限制策略会不同,因此有时候 domain A 可能需要 2000 个代理,但 domain B 只要 50 个,这种情况可以用这个值进行分割。如果不想要此限制,可以添加一个代表 every 的值,比如说all或者.
  • weight, 表示可选择代理的权重的最小值,目前如果一个代理未生效,会对其权重进行乘 0.9 的操作,初始值为 1。因此一个代理的权重值越大,表示它越可靠。在选择代理时,会从代理权重值大于 weight 的代理中进行选择,但不一定是权重最大的那个代理。
  • delay,表示一个代理两次被使用的最小间隔,也可以理解为冷却时间。单位是秒,也就是说,如果 delay 的值是 120,说明这个代理在一次使用后,至少要过 2 分钟才会再次被使用,也就是说,这个代理在 1 小时内最多只会被使用 30 次。这个值在网站对 IP 访问次数有严格限制时,会发挥很大作用。以 GitHub Develop API 为例,Github 每个 IP 每小时最多只能访问 60 次接口,也就是一分钟一个 IP 只能访问一次;这样只需要将delay配置为60即可。

另外,如果一个爬取任务中涉及到了多个url,会使用同一个代理,以增加爬取成功的成功率。

值得一提的是:代理池可以是自建的,可以使用第三方的;同理,可以直接从数据库中读取,可以通过封住的api返回,这些都不是问题,也没明显优劣,按需编写即可。毕竟,需求千万种,方案就一种:给时间都能做。

如何改成分布式部署?

要改成分布式部署,需要将调度模块Scheduler分成两块:producerworker,再引入一个消息队列(推荐aws的sqs,因为它有一个超时特性特别有用,当然其他的消息队列都是可以的)。之后的逻辑就是producer不断地向消息队列中生产爬虫任务,worker则是从消息队列中读取1个或多个任务,然后调用core API执行。这样理论上worker就是可以线性拓展的。

如何接入一些辅助模块,使框架更健壮?

虽然说单个爬取任务的成败无关紧要,但如果哪天Medium调整了它的接口,那么所有的Medium爬虫都会失败,因此我们需要一些手段能把这些识别出来。

解决方法是可以通过接入一些开源的、第三方的框架,比如说GrafanaSentry。另外因为爬虫的配置文件字段相对固定,可以再构建一些管理的web页面用于可视化的对爬虫进行管理(增删改查、状态调整等),Grafana的监控图表也可以整合到一起,一劳永逸。

关于项目名

灵感来源于贝尔版《蝙蝠侠:黑暗骑士》,这些爬虫任务就像一个个带有明确目标的钩子,在互联网中将我们感兴趣的内容钩了出来。

About

一个轻量的、稳定的、可扩展的爬虫框架

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published