结论先说:如果两个 URL 返回的正文完全一致,但响应头不同,那么它们是否被当成同一个页面、是否允许被抓取、是否值得保留,都不能只靠正文比对来下结论。响应头里的 X-Robots-Tag、Content-Type、Link、Vary 以及状态码,会分别影响抓取、解析、规范化与缓存判断。只有当这些头信息一致、或差异被明确解释时,才能把“内容相同”当成合并或保留的依据。
正文相同只是肉眼可见的部分。抓取工具先读状态行和响应头,再决定要不要读正文、按什么类型解析、是否把当前 URL 视为另一资源的变体。可以按下面三类归位:
X-Robots-Tag 出现 noindex、nofollow 或 none 时,即使正文与另一个可索引页面一模一样,这个响应也不能按“内容相同所以同样处理”来推断。它表达的是对当前响应的处理要求,不是对正文的重复判断。Content-Type 的字符集、Content-Language、Vary 会影响解析结果和缓存键。两个 URL 正文一致,但一个声明为 text/html; charset=utf-8,另一个声明了不同字符集或语言,解析出的文本可能并不相同。Link 里的 canonical、alternate、hreflang,以及 200、301、304、410 等状态,会改变“这个响应代表哪个资源”的判断。正文相同但状态不同,通常意味着它们在资源层面不是同一件事。把差异归到哪一层,直接决定下一步是查规则、查模板,还是查缓存与 CDN 配置。
同一份正文配不同响应头,最容易在四个判断上产生分歧:
X-Robots-Tag 决定的是抓取之后能否索引。两者作用点不同。若 A 响应带 noindex、B 响应不带,就不能因为正文相同而认为两者索引结果相同。Vary 不同会让中间缓存按不同维度存储同一 URL 的响应。此时“内容相同”可能只是当前请求下的巧合,换个请求头就未必相同。如果两个响应头不同,但差异只来自边缘节点或测试环境的临时配置,而源站输出本身一致,那么“响应头不同会影响判断”这个结论在源站层面并不成立。例如假设同一套模板在预发环境被注入了 X-Robots-Tag: noindex,生产环境没有;此时正文相同、响应头不同,真正要核对的是环境配置是否被误同步,而不是页面是否重复。
反过来,若差异稳定复现在所有节点、所有请求上,才适合把它当成资源本身的属性来处理。判断差异是否稳定,比争论“内容到底算不算相同”更有用。
多个角色对同一事实理解不同时,先不要争论结论,先固定核对项。建议按同一 URL、同一请求头、同一时间点抓取,记录以下字段:
Content-Type 及其字符集;X-Robots-Tag 的完整值;Link 中的 canonical、alternate、hreflang;Vary 与缓存相关头;一个实际动作是:对两个 URL 各抓两次,一次带普通请求头,一次带常见爬虫请求头,比较响应头是否随请求头变化。若变化,说明存在内容协商或缓存分片,下一步应查 Vary 和 CDN 规则;若不变,说明差异来自源站输出,下一步应查模板、路由或发布流程。这个动作的结果会直接决定排查方向,而不是停留在“内容一样为什么表现不一样”的争论上。
需要提醒的是,robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录;不同搜索引擎对响应头的支持情况需要分别核查。把响应头差异记录清楚,再决定改哪里,比先下结论更稳妥。