搜索抓取

软 404 与空壳页:蜘蛛拿到 200 之后看到的是什么

页面返回 200,内容却是空的——这类软 404 常被忽略。本文说明蜘蛛如何对待空壳页、它们常见的产生场景,以及从日志与页面特征识别后该怎么处理,避免白白消耗抓取预算。

搜索抓取

软 404 与空壳页:蜘蛛拿到 200 之后看到的是什么

状态码说的是“有”,内容说的是“空”

蜘蛛判断一个 URL 能不能抓,第一眼看的不是正文,而是响应状态码。返回 200,意味着服务器认为这个地址存在、可以正常访问,蜘蛛会把它放进待抓取队列,并按常规方式下载、解析、提取链接。问题在于,很多页面在状态码层面完全正常,打开之后却几乎没有内容:筛选条件组合出一个空结果、商品已经下架但模板还在、站内搜索关键词没人用过、分页翻过了最后一页。

这类页面通常被称为软 404或空壳页。它和硬 404 的区别是:硬 404 明确告诉蜘蛛“这里没有东西”,蜘蛛记下之后就不再频繁回访;而软 404 让蜘蛛每次都以为有东西,抓回来一看是空的,下一次可能还会再来。

蜘蛛为什么会把空页面当成正常页面

抓取是一件按信号执行的机械工作。蜘蛛拿到 200、响应时间正常、页面能解析出 HTML,就会走完整个流程:建立索引候选、提取出链、记录内容指纹。至于内容是不是有独立价值,属于后续的判定环节,而不是抓取环节的前置条件。

也就是说,空壳页并不会在抓取阶段被自动拦下。它先消耗掉一次请求、一次下载、一次解析,之后才可能被内容层面的规则过滤掉。如果这类 URL 数量很多,每次刷新又都返回 200,那么它们在队列里会持续占据位置。

空壳页常见的几个来源

  • 筛选与参数组合:多个筛选条件叠加后没有匹配结果,页面仍然渲染出一套完整的框架和导航。
  • 站内搜索结果页:关键词无结果、或结果极少时,页面主体接近空白。
  • 已下架内容:商品、文章被移除,但详情页 URL 仍返回 200,只剩标题和推荐位。
  • 超出范围的分页:列表只有 5 页,第 6 页及之后的地址没有做边界处理。
  • 依赖脚本渲染:内容需要接口返回后由 JS 填充,接口异常或超时,蜘蛛拿到的是一个空壳。
  • 地区、语言变体:模板生成了一堆变体 URL,但只有少数真正有内容。

它比硬 404 多消耗什么

硬 404 是一次性的:蜘蛛抓到、确认、降低回访频率,成本有限。软 404 的成本是持续的——同样的 URL 会在一段时间内被反复抓取,每一次都占用抓取预算。

更麻烦的是信号上的失真。站点向蜘蛛呈现的“有效页面”数量里混进了大量无内容地址,抓取配额被分摊到这些地址上,真正需要更新的页面反而排得更靠后。同时,页面内容高度重复或近乎空白,也会让蜘蛛对这个目录下 URL 的质量判断变得模糊。

判断标准可以简化成这样一句:如果这个 URL 明天返回 404,会不会有用户或业务受影响?如果不会,它很可能就是空壳。

怎么从日志和页面上认出来

  • 日志里状态码是 200,但字节数明显偏小,和同目录其他页面差出一截。
  • 响应时间很短,往往说明没有走数据库查询或查询直接返回空。
  • 页面标题是模板名或关键词拼接,正文区域几乎是导航和页脚。
  • 同一批 URL 在日志中反复出现,抓取频次不低,却看不到内容更新。
  • 搜索控制台或类似工具中会出现“软 404”“已抓取但未编入索引”类别的报告。

处理方式:先分层,再动手

  1. 确认页面是否具备独立价值。有真实内容、有搜索需求的筛选组合,可以保留并补齐说明文字;纯模板拼接的,不必强留。
  2. 无价值的直接返回 404 或 410。410 表示永久移除,语义更明确,对已经下架的内容更合适。
  3. 有过渡价值的用跳转。下架商品可以 301 到同类目或替代商品,无结果筛选可以 302 回上级分类页,让用户和蜘蛛都有落点。
  4. 需要保留但不希望被抓的用 noindex。注意 noindex 的页面仍可能被抓取,只是不进索引,因此它并不能替代状态码处理。
  5. 修渲染链路。如果空壳是脚本没跑起来造成的,要检查接口稳定性、必要的降级渲染,而不是简单地把页面删掉。

一个容易被忽略的平衡

把所有内容量偏少的页面一律当作空壳处理,同样会出问题。有些页面正文确实短,但承担着明确的入口作用;有些筛选组合虽然今天没有结果,明天可能就有了。判断的依据应当是“这个地址是否稳定地提供独立信息”,而不是单纯的字符数。

更稳妥的做法是定期从日志里筛出“200 且字节数偏低”的 URL 集合,按目录归类,看它们是被同一套模板批量生成的,还是零散存在的。批量生成的通常是规则问题,改模板或加边界判断就能收敛;零散的则要逐个确认内容状态。抓取预算从来不是被一次错误吃掉的,而是被成百上千个看似正常的空壳页慢慢摊薄的。