先给结论:如果死链只在特定时段出现,单次打开页面看到正常结果不能证明问题不存在,反过来单次看到404也不能说明它长期存在。你需要把它当成一个时间窗问题来处理,用带时间戳的重复探测把“偶发”变成“可复查的记录”,再决定是修链接、改跳转,还是先观察。
假设你手上有一份服务器访问日志,或者一个监控工具的报错截图。日志里某条URL在凌晨两点返回404,但你白天访问一切正常。这份资料能证明的是:在那个时间点、那个请求路径下,服务器返回了404。它不能证明的是:这个404是持续状态、是爬虫看到的版本,还是只对特定来源或特定参数出现。
所以第一步不是急着改,而是把证据按三个维度拆开:时间(几点到几点)、请求方(普通用户、搜索引擎爬虫、内部调用)、请求形态(带不带参数、带不带尾斜杠、走不走CDN)。只有这三个维度都对得上,你才有资格说“这是一个稳定的死链”。
不要靠人工在不同时间点刷新页面,那样既累又容易漏。更实际的做法是写一个定时任务,对可疑URL每隔几分钟请求一次,并把状态码、响应时间、返回内容长度、请求时间一起记下来。
如果你用命令行,可以简单到一个循环加curl -o /dev/null -s -w "%{http_code} %{time_total}\n",把输出追加到文件。重点不是工具多高级,而是记录里必须带时间戳和状态码。跑够一个完整业务周期,比如24小时或一周,你才能看到报错是否集中在某个时段。
这一步的实际动作是:选出3到5个最可疑的URL,包括一个已知正常的作为对照,连续探测。结果会影响下一步——如果只有可疑URL在特定时段报错,对照URL一直正常,问题更可能在链接本身或它依赖的资源;如果所有URL在同一时段都异常,那要查的是服务器、CDN或上游服务,而不是单个死链。
这是最容易误判的地方。一个URL在特定时段返回404,不等于搜索引擎已经把它记为死链。搜索引擎爬虫有自己的抓取节奏,它可能在那个时段根本没来,也可能来了但看到的是缓存版本。
你要看的证据至少包括两类:一类是服务器端记录,看爬虫在那个时段是否真的请求过这个URL、拿到什么状态码;另一类是页面层面的信号,比如这个URL是否还被站内其他页面链接、是否还在站点地图里。这里要记住一个事实:站点地图不保证收录,robots.txt的抓取限制也不等于可靠的索引移除。所以不要因为改了robots.txt或删了站点地图条目,就认为死链影响已经消除。
如果爬虫在那个时段确实拿到了404,而你又在同一时段对普通用户返回了正常内容,那说明你的服务对不同请求方行为不一致。这种情况优先查CDN缓存规则、动态渲染或边缘逻辑,而不是先去改链接。
拿到时间窗和请求方数据后,按下面的条件分流,而不是一律“发现404就改301”。
假设一个短例子:某产品页只在每天凌晨的备份任务期间返回404,持续约十分钟。探测记录显示这十分钟内所有请求都失败,备份结束后恢复。此时把它当死链去301,会掩盖真正的资源冲突问题;正确动作是调整备份任务与Web服务的资源隔离,之后再复查该URL是否还有异常。这个例子的数字只用于说明如何比较时段,不代表任何真实项目结果。
请求量归零、抓取量下降或某个状态码消失,都不能单独证明你的处理正确。它们还有别的合理解释:爬虫只是换了抓取节奏、页面被其他信号影响、或者你的探测本身出了问题。复查时至少同时看三样东西:带时间戳的状态码记录、站内是否还有指向该URL的链接、以及该URL当前对普通用户和爬虫是否返回一致结果。
如果这三样都指向同一结论,你才可以进入下一步;如果互相矛盾,说明证据还不够,继续探测比急着改动更划算。整个流程的核心不是消灭所有404,而是让每一次处理都有可复查的依据,这样下次再遇到只在特定时段出现的报错,你手里已经有现成的框架可以直接套用。