connectionreseterror是服务端主动断连所致,非代码bug;常见于反爬触发、连接复用冲突或负载保护,应禁用连接池、添加请求间隔与ua轮换、实现指数退避重试。

ConnectionResetError 通常不是代码 bug,而是服务端主动断连
这个异常本质是 TCP 连接在传输中途被对方(目标网站)强制关闭,Python 底层抛出 ConnectionResetError: [Errno 104] Connection reset by peer。它和网络超时、DNS 失败不同,说明请求已发出、甚至响应头都可能收到了,但服务端突然中止了连接——常见于反爬策略触发、连接复用冲突或服务端负载保护。
检查并禁用 requests 的默认连接池复用
requests 默认启用 urllib3 连接池(HTTPAdapter),复用 TCP 连接能提升性能,但在面对严格反爬的站点时,复用旧连接容易因 Cookie/headers 状态不一致被识别为异常行为,导致服务端重置连接。
实操建议:
- 显式创建 session 并禁用连接池:
import requests session = requests.Session() adapter = requests.adapters.HTTPAdapter(pool_connections=0, pool_maxsize=0) session.mount('http://', adapter) session.mount('https://', adapter) - 或者更彻底:每次请求都用全新 session,避免任何状态残留
- 注意:禁用连接池会增加建连开销,仅在确认是复用引发问题时启用
添加合理请求间隔与 User-Agent 轮换
高频、无变化的请求特征(如固定 User-Agent、无 Referer、毫秒级间隔)极易触发 Nginx 或 WAF 的连接重置规则。这不是“封 IP”,而是每条连接建立后立即被拒绝。
实操建议:
- 使用
time.sleep()控制节奏,单域名建议 ≥1.5 秒间隔;若并发抓取,需按域名独立限速 - 轮换
User-Agent字符串(从真实浏览器 UA 池中随机选),避免 header 中出现python-requests等标识 - 必要时补全
Accept、Accept-Language、Referer等字段,模拟完整浏览器请求上下文
捕获异常并实现带退避的重试逻辑
单纯 try/except 吞掉 ConnectionResetError 不解决问题,反而掩盖真实瓶颈。应结合指数退避(exponential backoff)重试,并限制总尝试次数。
实操建议:
- 用
tenacity库最省心:from tenacity import retry, stop_after_attempt, wait_exponential @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10)) def fetch_with_retry(url): return requests.get(url, timeout=10) - 手动实现时,务必在每次重试前
time.sleep(2 ** attempt),且首次失败后至少等 2 秒再试 - 重试仅对瞬时性连接重置有效;若连续 3 次都触发该异常,大概率是 IP 或行为已被标记,应暂停该 IP 抓取
真正难处理的是那种偶发、不可复现、又不伴随其他错误码(如 429、503)的 ConnectionResetError——它往往意味着你已经踩到了目标站反爬策略的模糊边界。此时日志里记录每次失败的 URL、时间戳、headers 快照,比加更多重试更有价值。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











