代理

我们在做爬虫的过程中经常会遇到这样的情况:最初爬虫正常运行,正常抓取数据,然而一会儿的功夫可能就会出现错误,比如403 Forbidden;这时候网页上可能会出现 “您的IP访问频率太高”这样的提示,过很久之后才可能解封,但是一会后又出现这种情况。

造成这种现象的原因是该网站已采取了一些防爬虫措施。例如,服务器将在一个时间单位内检测IP请求的数量。如果超过某个阈值,服务器将直接拒绝该服务并返回一些错误信息。这种情况可以称为封IP,因此该网站成功禁止了我们的抓取工具。

想象一下,由于服务器检测到IP单位时间内的请求数量,因此我们使用某种方式来伪装IP,以使服务器无法识别由本地计算机发起的请求,因此我们可以成功地阻止IP被封。

所以这时候代理池就派上用场了。

网络上有大量免费且公开的代理可以供我们使用,但这些代理并不能保证都可以使用,因为同样的代理可能被其他人拿来爬虫使用而遭到封禁,因此,在真正使用之前,我们需要对这些免费代理进行筛选,剔除那些不能使用的。保留下可以用的,来构建一个代理池,供我们爬虫使用。

代理池设计

相关问题

构建一个代理IP池,可能有下面这些问题:

  1. 代理IP从何而来?

    许多刚接触爬虫的,都试过去西刺、快代理之类有免费代理的网站去抓些免费代理,还是有一些代理能用。当然,如果你有更好的代理接口也可以自己接入。
    免费代理的采集也很简单:访问页面 —> 正则/xpath提取 —> 保存

  2. 如何保证代理质量?

    可以肯定免费的代理IP大部分都是不能用的。所以采集回来的代理IP不能直接使用,检测的办法也很简单:可以写个程序不断的用代理访问一个稳定的网站,看是否可以正常访问即可。这个过程可以使用多线/进程或异步的方式,因为检测代理是个很慢的过程。

  3. 采集回来的代理如何存储?

    这里选择Redis作为数据存储,因为它速度很快。以及Redis支持队列、hash、set、k-v对,支持T级别数据。

  4. 如何让爬虫更方便的用到这些代理?

    答案是服务,使用Python的web框架,写个api供爬虫调用。这样代理和爬虫架构分离,同时有很多好处, 比如:当爬虫完全不用考虑如何校验代理,如何保证拿到的代理可用,这些都由代理池来完成。这样只需要安静的码爬虫代码就行啦。

代理池由四部分组成:

  • 获取模块:代理获取接口,负责到各大免费代理网站爬取代理。代理形式都是IP+端口

  • 存储模块:负责存储抓取下来的代理。保存到数据库。

  • 检测模块:获取到的代理不一定都能使用,因此需要对抓到的每个代理,针对未来将要爬取的网站进行检测。测试过程中,如果可用就保存,不可用就删除。并且根据每个代理的表现,给代理进行评分,分数越高可用性越高。

  • 接口模块:使用轻量级的Flask来实现一个webAPI接口。

    用Python代理池搭建——代理获取(一)_python

mg

采集模块

搭建代理池,第一步是采集代理。可以在搜索引擎搜索“代理” 关键字 ,就可以到许多代理服务网站,网站上会有很多免费代理。

用Python代理池搭建——代理获取(一)_python_02img

但是这些免费代理大多数情况下都是不好用的,所以比较靠谱的方法是购买付费代理。付费代理在很网站都有售卖,数量不用多,稳定可用即可,我们可以进行选购。

这里我们以 66 代理为例,使用了设置了 headers 模拟请求头之后就能直接拿到数据。

用Python代理池搭建——代理获取(一)_python_03img

这样我们就将数据给下载下来了。这里我只使用了一家做示范,到项目真实部署,则需要更多的免费代理,否则当大规模采集时,ip可能不够用。

用Python代理池搭建——代理获取(一)_python_04img

存储模块

数据选择保存在redis数据库中,这里不选择MySQL或者其他数据库的原因很多。第一Redis数据库非常快而且安全。并且操作足够简单。python 操作 redis 数据库需要安装一下 redis 模块。使用 pip install redis 安装即可。

使用 redis 模块操作 redis 数据库不够简单。所以对数据库操作部分进行了封装。这样只要导入就可以使用了。封装的方法主要是支持基本的链接数据库、添加数据、获取代理。

redis有序集合

使用redis有序集合存储代理:

  1. 有序集合,有键值对构成的数据集合,键又叫成员member,值又叫分值score。

  2. 分值必须是浮点数/整数型,并且按照分值的由低到高排序。

  3. 键【member】必须唯一,分值可重复

例子:键【member】:220.12.23.62 :6666      值【score】:98

定义RedisClient()类

  1. 一旦实例化该类,自动初始化【连接数据库】,并作为该实例的一个属性

  2. 类实现以下方法:

  • 初始化方法链接数据库- decrease() 判断分值,减一或者删除代理

  • random() 在分值最大范围内取随机代理

  • exist()、count()、delete() 等其他方法

用Python代理池搭建——代理获取(一)_python_05img

保存免费代理

最终导入定义好的 RedisClient 对象,将获取的代理保存到数据库、备用。

用Python代理池搭建——代理获取(一)_python_06img用Python代理池搭建——代理获取(一)_python_07img

本案例中用到的 redis 数据库可以自行到网上下载,用到的 redis 数据库管理工具也是开源的。后面再讲如何筛选代理以及提供API服务,最终搭建出代理池。