先别急着改服务器配置。你手上那个被外链指向、返回 200 的错误页面,真正需要核对的是三件事是否指向同一个结论:HTTP 状态码、页面实际渲染出的内容、以及搜索引擎抓取时看到的那一份响应。三者只要有一处不一致,链接权重和用户信任就会流向一个本该消失的地址。下面按你手里已有的资料逐步拆解。
错误页面返回 200 通常有两种成因,处理方向完全不同。
区分方法:用命令行请求该地址,只看响应头第一行,再看正文首屏是否出现“不存在”类文案。如果状态 200 且正文是正常首页内容,属于第二种;如果状态 200 且正文明确说内容缺失,属于第一种。两种情况下,外链指向的域名都会持续传递信号给一个无效目标,但修复动作不同——前者改模板输出逻辑,后者改重写规则。
不要分两次操作(一次看状态、一次看页面),否则你无法证明两者来自同一次响应。用一条命令把响应头和正文一起留存:
curl -sS -D headers.txt -o body.html -A "Mozilla/5.0" https://example.com/old-page
这条命令把响应头写入 headers.txt、正文写入 body.html,且使用同一个请求。随后检查两点:
headers.txt 第一行是否为 HTTP/1.1 200 OK(或 HTTP/2 等价形式)。body.html 中搜索“不存在”“已删除”“返回首页”等模板文案是否出现。如果状态是 200 而正文是错误提示,你就拿到了软 404 的直接证据。这个证据的意义在于:它排除了“浏览器缓存显示旧页面”的干扰,因为命令行请求不经过你的浏览器缓存。下一步该做的是把这个证据交给负责模板或路由的人,而不是继续在外链侧做清理。
有些站点在服务端返回 200 和一段占位内容,再由前端脚本替换成真正的错误提示。这种情况下,原始 body.html 里看不到错误文案,但用户看到的是错误页。判断方法是比较两种结果:
如果两者不同,说明状态码由服务端决定、内容由客户端决定,二者已经分家。此时仅修改服务端状态码可能不够,因为前端仍会渲染出错误提示。你需要确认错误提示是由哪一层输出的,再决定统一到哪一层。假设某页面服务端返回 200 加空壳,前端脚本检测到数据为空后渲染“内容已下架”——那么只把服务端改成 404 并不能阻止前端脚本继续运行,最终用户可能看到一个 404 状态配错误文案,这比 200 配错误文案更接近正确,但仍需确认脚本不会在 404 响应上继续请求数据。
同一份内容可能存在多个 URL 变体,比如带与不带末尾斜杠、带与不带查询参数。外链实际指向的变体未必是你正在检查的那一个。动作:从外链来源页复制链接地址,不要手动输入。然后对该完整地址执行上面的请求命令。
结果如何影响下一步:如果外链指向的变体返回 200 且内容正确,而另一个变体返回 200 且内容是错误页,那么问题范围缩小到那一个变体的处理规则。你不需要重做整站错误页策略,只需修正该变体的路由或重写条件。反之,如果所有变体都返回 200 错误内容,说明问题在统一入口层,需要整体调整。
常规做法(改状态码、提交删除、等待重新抓取)之所以可能无效,往往是因为缺少一份能复查的记录。建议在修复前后各保存一次请求证据,并注明假设条件。
注意,抓取量或某个统计归零不能单独证明修复正确。抓取量下降也可能来自抓取预算调整、站点整体流量变化或该路径暂时未被调度。真正能支撑判断的是同一 URL 在修复前后状态码与内容的一致性变化。
另外,robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录。如果错误页面同时被 robots.txt 屏蔽,你更需要在屏蔽之外单独核对状态码,否则抓取工具可能根本看不到真实响应,你也就拿不到可复查的证据。把这份前后对照记录保存下来,下一次遇到同类页面时,你可以直接复用同一套请求命令和比对字段,而不必重新猜测问题出在哪一层。