在进行网页爬虫的项目时,常常会因为爬取的频率过高而触发 反爬虫机制 ,这时候,面临两个选择:
- 休息片刻。一般反爬虫机制不会进行永久的IP封禁,只是暂时限制访问而已,等待封禁时间结束再进行爬取即可。当然对于某些拥有黑名单机制的网站,如果封禁次数过多,封禁的时间也会随着这个次数而提高。
- 更换IP。既然我的IP被封了,那么我换一个其他的IP不就行了。
显然,第二种方法更优于第一种,并且更加符合geek的风格。但是问题在于,从哪里寻找这样一个IP地址呢?
很多的教材都有__免费代理网站__这样一个概念,但是免费代理面临的一个问题就是,很多的人都在使用,所以往往刚解封就又被封禁了,有的甚至直接就挂在网站的黑名单里。所以,代理网站提供的IP虽然多,但是可用的却非常的少。
小数量的IP跟没有一样,那么如何白嫖大量的__免费的有效的__IP代理呢?
代理网站有很多,假设每个网站能够提供两位数级别的可用IP,那么统合起来就是一个十分可观的数字了。用来应付_个人级_的爬虫项目游刃有余。
但是,这又引出一个问题。每次进行爬虫项目都要先对上千上万的IP地址进行一次过滤? 这无疑是非常地影响效率的。
所以,基于以上的种种问题,引出一个解决方案,建立一个__代理池(proxy pool)__ 。
这个想法在某些的教材上面出现过,并且也有类似的项目(但是大多数都已经失效了),这里笔者决定从零开始,维护一个属于自己的代理池项目。
游戏开始
进行一个项目,首先要对项目进行一个大致的规划,这个规划没有必要太过于详细,因为作为一个经验不是很充足的菜鸟程序员,永远不知道开发过程中会遇到什么问题,又会迸发出什么样令人拍案的灵感(agile development)。
预计有以下几个模块:
- getter:负责从各个免费代理网站上__获取__代理,并写入数据库
- tester:负责对数据库中的代理进行__测试__,并进行评分
- server:随机从数据库中__返回__代理
- scheduler:调度器,调度getter、tester、api三者的运行
- database:数据库接口
预计使用到一下的技术:
- request、bs4等:爬虫相关的技术,主要用于获取各个代理网站的代理
- flask:制作主页面和api
- redis:代理数据库。由于我们是需要完成一个评分机制的代理池,所以可以使用redis的有序集合结构,功能简洁,实现便利。
- aiohttp:通过协程提高测试效率
- MySQL:协同日志数据库
以上的项目主体框架思路来自于GitHub的几个热门代理池项目
1. 选取免费代理网站
笔者尝试过很多的代理网站,诸如西刺、快代理、齐云等国内知名的网站,但是发现可用的IP比例实在是太少,后来想了想,大抵是国内的爬虫学习者和个人开发者多引用这些网站,所以导致网站的IP大量被封吧。
于是笔者去搜索了一些外部的网站,如free proxy list等,IP的可用率确实提高了很多。
至于用不用国内的免费代理,就看个人的需求吧。
2. 完成getter模块
getter模块负责__获取免费代理,写入代理池__.
这里以free_proxy为例,因为笔者发现这个网站的IP地址使用了__Base64加密__,所以IP地址被爬虫新手"迫害"的程度较低:D。
import base64
res_ip = re.findall('Base64.decode\("(.*?)"\)',req.text)
res_port = re.findall('style=\'\'>(\d*)</span>',req.text)
proxy_list = []
for index in range(len(res_ip)):
proxy = base64.b64decode(res_ip[index]).decode('utf-8')+':'+res_port[index