先查 Content-Type 和内容编码,再查缓存与语言变体头。页面正文相同,不代表抓取端看到的是同一个文档:响应头会改变解析方式、字符集判断和缓存键,从而让一部分 URL 进入“可抓取但不适合索引”的状态。下面用一个明确假设的情境,把判断顺序和取舍写清楚。
假设某站有一篇产品说明,分别通过 /p/123 和 /product/123 返回完全相同的 HTML 正文。两个地址都能打开,页面标题、正文、内链一致,但服务器返回的响应头不同:前者是 Content-Type: text/html; charset=utf-8,后者是 Content-Type: text/html,并且后者多了一个 Vary: User-Agent。此时仅凭“正文相同”无法判断哪个地址会被当作规范对象,也无法判断抓取端是否把两者视为同一文档。
这个情境的关键不是正文,而是响应头是否让抓取端对文档类型、字符集、缓存版本产生不同理解。若只检查页面可见内容,就会漏掉这一层。
Content-Type 决定抓取端按 HTML 还是按纯文本、XML 等方式解析。缺少 charset 时,解析器会转向 meta 标签或自动探测;若探测结果与页面实际编码不一致,正文中的中文、符号或结构化数据可能被读成乱码。乱码不一定导致抓取失败,却会让“正文是否相同”的判断失真。
可执行动作:用抓取工具分别保存两个 URL 的响应头和原始响应体,比较 Content-Type 是否一致,以及解码后的正文是否仍然相同。若解码后不同,下一步应修正字符集声明,而不是先提交收录。
Vary、Cache-Control、ETag 会影响中间缓存和抓取端拿到的是哪个版本。假设 /product/123 带 Vary: User-Agent,而 /p/123 不带,那么同一地址对不同抓取端可能返回不同内容。此时“正文相同”只对某一次请求成立,不能推广为稳定结论。
可执行动作:固定同一 User-Agent 和同一 Accept-Encoding,分别请求两个地址,记录响应头和响应体哈希。若哈希随请求头变化,说明存在变体;下一步应确认是否必须保留该变体,还是让两个地址返回同一份可缓存文档。
当响应头导致解析结果不同,页面内的 rel=canonical、站点地图中的地址和实际返回文档可能互相矛盾。站点地图不保证收录,robots.txt 的抓取限制也不等于可靠的索引移除;这两点在此处只用于提醒:不要用“已提交站点地图”或“已屏蔽抓取”来替代对响应头一致性的检查。
可执行动作:列出两个 URL 的 canonical 指向、站点地图收录状态和响应头差异。若 canonical 指向的地址恰好是响应头异常的那个,下一步应先统一响应头,再观察抓取与索引状态是否变化。
Content-Type 与字符集声明,确保解码后的正文一致。Vary 与缓存头,确认同一 URL 不会因请求头返回不同文档。这个顺序的理由是:解析层不一致会让后续所有比较失去意义;缓存层不一致会让“相同内容”这个前提不成立;规范层不一致则是在前两者稳定后才值得处理的取舍。
请求量、抓取量或某个统计归零,不能单独证明响应头已修好。它们还可能受抓取预算调整、站点整体改版、外部链接变化或统计口径影响。更可靠的证据是:同一次请求下,两个 URL 的响应头字段一致、解码后正文哈希一致、canonical 指向明确,并且连续多次请求结果稳定。
若只能看到一个地址被处理而另一个仍异常,不要把“其中一个恢复”当作整体恢复。应回到假设情境中的比较方法,逐项确认差异是否真正消除,再决定是否继续调整内链或提交收录。