目录
爬虫基础篇之IP代理池
代理池介绍
由众多ip组成提供多个稳定可用代理IP的ip池。
当我们做爬虫时,最常见的反爬手段就是IP反爬,当同一个IP访问网站超出频控限制,将会被限制访问,那么代理IP池应运而生。资金充足的情况下个人建议还是付费ip代理池,比较免费ip时效性低,且难以维护。
爬取流程
代理IP采集模块: 采集代理IP -> 检测代理IP ->如果不可用用, 直接过滤掉, 如果可用, 指定默认分数 -> 存入数据库中
代理IP检测模块: 从数据库中获取所有代理IP -> 检测代理IP -> 如果代理IP不可用用, 就把分数-1, 如果分数为0从数据库中删除, 否则更新数据库, 如果代理IP可用, 恢复为默认分值,更新数据库
代理API模块:从数据库中高可用的代理IP给爬虫使用;
模块
爬虫模块
从代理IP网站上采集代理IP ,对抓取的ip进行校验(获取代理响应速度, 协议类型, 匿名类型), 并存储到数据库中。
校验模块
网站上所标注的响应速度,协议类型和匿名类型是不准确的,通过http://httpbin.org进行检测,获取指定代理的响应速度, 支持的协议以及匿名程度。
数据库模块
使用MongoDB来存储代理IP并实现对代理IP的增删改查操作。
检测模块
定时从数据库读取所有的代理IP,对代理IP进行逐一检测, 开启多个协程, 以提高检测速度,如果该代理不可用, 就让这个代理分数-1, 当代理的分数到0了, 就删除该代理; 如果检测到代理可用就恢复为满分。
API模块
根据协议类型和域名获取多个随机的高质量代理IP,根据代理IP不可用域名, 告诉代理池这个代理IP在该域名下不可用, 下次获取这个域名的代理IP时候, 就不会再获取这个代理IP了, 从而保证代理IP高可用性。
其他模块
数据模型
代理IP的数据模型, 用于封装代理IP相关信息, 比如ip,端口号, 响应速度, 协议类型, 匿名类型,分数等。
程序入口
代理池提供一个统一的启动入口
工具模块
日志模块: 用于记录日志信息
http模块: 用于获取随机User-Agent的请求头
配置文件
用于默认代理的分数, 配置日志格式, 文件, 启动的爬虫, 检验的间隔时间 等。
实战
思路1:依据流程图,逐步实现各个模块,当需要依赖其他模块时,暂停当前模块,开发其他模块功能,实现完毕再回头开发联调。
思路2:先实现不依赖其他模块的基础模块,再逐步实现具体的功能模块,比如爬虫模块, 检测模块, 代理API模块。
这里我们选择思路2实现爬虫代理IP池,因为思路1适合个人完成,不适合分工合作,且不易维护,思路跳来跳去,必须逻辑清晰。
数据模型domain
settings.py 中 定义MAX_SCORE = 50, 表示代理IP的默认最高分数
日志模块log
导入settings中日志配置信息,如下
LOG_LEVEL = logging.DEBUG # 默认等级
LOG_FMT = ‘%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s’ # 默认日志格式
LOG_DATEFMT = ‘%Y-%m-%d %H:%M:%S’ # 默认时间格式
LOG_FILENAME = ‘log.log’ # 默认日志文件名称
请求模块http
返回随机请求头和随机User-Agent,对抗反爬
校验模块httpbin_validator
检查代理IP速度 和 匿名程度;
代理IP速度: 就是从发送请求到获取响应的时间间隔
匿名程度检查:
对 http://httpbin.org/get 或 https://httpbin.org/get 发送请求
如果 响应的origin 中有’,分割的两个IP就是透明代理IP
如果 响应的headers 中包含 Proxy-Connection 说明是匿名代理IP
否则就是高匿代理IP
检查代理IP协议类型
如果 http://httpbin.org/get 发送请求可以成功, 说明支持http协议
如果 https://httpbin.org/get 发送请求可以成功, 说明支持https协议
数据库模块mongo_pool
在init中, 建立数据连接, 获取要操作的集合, 在 del 方法中关闭数据库连接
提供基础的增删改查功能
提供代理API模块使用的功能
实现查询功能: 根据条件进行查询, 可以指定查询数量, 先分数降序, 速度升序排, 保证优质的代理IP在上面.
实现根据协议类型 和 要访问网站的域名, 获取代理IP列表
实现根据协议类型 和 要访问网站的域名, 随机获取一个代理IP
实现把指定域名添加到指定IP的disable_domain列表中.
爬虫模块base_spider
在base_spider.py文件中,定义一个BaseSpider类, 继承object
提供三个类成员变量:
urls: 代理IP网址的URL的列表
group_xpath: 分组XPATH, 获取包含代理IP信息标签列表的XPATH
detail_xpath: 组内XPATH, 获取代理IP详情的信息XPATH, 格式为: {‘ip’:‘xx’, ‘port’:‘xx’, ‘area’:‘xx’}
提供初始方法, 传入爬虫URL列表, 分组XPATH, 详情(组内)XPATH
对外提供一个获取代理IP的方法
遍历URL列表, 获取URL
根据发送请求, 获取页面数据
解析页面, 提取数据, 封装为Proxy对象
返回Proxy对象列表
具体爬虫实现proxy_spiders
实现西刺代理爬虫: http://www.xicidaili.com/nn/1
定义一个类,继承通用爬虫类(BasicSpider)
提供urls, group_xpath 和 detail_xpath
实现ip3366代理爬虫: 云代理 - 高品质http代理ip供应平台/每天分享大量免费代理IP
定义一个类,继承通用爬虫类(BasicSpider)
提供urls, group_xpath 和 detail_xpath
实现快代理爬虫: 国内高匿免费HTTP代理IP - 快代理
定义一个类,继承通用爬虫类(BasicSpider)
提供urls, group_xpath 和 detail_xpath
实现proxylistplus代理爬虫: https://list.proxylistplus.com/Fresh-HTTP-Proxy-List-1
定义一个类,继承通用爬虫类(BasicSpider)
提供urls, group_xpath 和 detail_xpath
实现66ip爬虫: 免费代理ip_服务器http代理_最新ip代理_免费ip提取网站_国内外代理_66免费代理ip
定义一个类,继承通用爬虫类(BasicSpider)
提供urls, group_xpath 和 detail_xpath
由于66ip网页进行js + cookie反爬, 需要重写父类的get_page_from_url方法
访问http://www.66ip.cn/1.html 时返回一堆js,并不返回具体ip信息,通过逐步增加请求头中的Cookie时发现真正生效的Cookie为_ydclearance,控制台打开Preserve log发现页面第一次1.html做了跳转,历史请求中都没有出现_ydclearance的cookie,第二次请求1.html时已经携带了_ydclearance说明该cookie已经不是服务端响应生成,而是由客户端js生成。
一开始我们访问http://www.66ip.cn/1.html 时返回一堆js,执行这段js,就是用来生成_ydclearance的。那么分析这段js本身做了加密,js中通过定义函数jp并调用后,由于qo=eval,那么等同于最终调用了eval(po),真正js在 “po” 中。
通过正则提取jp(107)调用函数方法, 以及函数内容function jp(WI) { var qo, mo="" ...,通过将替换eval拿到返回的真实js
执行js并将返回作为Cookie添加到请求头中
运行爬虫模块run_spiders
创建RunSpider类
提供一个运行爬虫的run方法
根据配置文件信息, 加载爬虫, 把爬虫对象放到列表中
遍历爬虫对象列表, 获取代理, 检测代理(代理IP检测模块), 写入数据库(数据库模块)
使用异步来执行每一个爬虫任务
每隔一定的时间, 执行一次爬取任务
settings配置RUN_SPIDERS_INTERVAL作为爬虫运行时间间隔的配置, 单位为小时
检测模块proxy_test
创建ProxyTester类,检查代理IP可用性, 保证代理池中代理IP基本可用
提供一个 run 方法, 用于处理检测代理IP核心逻辑
从数据库中获取所有代理IP
遍历代理IP列表
检查代理可用性
如果代理不可用, 让代理分数-1, 如果代理分数等于0就从数据库中删除该代理, 否则更新该代理IP
如果代理可用, 就恢复该代理的分数, 更新到数据库中
为了提高检查的速度, 使用异步来执行检测任务
把要检测的代理IP, 放到队列中
把检查一个代理可用性的代码, 抽取到一个方法中; 从队列中获取代理IP, 进行检查; 检查完毕, 调度队列的task_done方法
通过异步回调, 使用死循环不断执行这个方法,
开启多个一个异步任务, 来处理代理IP的检测; 可以通过配置文件指定异步数量
使用schedule模块, 每隔一定的时间, 执行一次检测任务
定义类方法 start, 用于启动检测模块
在start方法中
创建本类对象
调用run方法
每间隔一定时间, 执行一下, run方法
setting.py 文件, 检查代理IP可用性间隔时间的配置
RUN_SPIDERS_INTERVAL = 2 # 修改配置文件, 增加爬虫运行时间间隔的配置, 单位为小时
TEST_PROXIES_ASYNC_COUNT = 10 # 配置检测代理IP的异步数量
TEST_PROXIES_INTERVAL = 2 # 配置检查代理IP的时间间隔, 单位是小时
API模块proxy_api
创建ProxyApi类,为爬虫提供高可用代理IP的服务接口
实现初始方法
初始一个Flask的Web服务
实现根据协议类型和域名, 提供随机的获取高可用代理IP的服务
可用通过 protocol 和 domain 参数对IP进行过滤
protocol: 当前请求的协议类型
domain: 当前请求域名
实现根据协议类型和域名, 提供获取多个高可用代理IP的服务
可用通过protocol 和 domain 参数对IP进行过滤
实现给指定的IP上追加不可用域名的服务
如果在获取IP的时候, 有指定域名参数, 将不在获取该IP, 从而进一步提高代理IP的可用性.
实现run方法, 用于启动Flask的WEB服务
实现start的类方法, 用于通过类名, 启动服务
settings中配置PROXIES_MAX_COUNT配置获取的代理IP最大数量; 这个越小可用性就越高; 但是随机性越差
启动入口main
定义一个run方法用于启动动代理池,开启三个进程, 分别用于启动爬虫, 检测代理IP, WEB服务
定义一个列表, 用于存储要启动的进程
创建 启动爬虫 的进程, 添加到列表中
创建 启动检测 的进程, 添加到列表中
创建 启动提供API服务 的进程, 添加到列表中
遍历进程列表, 启动所有进程
遍历进程列表, 让主进程等待子进程的完成
在 if __name__ == __main__: 中调用run方法
这里推荐一款适合爬虫的代理ip,遍及全国200多个城市,千万级IP池,24小时自动去重,IP可用率超越95%,稳定、高效、高匿,具有强大的技术团队,7*24处理运用中的问题,现在注册还能免费领取一万代理IP
代理云 - 可视化用户控制台console.v4.dailiyun.com/user/?channel=wyh-zh