haipproxy多月实现代理IP池的思路与方法
优采云 发布时间: 2021-08-24 03:22haipproxy多月实现代理IP池的思路与方法
一个分布式代理IP池的实现大概花了两个月的时间。目标是为*敏*感*词*分布式爬虫提供高可用性和低延迟的代理。它是开源和免费的。在实现过程中有一些想法。这个问题的日志虽然16年了,但还是忍不住来上课,和各种大佬交流。
Kaito 的回答给了我很多启发。在haipproxy实现的初期,大部分功能都是根据他的回答一步步实现的。站在巨人的肩膀上,我也有自己的一些想法。例如,代理 IP 源。除了百度和谷歌,另外两个非常重要的来源是类似项目的引用和代理IP站点的好友链接。它们也是一个非常重要的来源。 haipproxy统计墙内外代理IP来源,累计30+。
当IP源较多时,如何实现编码?如果设计不好,那么只有代理IP的捕获就要写很多代码,变成了手工任务。 haipproxy实现代理IP捕获的思路是:抽象出网站页面结构相似的共性,然后写规则复用代码。因为很多网站仍然使用表格布局的形式,代码复用会很容易。然后,对于动态捕获的网站,使用scrapy-splash进行渲染,然后将共性抽象出来复用代码。
代理爬取代码完成后,由于IP源网站会定时更新代理,我们需要定时爬取。定时任务也有一定的特殊性。一般不同网站的IP源的更新间隔是不同的,所以最好的办法就是保持定时任务和对应的网站的更新间隔一致。好处是:(1)不遗漏每次更新的代理源(2)不会因为频繁访问网站(3))而对其正常运行造成太大压力)服务器资源有限时,不会有任务堆积。
通过以上过程,我们已经可以在30分钟内采集达到上千个代理IP。但是我们都知道免费代理IP的可用性很低。如何在资源高度不可用的情况下获得一个质量不错的代理IP,本身就是一件非常具有挑战性和有趣的事情。 haipproxy 的方法类似于 Kaito 提到的方法。它会定期验证Redis中的代理IP。验证分为三个维度:(1)是否匿名(2)稳定性(3)响应速度。匿名可以通过访问自己搭建的web认证服务器来实现。为了降低验证压力,haipproxy会丢弃解析代理网站页面时的大部分透明IP。为了保证真实IP的匿名性,做检查是否匿名。稳定性可以通过一定的算法计算。由于篇幅原因,细节这里就不写了,有兴趣的可以看看这个文章。响应速度也可以通过写一个profilemiddleware中间件来实现。
到上一步,我们已经完成了一个代理IP从被抓到入库的第一次验证。有朋友应该也知道,同一个代理IP对应不同的网站,其代理效果可能完全不同。因此,有必要为特定站点维护一个验证器。那么验证器的细节应该如何实现呢?大体思路如下:(1)如果通过代理IP返回非Timeout错误,那么十有八九是代理服务器的相关端口关闭了,这个时候应该直接丢弃代理,而且不能再验证了。。如果是Timeout错误,那么就递减,然后再验证下一轮定时任务(2)Verification 网站应该是特定站点的稳定页面。根据返回的内容判断IP是否可用,比如知乎、微博等网站,如果代理IP被它屏蔽了,网站还是会回复200状态码,同样我们需要记录每次我们验证或更新相应代理的响应速度和最新验证时间。
通过上一步,我们已经完成了具体的验证器。这时候我们只需要用特定的开发语言编写客户端代码就可以得到代理IP。 Kaito使用squid作为二级代理的方法很有启发性和可行性,haipproxy已经实现了。但是经过深入使用,发现了几个问题:(1)squid可能会成为请求的瓶颈(2)squid对代理IP的具体使用没有感知和反馈。因此,haipproxy目前实现了一个基于Python的代理调用客户端py_cli,客户端采用了一些策略来保证代理IP的高可用和低延迟,具体方法如下:
根据配置,从存储代理分数、代理速度、最近验证时间的队列中选择满足配置参数要求的代理,然后将它们相交,这样才能合理保证上述标准。当通过上述选择方法选择的代理数量不足时,将放宽选择要求,将速度和最新验证时间相交,然后将成功率结合起来。如果代理数量不够,则降低要求,并合并满足最新验证时间和成功率的集合。
爬虫客户端调用py_cli时,代理客户端会先调用refresh()方法。如果代理客户端实例的可用代理数量不够,则通过上一步的算法扩展IP池。如果数量为Enough,则根据代理的调度策略选择合适的IP使用。
在代理客户端实例中调用代理池的代理IP也需要一个策略。 haiproxy 目前实现了两种代理调度策略。 (1)polling 策略。代理池是一个队列结构。每次使用一个IP从组长开始,如果IP请求成功,就会放在队列的末尾。如果不成功,需要调用代理客户端的proxy_feedback()方法反馈结果。这种策略的优点是IP负载比较均衡。但缺点是IP质量参差不齐,有的响应时间很快,有的响应时间很慢,而且优质的免费代理IP生命周期可能很短,所以不能充分利用。 (2)greedy 策略。使用该策略时,爬虫需要记录每次请求的响应时间,并在每次使用后调用`proxy_feedback()`方法。判断代理IP是否会继续使用下一个请求,如果使用代理IP的响应时间低于某个设定值,将继续使用,直到不可用并从代理池中删除。如果时间高于此值,则将IP置于队列的末尾。综上所述,策略是低质量IP轮询,始终使用高质量IP。
以上是从高可用资源中实现高可用代理IP池的思路。
另外,为了爬虫的效率和定时器的高可用,haipproxy基于scrapy和redis实现了分布式爬虫和定时任务调度器。
说了这么多,这个代理池的作用是什么?以下是3月3日以知乎为目标站点的单机爬取测试结果
可以看出在单机情况下,并发爬取可以达到1w/小时的请求量。
项目和测试代码地址
可以探索的东西很多,比如流量控制,按城市过滤(爬虫登录状态下有用),持续优化高可用策略等等,希望有志同道合的朋友加入一起优化,我一个人会寂寞。也希望看到这个回答或者使用这个项目觉得有帮助的同学可以给star一些鼓励。