requests.session() 会丢嵌套 cookie,因其默认 cookiejar 对 domain、path、secure 等属性校验严格,跨域重定向、iframe 多域名或 samesite=none/secure 组合等场景下,部分 set-cookie 被静默忽略;需改用 lwpcookiejar、手动 set cookie 或分域维护 session 实例。

为什么直接用 requests.Session() 会丢掉嵌套 Cookie?
因为 requests 默认的 CookieJar 实现(DefaultCookiePolicy)对 Domain、Path 和 Secure 属性校验严格,而多层嵌套场景(比如主站 set-cookie 后,子路径 JS 再发一次重定向 + set-cookie,或 iframe 域名跨域带 cookie)常导致部分 cookie 被 silently 忽略——你调用 session.cookies 看着有值,但实际发请求时没带上。
典型表现:401 或 302 循环,抓取登录后页面返回首页;用浏览器开发者工具能看到多个 Set-Cookie 头,但 session.cookies 里只存了第一个。
- 检查是否触发了 domain 匹配失败:比如响应头是
Set-Cookie: a=1; Domain=.example.com,但你请求的是sub.example.com,而 session 当前 host 是api.example.com,默认策略可能拒收 - 注意
Path精确匹配:若后端设了Path=/auth/callback,那这个 cookie 只会在该 path 下发送,不会透传到/api/user -
requests不自动处理SameSite=None; Secure组合在 HTTP 环境下的兼容降级,容易漏掉
用 http.cookiejar.LWPCookieJar 替代默认 jar 并手动加载/保存
它比默认 CookieJar 更宽松,支持显式导入导出,也允许你干预 cookie 存储逻辑。关键不是“换 jar”,而是绕过 requests 的自动注入链,自己控制何时塞 cookie。
实操建议:
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 初始化时指定 jar:
session.cookies = http.cookiejar.LWPCookieJar() - 若需从文件恢复历史状态(比如断点续爬),用
session.cookies.load('cookies.txt', ignore_expires=True),ignore_expires很重要——否则过期 cookie 直接被过滤 - 手动添加 cookie(绕过 domain/path 校验):
session.cookies.set('name', 'value', domain='example.com', path='/', secure=True),注意domain前不能加点(.example.com是错误写法,应写example.com) - 调试时打印所有 cookie:
list(session.cookies),别只看dict(session.cookies),后者会按 domain+path 合并同名 key
遇到多域名嵌套(如主站 + CDN + OAuth 回调域)怎么办?
requests 的单个 Session 只有一个 cookie jar,无法原生支持跨域共享 cookie。常见于 OAuth 流程:你跳转到 login.thirdparty.com,它 set-cookie 后再 redirect 回你自己的 callback.yoursite.com,此时 cookie 已丢失。
解决思路不是“让 requests 支持多域 jar”,而是分治:
- 对每个独立域名维护一个
Session实例,各自管理自己的CookieJar,比如main_session、oauth_session、cdn_session - 需要传递身份时,手动提取关键 cookie(如
session_id)并用headers={'Cookie': 'session_id=xxx'}显式带上——绕过 jar 的自动逻辑 - 若必须模拟浏览器完整行为(比如 SSO),改用
selenium或playwright,它们天然维护全局 cookie 上下文,但性能和资源开销大得多 - 警惕
requests的allow_redirects=True:它会在重定向时自动携带当前 jar 的 cookie,但仅限同域;跨域重定向后 cookie 就断了,此时应设allow_redirects=False,自己处理 302 Location 和后续请求
如何验证 cookie 是否真正生效?
不要只信 print(session.cookies),它只显示 jar 里的内容,不等于实际发出的请求头。最可靠的方式是抓包对比。
- 用
mitmproxy或Charles拦截 requests 发出的原始 HTTP 请求,看Cookie:头里有没有你预期的键值对 - 临时 patch
requests.adapters.HTTPAdapter.send,在发送前打印request.headers.get('Cookie') - 服务端返回的
Set-Cookie若含HttpOnly,你无法通过 JS 获取,但 requests 仍能接收并存储——这点常被误认为“没拿到” - 如果用了代理(比如公司内网),确认代理没 strip 掉
Cookie头,有些透明代理会过滤敏感 header
多层嵌套 cookie 的本质是状态同步问题,而不是存储格式问题。真正难的从来不是“怎么存”,而是“什么时候该存、从哪来、往哪发”。手动控制比依赖自动逻辑更可控,也更容易定位漏点。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










