Python爬虫爬虫一起学python

给自己的爬虫做一个简单的动态代理池

2017-02-14  本文已影响4127人  ArthurMao

使用代理服务器一直是爬虫防BAN最有效的手段,但网上的免费代理往往质量很低,大部分代理完全不能使用,剩下能用的代理很多也只有几分钟的寿命,没法直接用到爬虫项目中。
下面简单记录一下我用scrapy+redis实现动态代理池的过程。

我对“动态代理池” 的需求

我的爬虫项目需要7*24小时监控若干个页面,考虑了一下希望代理池能满足下面几个要求:

参考过的项目

找过一些现成的轮子,但发现或多或少都不太符合我的需求

kohn/HttpProxyMiddleware
一个“被动”选择代理的方式。在scrapy middleware中加入大量代码,让爬虫在代理失效后再去代理网站找代理,会有下面几个问题:

jhao104/proxy_pool
这个几乎和我想要的一样,但还是因为下面几点原因没有使用:

设计思路和代码

看了那么多方案,我就在想:能不能让代理池具有自我检查自我修复的功能?这样我们的爬虫就只需随机拿一个代理用就可以了,就算恰巧拿到一个失效代理,只要做一次retry,代理池的修复机制可以保证retry的时候失效的代理已经被移走了,不会再次取到。

简单规划一下:

对应的代码就有这么三个部分:

强行画个流程图:

hq-proxies.png

爬虫部分全部用scrapy写了,其实没必要,用requests就够了..但做的时候刚学scrapy,就顺便练练手了..
start.py的调度方式比较粗暴,直接起两个线程,在线程内用os.system调用scrapy爬虫(毕竟轻量级代理池嘛..好吧其实就是我懒图个方便..)

另外还有几个调度策略需要说一下:

其他细节可以看源码:arthurmmm/hq-proxies

部署和使用

需要先改一下配置文件hq-proxies.yml,把Redis的地址密码之类的填上,改完后放到/etc/hq-proxies.yml下。
在配置文件中也可以调整相应的阈值和免费代理源和测试页面。
测试页面需要频繁访问,为了节省流量我在某云存储上丢了个helloworld的文本当测试页面了,云存储有流量限制建议大家换掉。。验证方式很粗暴,比较一下网页开头字符串。。

另外写了个Dockerfile可以直接部署到Docker上(python3用的是Daocloud的镜像),跑容器的时候记得把hq-proxies.yml映射到容器/etc/hq-proxies.yml下。
手工部署的话跑pip install -r requirements.txt安装依赖包

在scrapy中使用代理池的只需要添加一个middleware,每次爬取时从redis SET里用srandmember随机获取一个代理使用,代理失效和一般的请求超时一样retry,代理池的自检特性保证了我们retry时候再次拿到失效代理的概率很低。middleware代码示例:

class DynamicProxyMiddleware(object):
    def process_request(self, request, spider):
        redis_db = StrictRedis(
            host=LOCAL_CONFIG['REDIS_HOST'], 
            port=LOCAL_CONFIG['REDIS_PORT'], 
            password=LOCAL_CONFIG['REDIS_PASSWORD'],
            db=LOCAL_CONFIG['REDIS_DB']
        ) 
        proxy = redis_db.sismember(PROXY_SET, proxy):
        logger.debug('使用代理[%s]访问[%s]' % (proxy, request.url))
        request.meta['proxy'] = proxy

在其他爬虫框架下使用也是类似的。

最后放一张萌萌哒日志菌触发proxy_fetch时候的截图:

Paste_Image.png
上一篇下一篇

猜你喜欢

热点阅读