站点cookie抓取
打开浏览器开发者工具,站点抓切到Application面板,站点抓左侧Cookies列表里躺着二三十条键值对。站点抓很多人以为这就是站点抓站点全部的cookie了,其实差得远。站点抓HTTP响应头里的站点抓Set-Cookie只是冰山一角,JS在运行时还能往document.cookie里塞东西,站点抓Service Worker有独立的站点抓CookieStore API,甚至有些站点把关键凭证藏在IndexedDB里伪装成"cookie"。站点抓我见过一个电商站,站点抓登录态token压根不在cookie列表里,站点抓而是站点抓被塞进了sessionStorage,名字还起得跟普通配置项似的站点抓。 抓cookie最直接的站点抓办法是看请求头。打开Network,站点抓随便点一个XHR请求,Request Headers里那行Cookie就是浏览器实际发出去的全部内容。这比在Application面板里翻列表靠谱,因为面板显示的是当前域下的cookie,而请求可能跨域携带了别的域的数据。有一次我调试一个支付回调,面板里死活找不到某个关键字段,结果在请求头里发现了——它来自一个iframe里的第三方域,面板默认只显示当前上下文。 但请求头只反映"发出去什么",不反映"怎么来的"。要追踪cookie的写入源头,得用Chrome的Cookie变更断点。Sources面板右侧有个Cookie Breakpoints,输入cookie名,任何JS对这个cookie的读写都会暂停。我靠这招抓到过一个反爬逻辑:页面加载后先写一个空cookie,等某个异步请求返回后再用JS覆盖成真实值,中间间隔不到200毫秒。用普通抓包工具根本看不出这个覆盖动作。 Python里用requests抓cookie,很多人直接拿response.cookies了事。这玩意只解析Set-Cookie头,JS写的那部分完全拿不到。要拿全量,得配合Selenium或者Playwright,等页面稳定后执行driver.get_cookies()。但这里有个坑:get_cookies()返回的是当前域的cookie,如果页面里有iframe,还得切到对应的frame再取一次。我写过一个脚本抓某社交平台的cookie,主域下只有基础标识,真正的鉴权cookie在passport子域里,得先driver.switch_to.frame()再操作。 cookie的SameSite属性这两年越来越严。Chrome默认把没有显式声明SameSite的cookie当成Lax处理,这意味着跨站POST请求不会带上cookie。抓取的时候如果发现某个接口在浏览器里正常,用脚本跑就401,先检查cookie的SameSite值。我遇到过最离谱的情况:站点在Set-Cookie里写了SameSite=None但没加Secure,Chrome直接拒绝写入,控制台报了个黄字警告,不仔细看根本注意不到。 HttpOnly是个硬门槛。标记了HttpOnly的cookie,JS的document.cookie读不到,只能通过HTTP请求携带。抓这种cookie要么用抓包工具看请求头,要么用CDP协议监听Network.responseReceived事件。Playwright的context.cookies()能拿到HttpOnly的cookie,因为它走的是浏览器底层接口,不受JS限制。但如果你用pyppeteer或者老版本puppeteer,某些情况下拿不到,得升级到支持CDP全量cookie导出的版本。 最后说个实际案例。某招聘网站的反爬会动态生成一个叫__zp_stoken__的cookie,值是一段加密字符串,有效期只有几分钟。它由页面里一个混淆过的JS函数生成,函数依赖window.performance.now()和几个随机数。硬逆向太费劲,我直接用Playwright挂了个hook,在document.cookie的setter上打日志,等它自己写进去再读出来。跑了一周,稳定拿到有效cookie。这种场景下,抓cookie的本质不是"读",而是"等它自己写"。