先看结论:静态响应和脚本渲染结果不一致,通常不是“死链查询工具坏了”,而是两类结果看的根本不是同一个页面状态。定位方法不是反复换工具,而是先固定一个可复现的 URL,分别记录原始 HTML、渲染后 DOM、以及两者各自发出的网络请求,再判断差异来自服务端、脚本执行还是抓取环境。下面用一个假设情境串起决策过程。
假设你运营一个商品站,栏目页的链接由前端脚本在加载后动态注入。你用手工请求抓取原始 HTML 时,这些链接不存在;用一个会执行脚本的检查方式时,链接存在且返回正常。于是“死链查询”给出两份互相矛盾的清单:一份报告大量 404,另一份几乎全绿。
此时不要急着修链接。先确认一件事:你比较的是同一时刻、同一 URL、同一请求头下的两个状态吗?如果原始请求和渲染请求的入口 URL 不同、缓存状态不同、设备标识不同,差异可能全部来自比较条件,而不是页面本身。
把每个可疑 URL 记录成三层,而不是只记“有链接/没链接”:
<a href> 存在。三层里只有网络请求层最接近“用户真的点开会发生什么”。原始 HTML 没有链接,只说明链接不来自服务端输出;渲染后 DOM 有链接,也不代表该地址一定返回 200。
假设同一个 URL 在两种检查下结果不同,可以按下面的条件分流:
这四类里,只有第二类和第三类会真正影响用户到达页面的能力。第一类和第四类需要先修正检查方法,再谈修复。
选一个代表性 URL,关闭缓存和登录态,分别做两次请求:一次只取原始 HTML,一次让脚本执行完再取 DOM 和网络记录。把结果按上面的四类归档。
动作的结果会直接决定下一步:如果归档到第一类,下一步是检查脚本加载条件,而不是改链接;如果归档到第二类,下一步是找到改写链接的脚本片段,确认它是否把有效地址替换成了失效地址;如果归档到第三类,下一步是搜索脚本和配置中的旧路径,而不是只看页面上的可见链接。
这个动作的价值在于,它把“两个工具结果不同”变成了“差异发生在哪一层”。只有定位到层,修复才有明确对象。
即使你确认某个地址返回 404,也不要把 robots.txt 的抓取限制当成索引移除手段。robots.txt 限制的是抓取,不是可靠的索引移除;被限制抓取的 URL 仍可能因外部链接出现在结果中。站点地图也不保证收录,它只是提交候选地址的一种方式。
因此,当静态响应与脚本渲染结果不同时,先不要用“提交站点地图”或“改 robots.txt”来掩盖差异。先确认差异层,再决定是修服务端输出、修脚本,还是修抓取检查方法。
如果最终确认是脚本在渲染后生成了有效链接,而原始 HTML 没有,那么对依赖原始 HTML 的检查方式来说,这些链接会被误报为死链;对执行脚本的检查方式来说,它们可能正常。此时正确做法是统一检查口径,而不是同时相信两份清单。
静态响应和脚本渲染结果可以同时成立,前提是它们描述的是不同状态:静态响应描述服务端初始输出,渲染结果描述脚本执行后的页面。对用户可见性而言,渲染结果更接近真实;对服务端可控性而言,静态响应更接近可修复范围。
所以决策条件可以简化为:如果差异只出现在脚本注入的链接上,且这些链接返回正常,优先修检查方法;如果差异出现在脚本改写或移除后导致请求失败,优先修脚本;如果差异来自请求头、缓存或时间,优先固定检查条件后再比较。
把每个可疑 URL 归入其中一类,再决定改代码、改配置还是改检查流程,才不会在两种结果之间反复摇摆。