文章目录
(前排提示:文末有总结表格方便保存!!!)
最近在调试Python爬虫时突然遇到了这个让人头秃的报错:HTTPConnectionPool(host='117.89.172.166', port=31265): Max retries exceeded...
。作为一个被这个问题折磨了整整两天的过来人,必须给大家分享这个价值10W+的经验总结!(别问,问就是加班费都赔进去了)
一、现象还原现场(必看)
当你的requests请求出现以下任意症状时:
# 典型报错1:连接超时
requests.exceptions.ConnectTimeout: HTTPConnectionPool...
# 典型报错2:重试耗尽
requests.exceptions.ConnectionError: HTTPConnectionPool...
(注意看!!)报错信息里这两个关键线索:
Max retries exceeded
:重试次数用完了Failed to establish a new connection
:TCP三次握手失败
二、四大元凶排查指南(对号入座)
1. 网络层问题(最常见!!)
👉 症状:能ping通但无法建立TCP连接
# 先测ICMP连通性
ping 117.89.172.166
# 再测TCP端口连通性(关键!!)
telnet 117.89.172.166 31265
(实战技巧)如果telnet卡住或报错:
- 检查目标服务器防火墙规则
- 确认本地是否有网络代理(特别是公司内网环境!)
- 试试换个网络环境(比如手机热点)
2. 客户端配置问题(新手必踩坑)
案例重现:某次我在requests请求里忘记加超时参数…
# 错误示范(没有timeout)
response = requests.get(url)
# 正确姿势(设置合理超时)
response = requests.get(url, timeout=(3.05, 27))
(超级重要)三个必须设置的参数:
requests.get(
url,
timeout=(连接超时, 读取超时), # 推荐(3, 10)
verify=False, # 跳过SSL验证(慎用!)
proxies={...} # 代理配置
)
3. 服务端问题(最无奈的情况)
当出现Connection reset by peer
时:
- 检查目标服务器是否开启
- 查看服务器防火墙日志
- 确认端口监听状态(netstat -tulnp)
4. 连接池泄漏(高阶问题)
长期运行的程序可能出现这种情况:
# 强制释放连接池(救命大招!)
import requests
from requests.adapters import HTTPAdapter
session = requests.Session()
session.mount('http://', HTTPAdapter(pool_connections=100, pool_maxsize=100))
三、六步绝杀解决方案(跟着做就对了)
Step 1:基础检查
- 检查URL拼写(别笑!真的有人把http写成htp)
- 确认端口号是否正确(常见80/443搞混)
- 试着重启大法(真的有用…)
Step 2:网络诊断
# 使用socket直接建立TCP连接
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
try:
s.connect(('117.89.172.166', 31265))
print("TCP连接成功!")
except Exception as e:
print(f"连接失败:{str(e)}")
finally:
s.close()
Step 3:调整请求参数
# 终极保命配置模板
response = requests.get(
url,
timeout=(3.05, 30),
headers={'User-Agent': 'Mozilla/5.0'},
verify=False,
proxies={
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
},
allow_redirects=False
)
Step 4:启用重试机制
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
retry_strategy = Retry(
total=5,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)
Step 5:抓包分析(高端操作)
使用Wireshark抓取TCP握手包:
- 过滤条件:
tcp.port == 31265
- 观察三次握手过程
- 检查是否有RST包
Step 6:终极解决方案
如果以上都失败,请依次尝试:
- 更换DNS(推荐8.8.8.8/114.114.114.114)
- 关闭IPv6(
sysctl -w net.ipv6.conf.all.disable_ipv6=1
) - 更新requests库(
pip install --upgrade requests
)
四、预防措施大全(血泪总结)
场景 | 预防方案 | 代码示例 |
---|---|---|
不稳定网络环境 | 增加重试次数 + 随机延迟 | Retry(total=5, backoff_factor=1) |
高并发场景 | 调整连接池大小 | HTTPAdapter(pool_maxsize=100) |
需要长期运行 | 定期重置Session | session = requests.Session() |
代理环境 | 正确配置proxies | proxies={'http':'x.x.x.x:8080'} |
(最后叮嘱)遇到这类网络问题千万不要慌!按照这个排查流程图来:
网络层检查 → 客户端配置 → 服务端状态 → 高级调试。保存好这个指南,下次遇到类似问题直接拿出来对照,保证节省你80%的调试时间!
彩蛋:当所有方法都失败时,试试这个玄学操作 —— 把代码里的端口号+1或者-1,有时候会有奇迹发生!(别问原理,问就是量子编程)