爬虫登录之后为什么后面的请求会自动带 cookie?手写 Cookie 头为什么没用?多个账号要怎么隔离?这篇用一个会发 Set-Cookie 的服务器,把 CookiesMiddleware 的行为一项项量出来。
COOKIES_ENABLED=1(默认):/login?u=alice 带 Cookie=(无);/other 带 Cookie=sid=alice;/me 带 Cookie=sid=alice COOKIES_ENABLED=0:/login?u=alice 带 Cookie=(无);/other 带 Cookie=(无);/me 带 Cookie=(无)
process_response 把 Set-Cookie 存进 cookie jar,process_request 按域名/路径等规则给请求加上 Cookie 头。
/c → 服务器收到 Cookie: via=cookies-param /h → 服务器收到 Cookie: (无) /later → 服务器收到 Cookie: via=cookies-param COOKIES_ENABLED=0:/c → (无);/h → via=header;/later → (无)
中间件在发送前会先删掉请求上已有的 Cookie 头再重建,所以要通过 Request(cookies=…) 设置,并且这些 cookie 会存进 jar,影响之后的请求。
/follow?jar=alice → Cookie: (无) /follow?jar=bob → Cookie: (无) /forgot?jar=alice → Cookie: (无) /forgot?jar=bob → Cookie: (无) /login?u=alice → Cookie: (无) /login?u=bob → Cookie: (无) /me?jar=alice → Cookie: sid=alice /me?jar=bob → Cookie: sid=bob
meta["cookiejar"] 的值是 jar 的键,不同键互不干扰;但 meta 不会自动继承,链路上的每个请求都要继续传。
Path=/admin Set-Cookie: a=1; Path=/admin → /admin/x 带 a=1;/public/x 带 (无) Secure(http 协议) Set-Cookie: a=1; Path=/; Secure → /x 带 (无) Domain=localhost(请求在 127.0.0.1) Set-Cookie: a=1; Path=/; Domain=localhost → /x 带 (无) Max-Age=1:立即请求一次,等 2 秒再请求一次 Set-Cookie: a=1; Path=/; Max-Age=1 → /x 带 a=1;/x 带 (无) Max-Age=0(删除) Set-Cookie: a=1; Path=/; Max-Age=0 → /x 带 (无) HttpOnly + SameSite=Lax Set-Cookie: a=1; Path=/; HttpOnly; SameSite=Lax→ /x 带 a=1
标准 cookie 规则:Path 限定路径、Secure 只在 https 发送、Domain 不匹配被拒绝、Max-Age 到期删除。
Received cookies from: <200 http://127.0.0.1:9960/login?u=alice>
Set-Cookie: sid=alice; Path=/
Sending cookies to: <GET http://127.0.0.1:9960/other>
Cookie: sid=alice
Sending cookies to: <GET http://127.0.0.1:9960/me>
Cookie: sid=aliceCOOKIES_DEBUG 打印每个收到的 Set-Cookie 和发出的 Cookie。
/login?u=carol → Cookie: (无) /me1 → Cookie: (无) /login?u=dave → Cookie: (无) /me3 → Cookie: sid=dave /me4 → Cookie: (无)
dont_merge_cookies 让一个请求不参与 cookie 机制:既不发也不存。