
本文详解 requests 库中 r.history 为空的原因及解决方案,重点说明服务端需使用 HTTP 状态码重定向(如 302)而非前端 JavaScript 跳转,并演示 allow_redirects=True 的必要性与实际用法。
本文详解 `requests` 库中 `r.history` 为空的原因及解决方案,重点说明服务端需使用 http 状态码重定向(如 302)而非前端 javascript 跳转,并演示 `allow_redirects=true` 的必要性与实际用法。
在使用 requests 发起 HTTP 请求时,若期望通过 r.history 获取完整的重定向链路,却始终得到空列表([]),通常并非客户端配置错误,而是服务端未按 HTTP 协议规范执行重定向。关键在于:r.history 仅记录由 HTTP 状态码(如 301、302、307)触发的服务端重定向响应,无法捕获前端 JavaScript 执行的 location.href 跳转。
在原始示例中,Flask 路由返回的是含 <script>location.href = "https://youtube.com"</script> 的 HTML 响应——这属于客户端跳转(Client-side Redirect),浏览器会执行脚本并导航,但 requests 作为纯 HTTP 客户端不会解析或执行 JavaScript,因此整个过程仅发出一次请求,无中间跳转响应,r.history 自然为空。
✅ 正确做法是:服务端应返回标准 HTTP 重定向响应。Flask 提供了 flask.redirect() 工具函数,它默认返回状态码 302 Found 并在 Location 响应头中指定目标 URL:
# webserver.py(修正版)
from flask import Flask, redirect
app = Flask(__name__)
@app.route('/')
def index():
return redirect('https://python.org') # 返回 302 + Location header
if __name__ == '__main__':
app.run('0.0.0.0', 80, debug=False) # 注意:生产环境勿用 debug=True 或 0.0.0.0同时,客户端必须显式启用重定向追踪(尽管 allow_redirects=True 是默认值,但显式声明更清晰、可维护):
立即学习“Python免费学习笔记(深入)”;
# main.py(修正版)
import requests
url = 'http://localhost:80' # ✅ 显式添加 http://,避免协议缺失导致异常
response = requests.get(url, allow_redirects=True) # ✅ 显式启用重定向
print("最终响应 URL:", response.url)
print("重定向历史:", [r.url for r in response.history])
# 示例输出:
# 最终响应 URL: https://python.org/
# 重定向历史: ['http://localhost:80/']⚠️ 注意事项:
- requests.get() 默认 allow_redirects=True,但若曾全局禁用(如 requests.adapters.HTTPAdapter(max_retries=...) 配置不当),仍可能导致重定向被忽略;
- 若服务端返回 3xx 但 Location 头缺失或格式错误,requests 将抛出 requests.exceptions.InvalidSchema 或 MissingSchema 异常;
- r.history 中每个元素均为 requests.Response 对象,可访问其 status_code、headers、url 等属性,用于调试重定向路径;
- 对于需要手动控制每一步重定向(如鉴权跳转链分析),可设 allow_redirects=False,再循环处理 response.headers.get('Location')。
总结:r.history 为空的根本原因在于重定向机制不匹配——务必使用服务端 HTTP 重定向(3xx + Location header),而非前端脚本跳转;客户端则需确保 allow_redirects=True(默认已满足),并正确构造初始 URL。遵循此模式,即可稳定获取完整、可追溯的重定向历史。









