模块介绍: 爬取网上很多公开的代理 IP 网址, HTTP HTTPS Sock5 , 去重后, 访问自己域名(返回 Json, 小于 300 字节), 用来测试匿名程度后保存
不使用代理,仅本地网络测试
设备: 联通光纤宽带(我一个人用) 下行 300M 上行 30 CPU: I7 7700HQ 4 核 8 逻辑处理器 内存: 16G
国内的服务器: 阿里云 1 核 2 内 1M
单进程 + 异步:
URL 500 个
asyncio.Semaphore(500)
aiohttp 设置超时时间为 1 秒
结果: 并发 500 的成功率为 97%左右(偶尔抽风)
每秒并发个数: 485
多进程 + 异步:
URL 500 个
5 个进程 (每个进程平均 100 个 URL)
asyncio.Semaphore(100)
aiohttp 设置超时时间为 1 秒
结果:并发 500 的成功率为 99%左右(偶尔抽风)
每秒并发个数: 495
多进程 + 异步:
URL 1600 个
8 个进程 (每个进程平均 200 个 URL)
asyncio.Semaphore(200)
aiohttp 设置超时时间为 1 秒
结果:并发 1600 的成功率为 4% ~ 75%左右(大概率低于 30%)
每秒并发个数: 64 ~ 1200
当前遇到的问题: 超过 500 并发后极其不稳定
目前猜测之所以 500 是临界点, 可能联通限制连接数 1000 导致 或是 Windows 平台 select 限制
当前策略每三秒对所有 代理 IP 访问自己服务器进行测试 测试代理 IP 超时时间为 3 秒 通过超时次数,和响应时间(使用) 对每个 IP 分配权重来筛选,排序, 所以要很大程度上减少自身网络或程序的错误, 才尽可能保证代理 IP 的准确性于可用性, 毕竟能用的 IP 太少, 误封就太可惜了
电脑性能和上行带宽没跑满, 多加几个服务器太浪费了
请问各位, 有什么方式能提高并发量, 或容错(误封可用 IP)的策略呢,
1
chizuo 2020-03-14 08:28:17 +08:00
你这个明显少了。我之前写了个爬虫 b 站排行榜的,多进程+异步 async+代理池,放到学校服务器上( 20c+48G),每秒并发可以轻松上千。不过持续不了多久,因为代理池太弱了,就会被封。
测试本地网页的话,应该能上万。 |
2
ClericPy 2020-03-14 09:16:40 +08:00
并发极限没测过, 反正协程自己跑就挺快了, requests + 多线程大概比 httpx 协程慢个 10%, gevent 不测
Test without uvloop, 12 logical CPUs. Windows-10-10.0.18362-SP0 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)] ================================================================================ test_aiohttp(3.6.2) : 2000 / 2000 = 100.0%, cost 1.158s, 1727 qps, 100.0% standard. test_httpx(0.11.1) : 2000 / 2000 = 100.0%, cost 3.927s, 509 qps, 29.47% standard. Test with uvloop, 1 logical CPUs. Linux-4.15.0-13-generic-x86_64-with-Ubuntu-18.04-bionic 3.7.3 (default, Apr 3 2019, 19:16:38) [GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] ================================================================================ test_aiohttp(3.6.2) : 2000 / 2000 = 100.0%, cost 0.698s, 2866 qps, 100.0% standard. test_httpx(0.11.1) : 2000 / 2000 = 100.0%, cost 2.337s, 856 qps, 29.87% standard. 以前随手测的, 请求本地 golang 只带 net/http 的 server |
3
lc7029 2020-03-14 11:52:52 +08:00
具体说是看你配置和网络
家用宽带可能有运营商的限制连接数或者 QOS |
4
black11black 2020-03-14 19:37:29 +08:00
很明显是你用 select 锁 512fd 的问题吧
|
5
lithbitren 2020-03-14 21:40:56 +08:00 via iPhone
@black11black 大佬,select 锁怎么解啊?我最近试了试一个挺火的 py 新框架 fastAPI,据说 qps 能上万,结果本地拿并发爬虫一打就死了,win10 上开服务并发量不能超 510,一超就爆 select 错直接垮了,stackoverflow 和 github 都没找到解答。。
|
6
ericbize 2020-03-14 21:53:05 +08:00 via iPhone
之前单位安全大佬写的 py 脚本 , 在 kvm 的 ubuntu 上面打了 12w 条连接,直接把单位的网卡死了。 背景,电信专线,固定 ip,100M
|
7
rockjike 2020-03-14 22:04:23 +08:00 via Android
一般网站,爬虫并发多大会挂掉
|
8
opengps 2020-03-14 22:29:46 +08:00
@ericbize 你们单位的网络设备支撑的在线连接数可能用满了,所以没有连接可用,表现成网络卡死。我当初 gps 系统上云是因为 5 万多买的硬件思科防火墙只能支撑 25 万 tcp 长连接
|
9
johnsona 2020-03-14 23:23:31 +08:00 via iPhone
你先把反爬虫绕过去再说
|
10
qsnow6 2020-03-14 23:33:32 +08:00
提供一个数据,python 爬虫框架的扛把子,scrapy,每秒并发可以达到 1800 request /s
|
14
lithbitren 2020-03-15 20:21:30 +08:00
我用 grequests 单线程最快每秒可以发 500-700 个 request,还没算上多进程,一次性可以同时建立数万的个协程请求,尤其找到一些复杂点的 API,没有保护的话必崩,同事里的个人几乎都被干崩过。
不过最近遇到一次严重的内存泄漏也是因为 grequests 的 gevent 给搞得,开了 20 万个协程,等了几分钟,直接爆了个 memory error,然后可能是 c 扩展里面的内存没有释放,程序炸了,idle 关了,内存占用率都还在 95%以上,开流氓工具清内存都清不掉,最后只能重启。 |
16
Cy86 OP @lithbitren 目前用 grequests 能达到 13377min/s 但 timeout 的几率有点大, 很难控制在百分之 98 以下, 我再研究研究
|
17
Cy86 OP 目前猜测是运营商的限制, 偶尔能突破 500 限制, 但阿里云和国外 VPS 测试依旧并发不满意, 服务器端可能是网络抖动的原因
目前: 国外: VPS 测试代理 IP 端口是否开放,过滤一波虚假的 家里: 单线程 异步 每秒 400 并发来使用, 3 秒能测试 1200 个代理 IP(GET 国内匿名测试服务器), 准确率达到百分之 98+% |
18
lithbitren 2020-03-15 21:46:54 +08:00
@Cy86 外网 grequests 我这边最多也就射出秒均 200-300 这样,任何做过保护的网站都会秒封 IP,只要设了 timeout 怎么都会被短暂阻塞,我测的是自己搭的本地服务框架,算上回收处理时间是 500-700,其实应该算成服务器秒内处理请求数。单纯的看发射的话,本地的秒均单进程应该可以达到 900 多,刚刚测了 1000 个请求,服务器日志的的请求间隔是 1.1 秒这样。其实对于小服务器来说,做好保护的话最多是带宽资源占用导致其他人无法正常使用服务,但也不是这么好崩的。
|
19
black11black 2020-03-16 19:24:14 +08:00
@lithbitren 建议补习基础知识....想异步爬虫就好好原生异步,不要猴子补丁....select 机能限制就这么高性能啊,我猜测 select 限制是因为 select 默认 512fd,正好符合了你说的超 500 不稳定,有问题上 epoll 啊,我又不知道你代码怎么写的,纯粹瞎猜。py 原生异步切换携程的时间消耗是微秒级的,合理配置后可以到纳秒级,十万并发不好说,网络状况合适的条件下单线程一万肯定能达到,你这么低性能都出问题明显是网络问题或者代码写的有问题。。
|
20
v2eeeeee 2020-03-16 19:48:47 +08:00
并发的时候会考虑 linux 系统设置的 ulimit (max user processes)吗?
还是说网络流的并发都是一个进程 (单线程理解为一个进程) 维护的? |
21
lithbitren 2020-03-16 20:49:34 +08:00 via iPhone
@black11black 没懂,grequests 用的 gevent 应该和之后的官方协程算另一套体系吧。。
|
22
lithbitren 2020-03-16 20:55:53 +08:00 via iPhone
@black11black grequests 的问题应该是解析数据占用了线程资源导致的效率瓶颈吧
|
23
black11black 2020-03-17 00:11:22 +08:00
@lithbitren 我一直不支持用猴子补丁,我不知道 grequests 的具体实现方式。但是你应该知道多线程是多线程,IO 复用是 IO 复用,你用线程的思考方式考虑 IO 复用是风马牛不相及的两码事。windows 下线程切换的默认时间片是十毫秒还是多少记不住了,linux 应该是几十微秒,基于线程模型理所当然是浪费大部分 IO 性能的,无所谓什么解析数据占用线程资源,就像 select 有监控上限,他不是 py 的并发极限,只是单纯你用了错误的方式而已
|
24
lithbitren 2020-03-17 01:17:10 +08:00
@black11black 不是,不推荐归不推荐,grequests 就是单纯的 gevent+request 的封装,并发爬虫几行写完了就是图个方便,协程是原理,但用 grequests 根本不需要懂协程,而且印象中是 3.5 之前就有了。单独 request 发送回收数据是需要解析时间解析的,从数据返回到数据解析成 request 对象也是需要时间的,是需要占用 GIL 资源的,切协程这个时间在解析数据这里是可以忽略不计的,但最后接收数据的时候阻塞的,如果任意一个请求的响应变慢或超时,整体的统计时间也会大幅增加。
我这里 win10 开线程的应该是不到 1ms 左右,协程应该也是几十微妙。 grequests 的核心代码就是一行 grequests.map(request_list),计时函数只能放在这行代码的前后,实质统计到的是所有请求完整生命周期的时间。 |
25
lithbitren 2020-03-17 01:34:29 +08:00
@black11black 不过我之前说的确实也不对,grequests 的发送时间统计里包括了所有 request 对象的构建,request 发送接受,对返回内容解析几个过程,并不算是实质从第一个对象发出到最后一个对象发出的时间。
|
26
chengxiao 179 天前
爬虫的极限是 代理池和账户号,其他都是浮云
|
29
macaodoll 179 天前 via Android
并发够用就行,别一味想着把你服务器性能全部打满,这样就离进去不远了。
|
30
bug123 179 天前
我对付那种并发高的爬虫也简单,不封禁,只是偶尔返回政治敏感数据
|
31
shanyaoxingtong 179 天前
代理池不够用多高的并发也没用啊,全被风控掉了
|
34
Cy86 OP @shanyaoxingtong #31 后面接了 5 家的代理池, 每天的总请求 13 亿, qps 能达到 15K, 咱们先讨论技术再讨论代理
|