aiohttp中不能在ClientSession初始化时设proxy,因会话级代理固定不可变;必须在每个session.get()等请求方法中单独传proxy参数,且需确保格式完整、避免传None,并配合force_close=True防止连接复用混乱。
为什么直接在
初始化时传
参数行不通
因为
的
参数是会话级的,一旦创建就固定绑定到某个代理地址,后续所有请求都复用它。你没法在单个 session 里“中途换代理”。强行改
属于黑盒操作,不稳定且在新版本中可能失效。
常见错误现象:
或请求仍走旧代理,甚至引发连接复用混乱。
真正可行的方式是:每个请求单独指定
参数
必须确保每次调用
/
等方法时,显式传入当前要使用的代理 URL
注意代理 URL 格式必须完整,例如
或
;不支持只传 host:port
如何在并发请求中为每个任务分配不同代理
核心思路是把代理列表和待抓取 URL 列表 zip 起来,或用
统一调度。避免多个协程争抢同一个代理导致限速/封禁。
实操建议:
立即学习
“
Python免费学习笔记(深入)
”;
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
用
轮询代理(适合简单轮换,但无法感知代理失效)
更稳妥的做法是维护一个可异步获取代理的函数,比如
,内部做健康检查(如先发 HEAD 请求验证连通性)
不要在
外层做代理选择逻辑,而应在每个
调用前确定代理值
示例片段:
——
必须是字符串,不能是
;若某次不想用代理,就别传
参数,而非传
遇到
怎么关联到代理问题
这个错误本身不指明是代理挂了还是目标站挂了。需要结合
或日志上下文判断。
容易踩的坑:
代理认证失败时,aiohttp 默认抛
(状态码 407),但有时会被底层 SSL 或连接层吞掉,最终表现为
代理超时或无响应,会触发
,但常被包裹进
中
建议在捕获异常后加一句:
做粗略过滤(虽然不严谨,但比完全盲猜强)
调试阶段可在请求前打印
,并用
手动验证该代理是否可用
代理切换频率太高会不会被 aiohttp 自动复用连接池搞乱
会。aiohttp 默认启用连接池(
),而连接池是按 host + port +
proxy
组合索引的。如果频繁切换代理,会导致大量空闲连接堆积,内存缓慢上涨,甚至触发
。
解决方案很直接:
初始化
时传
——
关键,它让每次请求后主动关闭 TCP 连接,避免复用到不同代理
或者更精细地控制:为每个代理单独建一个短生命周期的
(不推荐,开销大),不如统一用
+ 合理的
注意:设了
后,HTTP/1.1 的 keep-alive 会失效,但对代理场景影响不大——反正你本来就不想复用连接
代理池的实效性永远比切换逻辑更重要。再漂亮的异步调度,也救不了已经失效的代理列表。上线前务必加一层实时探测,别只靠“上次能用”来假设。
aiohttp.ClientSessionproxyaiohttp.ClientSessionproxysession._default_proxyAttributeError: can't set attributeproxysession.get()post()http://user:pass@host:porthttp://host:portasyncio.Queueitertools.cycle()async def get_valid_proxy()ClientSessionsession.request()async with session.get(url, proxy=proxy_url) as resp:proxy_urlNoneproxyNoneaiohttp.client_exceptions.ClientConnectorErrorexception.__cause__ClientResponseErrorClientConnectorErrorasyncio.TimeoutErrorClientConnectorErrorif "proxy" in str(exc).lower(): ...proxy_urlcurl -xTCPConnectorToo many open filesClientSessionconnector=aiohttp.TCPConnector(limit_per_host=10, force_close=True)force_close=TrueClientSessionforce_close=Truelimit_per_hostforce_close=True