
本文详解如何通过 requests.Session 维持登录态,安全下载需身份认证的图片或 PDF 等资源,解决因缺失 Cookie 或会话导致的“下载空文件(14 KB)”问题。
本文详解如何通过 requests.session 维持登录态,安全下载需身份认证的图片或 pdf 等资源,解决因缺失 cookie 或会话导致的“下载空文件(14 kb)”问题。
在 Web 自动化下载场景中,许多文件(如服务报告、工程图纸、审批附件)托管在需登录才能访问的后台系统中。直接用 urllib.request.urlretrieve 或无状态 requests.get() 请求这类资源时,即使 URL 正确,服务器通常仅返回一个轻量级 HTML 登录页(约 14 KB),而非真实文件——这正是用户反复遇到“文件已下载但打不开”的根本原因:请求未携带有效会话凭证(如登录后的 cookies)。
✅ 正确方案:使用 requests.Session 管理登录态
requests.Session 能自动持久化服务器返回的 cookies,并在后续请求中自动携带,模拟真实浏览器行为。以下是完整、健壮的实现步骤:
import requests
import os
# 1. 创建会话对象(自动管理 cookies)
session = requests.Session()
# 2. 构造登录请求(关键:确认实际登录接口与字段名)
login_url = "https://assetplanner.com/login" # 替换为真实登录地址
login_data = {
"username": "your_username", # 注意:字段名需与网页表单一致(常为 username/email)
"password": "your_password", # 部分系统可能含 csrf_token、remember_me 等隐藏字段
}
# 3. 发起登录(POST)
login_resp = session.post(login_url, data=login_data, timeout=10)
# 4. 检查登录是否成功(建议结合状态码 + 关键响应内容双重验证)
if login_resp.status_code == 200 and "dashboard" in login_resp.text.lower():
print("✅ 登录成功!")
else:
print(f"❌ 登录失败,HTTP 状态码:{login_resp.status_code}")
print("提示:检查用户名/密码、登录接口 URL、表单字段名(如是否为 'email' 而非 'username')")
exit(1)
# 5. 使用同一会话下载受保护文件(URL 中的 token 可能仍需保留)
file_url = "https://assetplanner.com/files/ServiceRequest/616/img_20241021093256.jpg?token=#####"
response = session.get(file_url, timeout=30)
# 6. 验证并保存文件
if response.status_code == 200:
# 自动推断扩展名(可选增强)
content_type = response.headers.get('content-type', '')
ext = '.jpg' if 'jpeg' in content_type or 'jpg' in content_type else '.pdf'
filename = f"downloaded_file{ext}"
with open(filename, 'wb') as f:
f.write(response.content)
print(f"✅ 文件已保存为:{os.path.abspath(filename)}")
else:
print(f"❌ 文件下载失败,状态码:{response.status_code}")
print("提示:检查文件 URL 是否有效、token 是否过期、服务器是否要求额外 Headers(如 User-Agent)")⚠️ 关键注意事项
-
登录接口必须真实有效:打开浏览器开发者工具(F12 → Network → Login),查看表单提交的
POST请求的URL、Headers(尤其是Content-Type)、Form Data字段名(常见有email/login/csrf_token),严格复现。 -
避免硬编码敏感信息:生产环境请使用环境变量(
os.getenv("AP_USERNAME"))或配置文件(.env+python-dotenv)管理账号密码。 -
处理反爬机制:部分网站要求
User-Agent、Referer或禁用重定向。可在session.get()中添加:headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"} response = session.get(file_url, headers=headers, allow_redirects=False) -
Token 的时效性:若 URL 中的
token=参数本身有时效(如 JWT),且你无法动态获取,则优先依赖会话登录,而非依赖 token 链接(除非 token 是长期有效的)。 -
错误排查建议:打印
login_resp.text[:500]查看返回的 HTML 是否含“登录失败”提示;用print(session.cookies.get_dict())确认 cookies 是否已写入。
? 总结
下载受保护资源的核心不是“拼 URL”,而是建立并维持一个合法的用户会话。requests.Session 是 Python 中最简洁可靠的解决方案。只要登录逻辑正确,后续所有资源请求均可复用该会话,无需重复鉴权。对于需批量下载多个报告的场景,只需将登录步骤封装为函数,再循环调用下载逻辑即可实现自动化。


















