历时大致两个月, 到现在终于完成了分布式代理抓取爬虫, 目前开源在了 Github 上写这个项目的原因主要有两点, 一是自己平时的部分工作需要和爬虫打交道, 代理 IP 在有的时候可以发挥非常重要的作用, 调研过一些开源的代理 IP 采集程序, 发现在抓取解析校验资源调度等这些方面总有一些不尽人意的地方; 二是和一个网友 (不严格的说算得上是伯乐) 的交流让我有了关于使用 Scrapy 来写分布式爬虫的一些想法, 正好可以借助这个机会来尝试证实这些想法
这篇文章的目的是阐述 haipproxy 的主要架构和流程该项目关键部分是
基于 Scrapy 和 Redis 的分布式爬虫, 用作 IP 抓取和校验, 对应于项目的 crawler
基于 Redis 实现的分布式任务调度工具, 对应于项目的 scheduler 和 redis_util.py
Crawler 分为代理抓取和校验, 两者实现思想类似, 主要使用 Scrapy 的 spider_idle 信号和 DontCloseSpider 异常来阻止 Scrapy 在没有数据的时候关闭, 灵感来自 scrapy-redis 为了方便阐述, 我画了一张包含各个组件的流程图, 如下
pro
启动调度器, 包括代理爬虫调度器和校验爬虫调度器调度器会读取 rules.py 中待抓取的网站, 将其编排成任务存入各个任务队列中
启动各个爬虫, 包括 IP 抓取和校验程序项目中爬虫和调度器都是高可用的, 可以根据实际情况进行分布式部署, 无需改动代码由于本文的目标不是写成该项目的详细使用文档, 所以省略了如指定启动爬虫类型和调度器类型的介绍
代理 IP 采集爬虫启动后会到对应的任务队列中获取任务并执行, 再把获取到的结果存入一个 init 队列中
init 队列由一个特殊的校验器
HttpbinInitValidator
进行消费, 它会过滤掉透明代理, 再把可用代理输入各个 Validated 队列中
调度器会定时从 Validated 队列中获取代理 IP, 再将其存入一个临时的队列这里用一个临时队列是为了让校验更加公平, 如果直接从 Validated 队列中获取资源进行校验, 那么会增大不公平性
这时候各个校验器 (非 init 校验器) 会从对应的临时队列中获取待校验的 IP 并对其进行校验, 此处省略校验细节
校验完成后再将其放回到 Validated 队列中, 等待下一轮校验
请求成功率 (体现为分数) 响应速度和最近校验时间满足 settings.py 所配置要求的代理 IP 将会被爬虫客户端所消费
为了屏蔽各个调用语言的差异性, 目前实现的客户端是 squid 客户端, 它可以作为爬虫客户端的中间件
到此, 整个流程便完了
来源: https://juejin.im/post/5a965b7af265da4e7527c8f8