控制 aiohttp 并发数最直接的方法是配置 TCPConnector 的 limit 参数,适用于需要礼貌抓取公共网页的场景。风险边界在于设置过低会导致爬取效率不足,设置过高可能触发目标服务器的反爬机制或被视为攻击。
先说结论:通过实例化 aiohttp.TCPConnector 时设定 limit 值限制连接池大小,配合 asyncio.Semaphore 控制任务并发,能有效降低对目标服务器的压力。
- 适合:需要长期稳定运行且不能触发目标封禁的爬虫任务
- 先准备:确认目标服务器是否公开允许抓取及大致承受能力
- 验收:连续运行期间目标服务器不返回 429 或 503 状态码
快速处理思路
import aiohttp
import asyncio
connector = aiohttp.TCPConnector(limit=20)
async with aiohttp.ClientSession(connector=connector) as session:
# 发起请求为什么会这样
aiohttp 默认的连接池限制可能对于某些敏感服务器过高。TCPConnector 的 limit 参数限制了客户端同时保持的最大连接数,超过该数量的请求会进入等待队列,从而物理上限制了并发请求量。
分步处理
第一步:导入 aiohttp 和 asyncio 库,确保环境已安装对应版本,操作动作是 pip install aiohttp。
第二步:实例化 TCPConnector,设置 limit 参数,例如 limit=20 表示最多 20 个同时连接,适用场景是目标服务器带宽有限。
第三步:创建 ClientSession 时传入 connector 对象,确保会话复用该限制,风险边界是忘记传入会导致使用默认配置。
第四步:在请求逻辑中加入 asyncio.sleep 随机延时,避免请求频率过于规律,验证结果是请求间隔符合预期。
第五步:使用 try-except 捕获 aiohttp.ClientError,防止单个请求失败影响整体并发控制,操作动作是包裹请求代码。
怎么验证是否生效
查看程序运行日志,确认同一时刻活跃连接数不超过设定值。观察目标服务器响应状态码,若不再出现 429 Too Many Requests,说明并发控制生效。本地可使用 netstat 命令查看 ESTABLISHED 连接数是否稳定在限制范围内。
常见坑
忘记关闭 ClientSession 会导致连接泄露,最终绕过 limit 限制。未在异步函数中使用 await 会导致并发失控。忽略 SSL 证书验证错误可能导致连接建立失败从而重试,增加服务器压力。
常见问题
aiohttp 默认并发限制是多少?
官方文档指出默认 limit 通常为 100,但建议显式设置以确保一致性。
Semaphore 和 Connector limit 有什么区别?
Connector limit 限制物理连接数,Semaphore 限制逻辑任务并发数,两者通常配合使用。
遇到 429 错误应该怎么调整?
立即降低 limit 值并增加请求间的 sleep 延时时间,直到错误消失。
参考来源
aiohttp 官方文档,Client Reference - TCPConnector,https://docs.aiohttp.org/en/stable/client_reference.html