结论先行:当两个地址返回的可见内容完全一致,而响应头不同,最值得怀疑的不是“内容是否重复”,而是你正在把状态码、缓存策略、内容类型和规范化信号混在一起判断,导致死链修复的结论失真。只有当两处响应头的差异确实指向同一资源的不同处理方式时,才应把它们当作同一问题处理;否则,先分开记录,再决定是否修复。
死链修复通常先看返回状态。假设一个地址返回 200 OK,另一个返回 301 Moved Permanently 或 410 Gone,即使页面正文看起来一样,也不能直接认定两者都是“正常页面”。如果修复动作是把旧地址批量改成新地址,而旧地址本来返回 301,改完之后可能把原本可传递的跳转信号切断了。更稳妥的动作是:先按状态码分组,把 200、301、302、404、410 各自列开,再分别决定是保留、替换还是移除链接。这个动作的结果会直接影响下一步——如果状态码分组后仍有一组地址内容相同但状态不同,才需要继续查响应头里的其他字段。
两个地址正文一致,但一个带 Cache-Control: no-store,另一个带 Cache-Control: max-age=3600,说明它们面向的读取路径可能不同。此时若你只凭浏览器里看到的页面做判断,可能把缓存版本当成当前版本。另一个常见差异是 Content-Type:一个返回 text/html,另一个返回 text/html; charset=gbk 或 application/xhtml+xml,正文肉眼近似,但解析和后续处理并不完全一样。实际动作是:用同一个请求工具分别记录完整响应头,不要只截图页面。记录之后,如果发现差异集中在缓存或字符集,修复重点应放在统一响应策略,而不是继续删链接或改正文。
页面内容相同、响应头不同,还可能表现为一个地址带 Link: <https://example.com/a>; rel="canonical",另一个不带或指向自己。这种情况下,两个地址在“谁是主版本”上给出不同答案。对死链修复来说,如果旧地址本应退出,却仍返回 200 并声明自己为规范版本,那么把它简单替换成新地址,可能只是把冲突从一个位置搬到另一个位置。此时的动作是:先确认每个地址的 canonical 指向是否一致,再决定是保留一个主地址,还是让旧地址明确跳转。若 canonical 指向不一致,不要仅凭正文相同就合并处理。
反例成立的条件是:两个地址内容相同,响应头差异只来自不同 CDN 节点、不同语言协商或不同设备类型,而它们本来就服务于不同访问路径。例如同一篇文章在桌面端和移动端返回相同正文,但 Vary 头不同,或一个节点返回 200,另一个节点因缓存未命中返回 304。这类差异不说明链接失效,也不说明需要修复死链。若把它们当成死链处理,可能误删仍然有效的入口。判断边界是:差异是否与“该地址是否还能作为有效入口”有关。若无关,就只记录,不进入死链修复队列。
可以按下面顺序执行,动作和结果都影响下一步:
Location、Content-Type、Cache-Control、Link 五个字段做对照。这样做的结果是:你不会因为“页面看起来一样”而把不同响应头当成同一类问题。下一步再决定是改链接、改跳转,还是只调整响应策略,判断依据会更清楚。