我的知识记录

Python requests设置超时与重试:网络抖动自动恢复

讲解requests设置timeout防止卡死,用urllib3的Retry适配器实现失败自动重试,配合backoff指数退避,提升网络抓取脚本的健壮性。

场景痛点

跑爬虫脚本跑到一半卡住不动,Ctrl+C一看是某个请求永远等不到响应;或者临时网络抖了一下,整批任务就挂了。生产环境的抓取脚本必须做两件事:每个请求设超时,失败自动重试几次。requests本身不带重试,需要挂一个urllib3的Retry适配器。

用到的库

pip install requests beautifulsoup4 lxml

完整代码

# 导入库
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def build_session():
"""构造一个带自动重试的Session"""
session = requests.Session()

# 定义重试策略
retry_strategy = Retry(
total=3,                    # 总共重试3次
backoff_factor=1,           # 退避因子:第1次等1秒,第2次2秒,第3次4秒
status_forcelist=[429, 500, 502, 503, 504],  # 遇到这些状态码才重试
allowed_methods=["GET", "POST"],  # 对哪些方法重试
)

# 把重试策略挂载到Session上,HTTP和HTTPS都生效
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)

return session

def fetch(url):
"""用带重试的session发请求"""
session = build_session()
try:
# timeout=(连接超时, 读取超时),单位秒
resp = session.get(url, timeout=(5, 15))
resp.raise_for_status()
print("成功:", url, resp.status_code, len(resp.text), "字节")
return resp.text
except requests.exceptions.RequestException as e:
print("最终失败:", url, "原因:", e)
return None

def main():
# 测试一个正常URL
fetch("https://httpbin.org/get")
# 测试一个必然失败的URL,观察重试过程
fetch("https://httpbin.org/status/500")

if __name__ == "__main__":
main()

代码讲解

  • timeout 可以传一个元组 (connect, read),分别控制连接阶段和读取阶段的超时,比单个数字更精细。
  • Retry 是urllib3提供的重试策略:total 是总次数,backoff_factor 控制每次重试前等待多久(指数退避:1秒、2秒、4秒),避免雪崩。
  • status_forcelist 列出哪些HTTP状态码值得重试,429是限流,5xx是服务器临时故障,404这种永久错误不重试。
  • HTTPAdapter 把重试策略挂到Session上,之后这个session发的所有请求都自动应用重试规则,不用每个请求单独写。
  • allowed_methods 指定对哪些HTTP方法重试,POST默认不重试(怕重复提交),这里因为是查询接口所以加上。

运行结果

第一个URL正常返回200;第二个URL返回500,脚本会自动重试3次(间隔1秒、2秒、4秒),最后打印"最终失败"。整个过程不会卡死,也不会因为一次网络抖动就终止。

注意事项

  • 超时时间要根据实际网络环境调,本地访问内网接口3秒够了,访问海外接口可能要30秒。
  • 重试不要无脑重试所有错误,400、404这种客户端错误重试一万次也没用。
  • POST请求重试要谨慎,可能造成重复提交,只对幂等接口(查询类)开重试。
  • 重试日志要打出来,方便排查到底是网络问题还是对方服务挂了。

Python requests设置超时与重试:网络抖动自动恢复

标签:

更新时间:2026-09-14 20:47:04

上一篇:Python requests伪装User-Agent反爬:随机切换与Headers池

下一篇:Python requests保持会话Session:跨请求保留Cookie