做蜘蛛池入口页时,很多人把注意力放在 URL 结构、内链和响应时间上,却忽略了一个很小的变量:Cookie 和会话状态。它平时不显眼,但一旦入口页依赖会话才能输出内容,蜘蛛拿到的页面可能和一个普通访客完全不是同一个。
蜘蛛的请求通常是无状态的
搜索引擎蜘蛛发起请求时,一般不会像浏览器那样保存并回传上一次的 Cookie,多数情况下每次抓取都是一次全新的、不带 Cookie 的请求。这意味着,任何“必须先有 Cookie 才给内容”的逻辑,都可能把蜘蛛挡在门外,或者让它只看到一个空壳页面。
常见的依赖会话的场景包括:
- 首次访问就强制跳转到带 jsessionid、PHPSESSID 之类参数的地址;
- 用 Cookie 记录“已同意隐私条款”之后才展示正文;
- 用 Cookie 做 A/B 分流,蜘蛛每次被分到不同版本;
- 用 Cookie 判断来源地区、语言或渠道,再决定返回什么内容。
三种最容易踩的坑
一、会话参数写进 URL
当服务端用 URL 重写把会话 ID 写进地址,蜘蛛抓到的链接就会带着一长串会话参数。这类地址对每个新会话都可能不同,容易造成同一内容被反复发现、重复抓取,也会稀释入口页本身的权重。建议在入口页关闭 URL 重写,实在关不掉,就用 canonical 做归一。
二、同意墙挡在正文前面
Cookie 同意弹窗如果实现成“内容必须由 JavaScript 在用户确认后才渲染”,蜘蛛往往只能看到提示文字。更稳妥的做法是把正文直接放在 HTML 里,弹窗只做视觉遮挡;确需交互时,也让未携带 Cookie 的首次请求返回完整内容。
三、缓存被会话状态废掉
一旦响应头里出现 Cache-Control: private,或者页面因为 Set-Cookie 而被 CDN 判定为个性化内容,边缘缓存的命中率就会下降。对蜘蛛来说抓取成本没变,但你服务器承受的并发会明显上升,响应时间也更容易抖动。
Set-Cookie 本身要不要紧
单纯返回 Set-Cookie 头,一般不会直接导致抓取失败,蜘蛛通常会忽略它。真正的问题在于这个 Cookie 是否反过来决定了后面的响应:如果入口页对每个无 Cookie 请求都返回相同内容,影响不大;如果无 Cookie 就跳转、就空白、就返回 403,那就属于典型的“抓取通道被会话逻辑掐断”。
判断标准很简单:用不带 Cookie 的请求访问一次入口页,看看拿到的 HTML 和你自己在浏览器里看到的是不是同一份。
落地时的几条建议
- 入口页保持无状态:正文、标题、内链都不依赖任何会话变量。
- 把识别判断放在 UA 与 IP 上:需要区分蜘蛛时,优先用反向解析验证过的来源 IP,而不是靠 Cookie。
- 会话参数不进链接:避免把会话 ID 写进 href;历史上已产生的,做跳转或 canonical 归一。
- 分流留一份默认版本:A/B 测试对蜘蛛固定返回主版本,避免同一入口页反复改内容。
- 把缓存策略写清楚:入口页尽量走公共缓存,减少动态逻辑带来的响应波动。
怎么验证有没有问题
三个低成本动作就够用:一是用命令行工具或抓取工具发起不带 Cookie 的请求,对比返回内容;二是看响应头里的 Set-Cookie、Cache-Control、Vary 字段是否出现在入口页上,尤其留意 Vary: Cookie;三是在服务器日志里筛出蜘蛛请求,看状态码分布是否和预期一致,有没有大量跳转或 403。
会话状态属于那种“平时不出声、出事就成片”的配置。把入口页做成无状态可读的页面,往往比事后排查抓取异常省事得多。