很多站点排查抓取问题,习惯先看 robots、Sitemap 和内链,却忽略了一个前置环节:蜘蛛请求的那个 URL,最终是由谁返回内容的。如果站点前面挂了 CDN 或反向代理,蜘蛛拿到的可能不是源站当前版本,而是边缘节点上的某一份缓存副本。抓取路径没变,看到的内容却对不上,问题就会显得很“玄”。
缓存命中时,蜘蛛看到的是哪一份内容
CDN 的默认行为是尽量提高命中率,这对普通访客是好事,对蜘蛛却可能带来偏差:
- 源站刚更新了标题和价格,边缘缓存还没过期,蜘蛛抓到的仍是旧版本,内容新鲜度信号被“冻结”。
- 页面缓存了带登录态或带地区差异的版本,蜘蛛拿到的页面里出现本不属于它的内容。
- 不同节点返回的 HTML 不一致,蜘蛛在不同时间看到不同结果。
这些情况本身不会直接导致降权,但会让“抓到的内容”和“站点真实内容”之间产生漂移。判断方法很简单:用蜘蛛的 UA 从一个普通网络出口请求页面,与源站直连的输出做对比(先去掉时间戳、随机 token 之类的动态部分)。如果差异明显,优先查缓存策略,而不是先改内链。
缓存键与 URL 参数:同一页面被拆成几份
缓存键决定了“什么算同一个资源”。如果缓存键把全部查询参数都算进去,带 utm、带会话参数、带排序参数的 URL 都会各自生成一份缓存,蜘蛛顺着这些 URL 走一圈,抓到的是一堆内容相同、地址不同的页面。反过来,如果缓存键忽略了有意义的参数(比如分页的 page、筛选条件的 id),蜘蛛请求第 2 页时可能被塞回第 1 页的内容,抓取深度看起来走了,实际没走。
比较稳妥的做法是:明确哪些参数参与缓存键,哪些不参与;在缓存层把无意义参数剥离或统一跳转;确保分页、筛选这类真正改变内容的参数不被忽略。这部分配置通常由运维或前端架构决定,但内容运营需要知道它存在,否则容易误判成“蜘蛛不抓列表页”。
Vary、Cookie 与多版本页面
同一个 URL 因为有 Vary 头或 Cookie 差异,可能对应多种缓存版本。需要确认的是:
- 蜘蛛请求时通常不带 Cookie,边缘节点会把哪一份缓存给它,这一份是否就是希望被索引的版本。
- 如果 Vary 里包含 User-Agent,移动版和桌面版会分开缓存,这时要确认返回给蜘蛛的,是与页面 canonical 一致的那一份。
- 地区重定向、语言切换如果在缓存层完成,要确认蜘蛛不会被反复送到某个临时的默认版本。
缓存层是最容易把“一个页面”变成“多个页面”的地方,也是最容易把“多个页面”压成“一个页面”的地方,两头都会影响蜘蛛对站点的理解。
别把错误状态一起缓存
源站偶尔出现的 5xx、502、超时页,如果被边缘缓存按默认 TTL 存下来,蜘蛛在接下来的一段时间里会持续拿到错误响应。它看到的不是一个偶发抖动,而是一个持续不可用的地址,回访节奏自然会调整。建议在缓存规则里明确:4xx、5xx 不缓存,或只做极短时间的缓存;同时留意源站的超时页是否被当成 200 返回。
缓存头与蜘蛛的回访
Cache-Control、Expires、ETag、Last-Modified 这些头,不只是给浏览器看的,蜘蛛在决定是否重新拉取内容时也会参考。如果边缘节点把源站的 ETag 抹掉或重新生成,条件请求就可能失效,每次回访都要拉完整内容;如果 TTL 被设得极长,蜘蛛可能长时间看不到更新后的页面。合理的方向是让缓存头真实反映内容更新节奏:详情页和列表页区分开,不要用“一周不变”这种一刀切策略。
怎么验证蜘蛛拿到的是源站内容
不需要复杂工具,按下面的顺序排查基本够用:
- 用与蜘蛛相同的 UA 请求目标 URL,保存响应头和正文。
- 绕过 CDN,直接请求源站上的同一路径,做对比。
- 检查响应头里的缓存命中标识(如 X-Cache、Age、CF-Cache-Status 之类,不同厂商命名不同)。
- 如果命中缓存,看该 URL 的 TTL 与实际内容更新时间是否匹配。
- 对比访问日志中“源站收到的请求”与“边缘收到的请求”,确认蜘蛛的请求有没有真正到达源站。
如果发现蜘蛛长期只命中缓存、几乎不回源,说明缓存策略对抓取过于“友好”,把更新信号挡在了外面,这时需要单独为搜索引擎的 UA 配置回源或更短的 TTL。把“蜘蛛看到什么”先确认清楚,再谈抓取频率和发现效率,判断会准确得多。
写在最后
抓取问题不总是出在链接结构上。CDN 和缓存层处在蜘蛛与源站之间,决定了蜘蛛实际上看到了什么。把这一层核对清楚,再去调整 Sitemap、内链和更新信号,才不会把时间花在错误的方向上。