搜索抓取

Cookie、地域跳转与 A/B 测试:蜘蛛拿到的那一版页面里还有链接吗

同一个 URL 在服务端可能返回多个版本:带 Cookie 的、按地域跳转的、按 UA 分流的、参与 A/B 测试的。蜘蛛抓到哪一版,直接决定它能不能顺着内链继续发现 URL。本文梳理常见的版本分流方式、缓存层造成的影响,以及可以落地的排查与治理动作。

搜索抓取

Cookie、地域跳转与 A/B 测试:蜘蛛拿到的那一版页面里还有链接吗

蜘蛛抓取时拿到的,是服务器在那一瞬间返回的响应。这条响应可能已经被 Cookie、地域判断、设备识别或 A/B 测试改写过。一旦改写后的版本里少了导航、少了列表链接,抓取路径就会随之变窄,URL 发现也会跟着慢下来。

为什么同一个 URL 会返回不同内容

分流本身不是错误,很多站点确实需要它。问题在于分流经常在爬虫不知情的情况下发生,而且是按“有没有带 Cookie”“请求从哪个区域进来”这类蜘蛛不具备的条件来判断。

  • Cookie 与同意弹窗:首次访问返回一个带遮罩层的版本,用户点过之后才写入 Cookie。蜘蛛没有这个 Cookie,每次拿到的都是遮罩版,若遮罩把首屏链接一起挡在客户端渲染之外,内链就等于不存在。
  • 地域与语言跳转:按 IP 或 Accept-Language 跳到某个语言站。蜘蛛的出口 IP 与用户分布不同,可能被反复送到同一个版本,其他语言站的 URL 就长期缺少入口。
  • User-Agent 分流:给移动端和桌面端返回不同的 HTML 骨架。如果其中一版的导航依赖脚本后置注入,蜘蛛从中拿不到可跟随的链接。
  • A/B 测试与灰度:随机把访问者分到实验组。蜘蛛每次抓到的可能都是不同分支,链接结构不稳定,抓取结果也就不稳定。
  • 登录或会员门槛:未登录状态只给一个极简首页,站内大部分 URL 没有对外暴露的路径。

这些分流怎样影响 URL 发现

URL 发现依赖可见的、可跟随的链接。当蜘蛛拿到的版本是一份“瘦身版”,它并不是抓取失败,而是把这份瘦身版当成了页面的真实样子:里面有多少链接,就顺着多少链接往下走。结果是站点里有内容的页面长期没人访问,日志里只看到首页反复被请求。

判断标准很朴素:在不带 Cookie、不模拟登录、不设置特殊 UA 的情况下请求一次,看看返回的 HTML 里能不能找到通向主要栏目的链接。找不到,就是发现路径被切断了。

缓存层会把问题放大

CDN 和反向代理按缓存键决定返回哪一份内容。如果缓存键里包含 Cookie,同一 URL 会被拆成很多份副本,命中率下降,回源增多;如果响应带上了 Vary: Cookie 或 Vary: User-Agent,缓存会把不同请求者当成不同对象,蜘蛛抓到的那一份可能恰好是某个边缘节点上残留的实验版本。反过来,如果缓存键过于简单,先被缓存的实验版或遮罩版又会被分发给后续所有请求者,包括蜘蛛。

排查与治理的常规做法

  1. 用全新会话、不带任何 Cookie 的请求抓一次首页和几个栏目页,检查返回 HTML 中的链接数量。
  2. 分别用桌面与移动 UA 请求同一 URL,比对可跟随链接的差异。
  3. 检查响应头里的 Vary、Cache-Control 与缓存键设置,确认蜘蛛与普通用户是否可能落到不同副本。
  4. 把导航、面包屑、主要列表这类关键链接做成服务端直出的静态 HTML,不依赖脚本后置注入。
  5. 确认弹窗、跳转、同意层不会阻断链接的抓取路径,必要时对爬虫请求返回不含遮罩的基础版本。
  6. 如果确实需要多语言或多地域版本,确保每个版本都有稳定、独立的 URL,并互相之间有可跟随的链接。

把版本差异控制在无害范围内

理想状态不是消灭所有分流,而是让分流只影响样式、推荐位这类非关键内容。左侧导航、页脚、面包屑、分页链接这些承载发现功能的元素,最好在任何版本里都保持一致,并且是服务端就能输出的。这样即便蜘蛛抓到的是实验分支、地域版本或未登录版本,它依然能顺着同一套链接继续走,URL 发现的节奏不会被局部改动打乱。

做这类检查不需要复杂工具,一份不带 Cookie 的响应加上一次日志比对,通常就能看出问题出在哪一层。