requests 默认自动跟随302重定向,最多30次;可通过Session.max_redirects设置全局跳转上限,设为0则禁用跳转,或手动控制并检测循环。

requests 默认如何处理 302 重定向
默认情况下,requests 会自动跟随 302(以及 301、307、308)响应中的 Location 头,最多跳转 30 次。这个行为由 allow_redirects=True 和内置的 RedirectHandler 控制。一旦服务器返回的跳转链形成闭环(比如 A → B → C → A),而默认限制又没被触发或绕过,就可能卡住、超时,甚至抛出 requests.exceptions.TooManyRedirects。
用 max_redirects 显式限制跳转次数
最直接有效的办法是关闭自动跳转,自己控制逻辑,或通过 Session 设置全局最大跳转数。注意:requests 本身没有 max_redirects 参数,但可以通过配置 Session 的 max_redirects 属性实现:
import requests
<p>session = requests.Session()
session.max_redirects = 5 # ⚠️ 这个值必须是整数,设为 0 则完全禁用跳转</p><p>try:
resp = session.get("<a href="https://www.php.cn/link/f4693942620b18fb077b314ab3b8f369">https://www.php.cn/link/f4693942620b18fb077b314ab3b8f369</a>", timeout=10)
except requests.exceptions.TooManyRedirects:
print("检测到重定向循环,已按 max_redirects=5 中断")
-
session.max_redirects是 Session 级别设置,对所有后续请求生效 - 设为
0时,allow_redirects即使为True也不跳转(等价于allow_redirects=False) - 若单次请求需特殊处理,仍可传
allow_redirects=False,再手动解析resp.headers.get("Location")
手动处理跳转并检测循环
当需要识别“是否回到已访问过的 URL”时,自动跳转机制不够用。此时应禁用自动跳转,自己维护访问历史:
def fetch_with_loop_check(url, max_hops=5):
visited = set()
current = url
for i in range(max_hops + 1):
if current in visited:
raise ValueError(f"重定向循环 detected at {current}")
visited.add(current)
<pre class="brush:php;toolbar:false;"> resp = requests.get(current, allow_redirects=False, timeout=8)
if resp.status_code in (301, 302, 307, 308):
next_url = resp.headers.get("Location")
if not next_url:
break
# 处理相对重定向(如 /path)
from urllib.parse import urljoin
current = urljoin(current, next_url)
else:
return resp
raise RuntimeError(f"超过最大跳转次数 {max_hops}")
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
- 务必用
urljoin()解析Location,否则相对路径会出错 - 检查
307和308(它们保留原始请求方法,但常被忽略) -
visited存的是标准化后的 URL(建议用urllib.parse.urldefrag去掉 fragment)
为什么有时 max_redirects 不生效
常见失效场景包括:
- 用了
requests.get(..., allow_redirects=False),此时session.max_redirects完全不参与 - 中间某次跳转返回了非标准
Location(比如空格、编码错误),导致urljoin解析失败,后续请求 URL 变成None或乱码,跳转中断但未报错 - 某些反爬服务故意返回「看似不同实则等价」的 URL(如带不同 query 参数但路由相同),仅靠字符串匹配无法识别循环
- HTTPS → HTTP 跳转时,部分旧版
requests(max_redirects 限制
真正可靠的循环检测,得结合 URL 规范化 + 状态码 + 响应特征(比如 Set-Cookie 是否重复),不能只依赖跳转次数计数。

















