ConnectionError本质是服务端主动拒绝连接,而非本地网络不通;常见于请求特征触发反爬机制,需通过curl和浏览器交叉验证,优化代理池、延迟策略及Session配置来规避拦截。

ConnectionError 本质是连接被主动切断,不是网络不通
看到 requests.exceptions.ConnectionError 别急着查本地网络——多数情况下,目标服务器已识别出你的请求模式(高频、无头、单IP),直接在 TCP 层拒绝握手或中途 RST。错误日志里常带 [WinError 10054] 或 Remote end closed connection,这说明对方“不想跟你连”,而非你连不上。
验证方法很简单:curl -v https://target.com 在终端跑一次;如果也失败,再换浏览器访问。两者都通,但 Python 脚本失败,基本锁定是请求特征触发了服务端拦截。
- 不要用
time.sleep(0.1)这类固定短延迟,容易被统计模型识别为爬虫节奏 - 避免复用同一个
requests.Session()对象持续发请求,某些 CDN 会基于 TCP 连接复用特征做判断 - 禁用
'Connection': 'close'头,它反而会让连接更“可疑”——真实浏览器默认 keep-alive
代理池必须带实时可用性校验,不能只靠列表轮询
扔一堆代理 IP 进列表然后 random.choice(proxy_list) 是最常见却最无效的做法。大量代理实际已失效、延时超高或返回 403/407,直接导致 ProxyError 或 Timeout,掩盖了原始问题。
真正可用的代理池要满足三个条件:能连通、能转发、能返回真实 IP。推荐用 http://httpbin.org/ip 做探测端点,且必须用多线程并发验证(单线程检测 100 个代理要几分钟):
立即学习“Python免费学习笔记(深入)”;
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
def check_proxy(proxy_url):
try:
proxies = {'http': proxy_url, 'https': proxy_url}
r = requests.get('http://httpbin.org/ip', proxies=proxies, timeout=3)
return proxy_url if r.status_code == 200 and 'origin' in r.json() else None
except:
return None
- 每次请求前从校验过的活跃池中取一个,用完即弃,不缓存连接
- 代理 URL 格式必须完整,例如
http://user:pass@host:port,缺认证字段会报ProxyAuthenticationError - 避免使用免费公开代理列表,99% 的存活率低于 5 分钟,还可能带恶意 header 注入
延迟不能只靠 sleep,得加随机抖动和响应反馈
单纯 time.sleep(2) 是静态节拍器,服务器很容易建模识别。真实用户操作有天然抖动:页面停留时间不等、滚动速度不一、点击间隔非整数秒。爬虫要模拟这个“不规律”。
更关键的是:延迟值应根据上一次响应动态调整。比如收到 429(Too Many Requests),下一轮延迟翻倍;收到 200 且 response.elapsed.total_seconds() < 0.8,说明代理快、可小幅缩短间隔。
- 基础抖动公式:
time.sleep(random.uniform(1.5, 4.2)),范围别太窄(如 1–1.1 秒) - 遇到
ConnectionResetError后,别立刻重试,先 sleep 至少 3 秒,否则大概率二次失败 - 不要在循环开头统一 sleep —— 应该在
response = requests.get(...)之后、处理数据之前 sleep,让“请求-等待-解析”形成自然节奏
Session 复用和连接池配置容易适得其反
文档常说“用 Session 提高性能”,但在反爬场景下,它常常是雷区。HTTPAdapter 默认的连接池(pool_connections=10, pool_maxsize=10)会让多个请求共享底层 TCP 连接,而某些 WAF(如 Cloudflare)会把这种复用行为标记为“非浏览器特征”。
如果你发现加了 Session 后 ConnectionError 反而增多,试试彻底关闭连接复用:
s = requests.Session()
s.mount('http://', requests.adapters.HTTPAdapter(pool_connections=1, pool_maxsize=1))
s.mount('https://', requests.adapters.HTTPAdapter(pool_connections=1, pool_maxsize=1))
- 每次请求都走新 TCP 握手,看起来更像独立标签页访问
- 务必配
timeout=(3, 7)(连接 3 秒 + 读取 7 秒),避免某个慢代理拖垮整个流程 -
verify=True必须保留,关 SSL 验证不仅危险,还会让部分 HTTPS 站点直接拒绝连接
真正难的不是写对几行代码,而是让每次请求的 TCP 行为、TLS 握手指纹、HTTP 头组合、时间间隔分布,都落在真实浏览器的统计方差范围内。代理和延迟只是表层,底层连接策略才是服务器真正在看的“身份证”。

















