python 请求库 requests 使用代理造成内存泄漏
背景
在网上买了短效代理套餐,平均10s产出一个ip,一个ip的有效时长在3分钟左右,使用requests写一个简单爬虫,每次提取一个新的代理发送请求,如果没有新的代理就用之前没有过期的代理,请求的并发在每秒5个左右,当爬虫运行一段时间后会发现内存一直往上涨且网络环境变得极其糟糕。
定位问题
尝试中断程序看看内存和网络程序的情况
- 网络问题会随着时间的推移逐渐好转
- 内存问题直接就回到没有运行爬虫之前了
重新运行程序并开始监控网络状况
发现正在连接的数量一直往上涨,由于我用的是连接池,所以猜测应该是连接池内的连接没有释放掉导致的。
requests 连接池实现
requests 的连接池其实就是个字典,字典的key 是本地ip+本地ip的port+目标ip+目标ip的port(代理ip+代理ip的port)
字段的value 就是已经建立的连接,由于我使用的是短效代理所以几乎,每隔10s 这个字典都会增加一个key,value.
原因
- 由于使用的是短效代理,所以每隔10s 连接池都会至少增加一个连接。从而无限累加
- requests 不会主动释放之前的连接,导致内存无法释放
- 当出现大量连接无法释放的时候,网络问题也会变的非常差
解决方法
- 定时主动释放连接池的连接 (注意把握好场景,不然弄巧成拙)
- 使用短链接(会影响网络,慎用)
- 使用其它没有这方面的库(python 几乎所有的库都有这个问题,因为这是python 这门语言决定的)
使用golang 完美解决问题
为什么golang 没有这个问题呢
这是由于golang 在创建一个连接后会直接启动两个协程(一个读,一个写)。由于代理的时效性是3分钟,3分钟一到,读取肯定有异常,进而直接释放连接。
但是python 就不行了,python 它只有使用的时候才知道这个连接是否异常。
gospider 介绍
gospider 是一个golang 爬虫神器,拥有python到golang爬虫过渡的所有必需库。用于python爬虫从业者快速且无坑的过渡到golang
安装
go get -u gitee.com/baixudong/gospider
gitee地址
https://gitee.com/baixudong/gospider
github地址
https://github.com/baixudong007/gospider