结论:Cookie 和 Session 决定爬虫能不能拿到"登录后"的数据,也决定你的抓取行为会不会被精确记账到某个账号上。不带 Cookie 抓的是游客视图,带上 Cookie 就变成有状态会话——服务端能通过 sessionid 追踪你的每一次请求,风控一旦触发,封的不是 IP 而是账号。
Cookie 和 Session 有什么区别?
结论:Cookie 是存在客户端的凭证字符串,Session 是存在服务端的会话数据,两者靠 Cookie 里的 sessionid 绑定。
Cookie 是服务端通过 Set-Cookie 响应头下发、客户端在后续请求的 Cookie 请求头里回传的键值对,浏览器和爬虫都存本地,带 expires 或 Max-Age 控制有效期,带 HttpOnly 的 Cookie 是 JS 读不到的,带 Secure 的只在 HTTPS 下发送。Session 是服务端内存或 Redis 里的一份状态,客户端只拿到一个形如 sessionid=abc123 的随机串作为钥匙。
区别在于:Cookie 你能随便改,Session 你改不了。爬虫真正要复用的是那个 sessionid,而不是整个 Cookie 串。
不带 Cookie 抓取会怎样?
结论:不带 Cookie 只能抓到公开页面,但凡需要登录的接口都会返回 302 跳登录页、401 或 403。
具体表现是:请求 HTML 页面时,requests.get(url) 不加任何 Cookie 拿到的是登录页内容而不是目标页;请求 API 时返回 {"code":401,"msg":"请先登录"} 这类 JSON。判断方法很直接——看响应状态码是不是 302 且 Location 指向 /login,或者看返回内容里有没有"登录"字样。
好处是匿名请求不绑定任何账号,被限流最多封 IP,换代理就恢复。所以能匿名抓的绝不登录,这是第一原则。
带上 Cookie 抓取有什么好处和风险?
结论:好处是能访问登录后数据、保持个性化状态;风险是抓取行为直接记在账号头上,且 Session 过期后请求会静默失效。
用 requests.Session() 时,会话对象会自动保存响应里的 Set-Cookie 并在后续请求中带上,这是维护登录态最省事的方式:
s = requests.Session()
s.post(login_url, data={"user": "xxx", "pwd": "yyy"})
r = s.get(target_url) # 自动带 Cookie
风险集中在三点:一是同一 sessionid 的并发和频率被服务端完整统计,1 秒内发 10 次请求基本会触发验证码或滑块;二是 Cookie 与 IP、User-Agent 不一致时会话会被判定为异常,所以换代理时必须同步换 Cookie;三是 sessionid 通常几小时到几天过期,过期后服务端不报错,直接把你当游客,返回登录页,程序如果不校验就会一直把登录页当数据存下来。
爬虫该怎么正确处理 Cookie 和 Session?
结论:匿名优先、登录用小号、Cookie 与出口 IP 和 UA 严格绑定一致、每次响应校验登录态。
步骤写清楚:
- 能用公开接口就不登录,减少账号暴露面。
- 必须登录时用专用小号,不要用主账号,登录后立即导出 Cookie 或 sessionid 复用,避免反复登录(反复登录本身就是风控特征)。
- 用
requests.Session() 或 httpx.Client() 保持会话,把 UA、Cookie、代理三者绑定成一组,一个账号固定一个出口 IP。
- 控制频率:同一 sessionid 的请求间隔保持 1-3 秒,并发数压到 1-2 条。
- 每次请求后检查响应:状态码 302 且 Location 含 login、或响应体出现登录页特征,就判定会话失效,停止并重新获取。
- 多账号场景做轮换,每个账号独立 Session 对象,别共用 CookieJar。
注意点:带 HttpOnly 的 Cookie 无法用 JS 注入,只能从抓包或登录接口响应头里取;SameSite=Strict 的 Cookie 跨站请求不会发送,做接口调用时要注意请求来源。
总结
Cookie 是钥匙,Session 是门后的房间。爬虫不带 Cookie 就是游客,受限但安全;带上 Cookie 就进了登录态,能拿到数据也把自己交了出去。实操上坚持匿名优先、登录小号、Cookie 与 IP/UA 绑定、控频 1-3 秒、每次校验登录态这五条,就能在拿到数据的同时把封号风险压到最低。