在抓取这件事上,状态码是最直接的一层沟通。蜘蛛请求一个 URL,服务器回 200,它默认这里有一份可用的内容;回 404 或 410,它就知道这个地址不用再来了。麻烦出在两者之间:地址已经没有什么可看的,服务器却依然回 200。这类页面通常被称为软 404。
软 404 是怎么出现的
多数软 404 并不是有人刻意做出来的,而是模板和参数体系自然产生的副产品。常见的有这么几类:
- 筛选、排序、多条件组合之后没有任何结果,列表模板照常输出,只是中间是空的。
- 商品下架、文章删除后,详情页用兜底模板返回 200,正文位置写着“内容不存在”。
- 分页参数超出实际页数,比如 ?page=999 仍然返回一个空列表。
- 站内搜索结果页,没有任何关键词命中时同样返回 200。
- 空分类、空标签、只建了壳还没填内容的栏目页。
蜘蛛拿到 200 之后会做什么
蜘蛛并不理解页面上的文案含义,它主要依赖状态码、可解析的链接结构、以及页面之间的引用关系来判断一个地址值不值得保留。返回 200,等于告诉它“这里正常”。于是这个 URL 可能被收进索引,也可能在之后的抓取周期里被反复访问。
问题在于,抓取资源是有限的。如果站点里存在大量这类空壳地址,蜘蛛每次来都要在这些页面上花掉一部分时间,真正有内容的页面分到的份额自然会被挤压。
影响不只是浪费抓取
软 404 的代价大致有三层。第一层是抓取层面的消耗,前面已经提到。第二层是内容层面的干扰:大量结构相同、内容为空的页面混在索引里,会让站点整体呈现出一种“低信息密度”的状态。第三层是维护层面的,时间一长,你很难分清哪些地址是真的不存在,哪些只是暂时没有内容。
先找出来,再决定怎么处理
排查可以从几个角度同时看:
- 从服务器日志里筛出返回 200 的 URL,按路径模式归类,看哪些前缀下存在大量相似地址。
- 对同一模板的页面做抽样,比较正文区域的文字量,异常偏低的那一批往往就是软 404。
- 把站内搜索、筛选、排序这些参数单独列出来,观察它们产生的 URL 有多少被蜘蛛访问过。
- 结合搜索后台的覆盖面报告,看是否存在大量“已抓取但未收录”或“已发现但未抓取”的地址。
按类型分开处理,比一刀切更稳
确实已经不存在的
下架商品、删除的文章,如果没有替代页面,直接返回 404 或 410 是清晰的表达。410 语义更明确,表示永久移除,但实际使用中 404 已经够用。关键是不要让兜底模板继续返回 200。
暂时没有内容的栏目
如果栏目未来会有内容,短期内可以保留页面并加 noindex,避免它进入索引;等内容填充完再放开。如果长期没有补充计划,不必留着,直接 404 反而干净。
参数组合生成的空结果页
这类页面往往数量无限,靠逐个处理不现实。可行的方向是收敛参数:能合并的合并,能屏蔽的屏蔽,让蜘蛛只能访问到有意义的参数组合。此时再把剩余的空结果页统一返回 404。
站内搜索和筛选结果页
这类页面本身对用户有用,但不适合大量进入索引。常见做法是通过 robots.txt 或 noindex 控制,同时保证内部链接不要把蜘蛛引向随意拼接的搜索参数。
几个容易踩的坑
- 用 200 加 noindex 长期兜底。它能阻止收录,但抓取仍会发生,空页面还会被继续访问。
- 为了清掉软 404,把一批本来正常的页面也一并改成 404,反而制造了新的断链。
- 同时给软 404 页面设置 canonical,指向一个并不相关的地址,信号会变得混乱。
- 只处理详情页,忘了列表页、分页和参数页同样是软 404 的高发区。
判断标准可以很简单:如果这个地址对用户来说已经没有可看的内容,它就不该以 200 的形式出现在抓取视野里。
把口径固定下来
软 404 不是一次清理就能解决的问题,它会随着商品上下架、内容更新不断重新出现。更实际的做法是在模板和路由层面定下规则:什么情况下返回 404,什么情况下保留页面但加 noindex,什么情况下直接收敛参数。规则稳定之后,蜘蛛看到的地址集合会逐渐清晰,抓取资源也能更集中地落在真正有内容的页面上。