先给结论:不要用同一台设备、同一个账号交替切换去“对照”,那样拿到的差异无法归因。正确做法是把“设备/UA”和“登录状态”拆成两个独立变量,用两组互不干扰的请求分别固定其中一个变量,再逐层比对返回内容、状态码和可索引信号。只有当两组结果都指向同一处内容差异时,才能确认是服务端按条件返回了不同版本,而不是缓存或前端渲染造成的假象。
同一地址出现不同内容,常见来源有三类:服务端按 User-Agent 或 Cookie 返回不同 HTML;CDN 或反向代理按设备缓存了不同副本;前端脚本在拿到同一份 HTML 后按登录态改写 DOM。这三类的处理方式完全不同,所以第一步是排除客户端改写。
最直接的动作是关闭 JavaScript 后再取一次内容。如果关闭脚本后两个条件的返回完全一致,差异就发生在浏览器渲染阶段,属于前端逻辑,不涉及服务端分流;如果关闭脚本后差异依然存在,说明分歧在传输层之前就已产生,需要继续往服务端和缓存查。
这一步的结果会决定后续方向:前端改写要改渲染与预渲染策略,服务端分流要改返回逻辑或缓存键。方向判断错了,后面所有对照都是白做。
把变量拆开,有两种成立条件不同的做法,按你的实际条件选一种。
适用条件是你怀疑服务端按 UA 或设备类型分流。做法是全程使用未登录的干净会话,只替换请求头里的 User-Agent,分别模拟桌面与移动端,其余头部保持一致。
动作与判读:用 curl 或等效工具发起两次请求,保存完整响应体与响应头。比较三样东西——正文可见文本、Link 里的 canonical 指向、以及返回的状态码。如果移动端返回的 canonical 指向另一个地址,或正文主体不同,就说明服务端在做设备分流,索引优化要处理的是让两个版本互相声明关系,而不是强行统一内容。
适用条件是你怀疑内容按登录态区分,比如登录后出现额外区块或整页替换。做法是保持同一 UA,先用无 Cookie 会话请求一次,再带上有效登录 Cookie 请求一次。
动作与判读:重点看未登录版本是否包含登录后才出现的正文。如果核心内容只在登录态可见,而未登录版本是空壳或提示页,那么被索引的将是那个空壳。此时要决定的是:把核心内容放到未登录也可见的版本,还是让登录页明确返回不可索引信号。这个取舍取决于内容本身是否需要对未登录访客展示。
只对比“看起来不一样”没有说服力,要留下可复查的证据。每次请求至少记录以下内容:
Vary其中 Vary 是关键线索:如果它声明按 User-Agent 或 Cookie 变化,说明缓存层已经预期不同条件返回不同内容,你的对照结果必须按这个维度分组,否则会把缓存副本误判成服务端逻辑。记录完这些字段后,若两组结果的差异集中在正文而状态码与 canonical 一致,问题更可能出在渲染或缓存;若 canonical 或状态码本身就不同,则属于服务端分流。
有些差异看起来像分流,其实另有原因,需要排除后再下结论。
另外要提醒:robots.txt 的抓取限制不等于可靠的索引移除,即便你屏蔽了某个条件版本,它仍可能以其他方式出现在结果中;站点地图也不保证收录。因此对照的目的不是靠屏蔽掩盖差异,而是先弄清差异的真实来源,再决定是统一内容、声明版本关系,还是对不该索引的版本单独处理。
对照完成后,判断依据落在“差异是否稳定复现”上。若同一条件下重复请求结果稳定,且差异与设备或登录状态一一对应,就可以确认是条件分流,接下来处理版本声明与索引目标;若同一条件下结果自身就在变化,应先解决缓存一致性,再谈索引优化,否则任何声明都会被不稳定的返回覆盖。把这一步做实,后面的改动才有可验证的基准。