收录掉了一个季度没人发现:用 GSC 覆盖率报告和访问日志对账的排查记录
阅读前提:网站已在 Google Search Console(以下简称 GSC)验证,服务器保留访问日志。
事情是怎么被发现的
今年 3 月 11 日,我去一家做精密蜗轮减速机的工厂(化名「恒达传动」)驻场。市场部的小周把我拉到工位前,语气里带着点委屈:"领导说咱官网在 Google 上搜不到了,你是搞技术的,你给看看。"

我先在 Google 上用 site:hengda-example.com 查了一下,返回结果少得可怜。然后打开他们 GSC 后台,一看「网页索引编制」报告里的已编入索引数量:2025 年 11 月还有 1180 页,到 3 月初只剩 412 页。掉收录这件事不是哪天突然发生的,是过去三个多月慢慢漏光的,中间没有任何人看后台。
这不是个例。做工业品官网的团队大多没有专职 SEO,网站"打不开吗?能打开啊",于是没人管收录。等销售在海外展会上被客户问到"你们网站上怎么找不到这个型号",问题已经攒了一个季度。
GSC 覆盖率报告先看什么
GSC 的「网页索引编制」报告(旧版叫覆盖率报告,Coverage Report)把所有已提交的 URL 分成两大类:返回了 200 且已编入索引的,和"未编入索引"的。后者才是重点,里面每一行排除原因都值得点进去看数量。
恒达官网当时的排除原因分布是这样的(3 月 12 日导出的数字,仅代表该站当时状态):
| 排除原因(GSC 原文) | 页面数 | 初步判断 |
|---|---|---|
| 已编入索引 | 412 | 正常存量 |
| 重复网页,Google 选择的规范网页与用户指定的不同 | 486 | 详情页带 session 参数导致重复 |
| 已编入索引,但被 robots.txt 屏蔽 | 0 | 见下文,此处反而是线索 |
| 找不到(404) | 57 | 老型号下线,正常 |
| 软 404(soft 404) | 23 | 搜索结果空页被抓 |
| 已抓取 - 尚未编入索引 | 31 | 抓取预算不足或质量存疑 |
看到这份表,第一反应是那个 486 的重复网页数字。但真正让我后背发凉的是另一件事:已编入索引,但被 robots.txt 屏蔽 是 0——而他们 1 月中旬刚换过 CDN,运营顺手改了 robots.txt。我立刻去翻了改版记录,果然,新的 robots.txt 里多了一行 Disallow: /products/,本意是想屏蔽一个内网测试目录,路径写串了。
也就是说:1 月 14 日上线的新 robots.txt 把整个产品目录封了。 Google 的处理方式很"温和"——已索引的页面不会立刻消失,而是在接下来几周里随着重新抓取陆续从索引里退出,同时因为被封了 robots,GSC 里连"被屏蔽"的记录都看不到(被 robots 封锁的 URL 抓都抓不了,自然不进覆盖率报告的正常统计)。这就是为什么掉得悄无声息。
访问日志对账:GSC 说的和爬虫做的是不是一回事
GSC 报告是 Google 的一面之词,而且数据延迟好几天。要确认"Googlebot 到底来没来、来了抓的是哪些 URL",得回到服务器自己的访问日志。这是我最推荐的对账手段:GSC 说某类 URL 被排除,日志能告诉你爬虫是不是真的来过、来了多少次、拿到什么状态码。
恒达用的是 nginx,日志按天切分,保留 90 天。环境:Python 3.12 / nginx 1.24 标准日志格式。下面这段小脚本我改了三四处之后基本可以在任何 nginx 日志上复用:
import re
from collections import Counter
from pathlib import Path
# nginx 默认 combined 格式的一行日志
# 正则只抓用得到的字段,写太长在日志量大时会很慢
LINE = re.compile(r'(?P<ip>\S+) .*?"(?P<ua>[^"]*)".*?"(?P<req>\S+) (?P<url>\S+)[^"]*" (?P<status>\d{3})')
def is_googlebot(ua: str) -> bool:
# 真实校验应做反向 DNS,工程上先用 UA 粗筛
return "Googlebot" in ua
counts = Counter()
# 逐天逐行扫,nginx 按天切分的日志直接丢进来就行
for f in Path("logs/2026-03").glob("*.log"):
for line in f.open(encoding="utf-8", errors="ignore"):
m = LINE.search(line)
# 粗筛:UA 带 Googlebot 的行才进入统计
if not m or not is_googlebot(m["ua"]):
continue
url = m["url"].split("?")[0]
# 归并到目录级,看抓取都花在哪个目录上
prefix = "/".join(url.split("/")[:3])
counts[prefix] += 1
# 对照组:把 202603 换成 202601 再跑一遍,就能对比改版前后的抓取分布
for prefix, n in counts.most_common(10):
# 输出目录级抓取次数,和 GSC 覆盖率数据交叉对账
print(f"{prefix}\t{n}")
跑 3 月 1 日到 10 日的日志,结果很能说明问题:/products/ 目录的 Googlebot 请求是 0 次,而 / 根路径和 /news/ 加起来每天还有一两百次。作为对照,我又拉了 1 月 10 日(改 robots 之前)的日志,/products/ 每天有 60 到 90 次抓取。两边一对照,时间线就锁死了:1 月 14 日之后,Google 对产品目录的抓取彻底停了。
顺带在日志里还发现一个次要问题:URL 分析里 ?sid= 开头的会话参数占了抓取量的三成多,这些页面内容完全一样,白白消耗抓取预算(Crawl Budget,抓取预算)。
断点在哪:抓取、索引与排序的机制差异
排查到这里,有必要把搜索引擎的流水线捋一遍,不然很容易把"掉收录"和"排名掉了"混为一谈。搜索引擎对网页的处理分三步:抓取(Crawl)→ 索引(Index)→ 排序(Ranking),三个环节各自可能断掉,断的位置不同,现象和解法完全不一样。
flowchart LR
A[提交 / 发现 URL] --> B{robots.txt 放行?}
B -- 拦截 --> X1[不抓取, 页面进不了任何报告]
B -- 放行 --> C[抓取 拿到 HTML 与状态码]
C --> D{noindex / 404 / 软404?}
D -- 是 --> X2[不索引, 进覆盖率报告排除项]
D -- 否 --> E[内容分析与去重 规范化 canonical]
E --> F{判定为重复或低质?}
F -- 是 --> X3[重复网页省略, 不占索引]
F -- 否 --> G[进入索引]
G --> H[排序 面向具体查询]
恒达的断点在第一步和第三步之间:robots 封禁让 /products/ 直接停在抓取之前;?sid= 参数页面则卡在去重环节,被归并掉。很多人以为"页面只要能访问就会收录",实际上从可访问到进入索引,中间隔着 robots 放行、状态码健康、内容去重三道闸门,任何一道关了都会掉收录,而且 GSC 里未必有醒目提示。
robots 这道闸门尤其阴险:它发生在抓取之前,所以 GSC 的抓取统计里根本不会出现这些 URL,覆盖率报告也不会把它们列进"被屏蔽"——你只能从"已索引数量持续下降 + 日志里抓取归零"这两个反向信号推出来。
对账的固定流程
后来我把这套排查固化成了一个流程图,团队里谁遇到收录异常都照着走一遍:
flowchart TD
S[发现收录异常] --> T1[GSC 已索引数量导出 与 3 个月前对比]
T1 --> T2[覆盖率报告排除原因分类计数]
T2 --> T3[服务器日志统计 Googlebot 抓取分布]
T3 --> Q{日志抓取 与 GSC 数据对得上吗?}
Q -- 抓取为零 --> R1[查 robots.txt / noindex / CDN 防火墙]
Q -- 抓取正常但不索引 --> R2[查状态码 / 软404 / 重复内容与 canonical]
R1 --> F[修复后用 URL 检查工具请求编入索引]
R2 --> F
F --> W[每周对账一次, 观察恢复曲线]
这里面有两个细节值得强调。一是对账要比对两个口径:GSC 记录的是"Google 认为它对你的站做了什么",日志记录的是"你的服务器实际看到了什么",两者对不上的时候,日志是更可信的那份。二是 URL 检查工具(URL Inspection)里的"请求编入索引"有配额限制,只对关键页面用,别拿来全站推。
修复与恢复过程
修复动作本身不复杂,1 月埋的雷 3 月拆:
- robots.txt 撤掉
Disallow: /products/,线上用 curl 确认生效; - 详情页加 canonical 指向无参数的干净 URL,并在响应头里关掉会话写死进链接的逻辑;
- 给 GSC 提交了一份新的站点地图,只含 600 个真实产品页;
- 软 404 的 23 个页面改造成正常的"无结果"页,返回明确的 404。
验证 robots 是否真的放行,用 curl 就够了,环境:任意带 curl 7.x 的终端:
# 确认 robots.txt 已经不再屏蔽产品目录
curl -s https://www.hengda-example.com/robots.txt | grep -n "products" || echo "OK: 无 products 规则"
# 看产品详情页响应头里有没有意外出现的 X-Robots-Tag(noindex 会藏在响应头里)
curl -sI https://www.hengda-example.com/products/worm-gear-50.html | grep -i "x-robots-tag" || echo "OK: 响应头无 noindex"
恢复不是线性的。按我们自建监测口径(每周三用 site: 查询和 GSC 后台各记一次,非任何第三方工具数据),3 月 19 日索引数还在 405,4 月 2 日回到 620,4 月 23 日到 980,5 月中旬基本回到 1150 附近,前后花了两个多月。前两周最煎熬,因为修复后日志里 Googlebot 对 /products/ 的抓取恢复得很慢——它对被长期封禁的站点会留有戒心,抓取频率是逐步爬回来的。
| 时间点 | 已编入索引(GSC) | /products/ 日均抓取(日志) | 备注 |
|---|---|---|---|
| 2026-01-10 | 1172 | 73 | 换 CDN 与改 robots 前一周 |
| 2026-03-12 | 412 | 0 | 进场排查当天 |
| 2026-04-02 | 620 | 21 | 修复后第三周 |
| 2026-05-14 | 1148 | 68 | 基本回到事故前水平 |
复盘:为什么一个季度没人发现
总结下来有三条经验,说给同样没人管 SEO 的团队:
- 收录监控要放报警。GSC API 每天拉一次已索引数量,环比掉 10% 就发消息到群,成本一小时,恒达这次损失的三个多月本可以缩到一周以内。
- 改 CDN、改 robots、改认证策略这类动作,上线当天就该跑一遍日志对账,确认 Googlebot 还能正常进站。CDN 的 WAF 误拦 Googlebot 也是高发事故,和这次的 robots 封禁是同一种病。
- 换 CDN 后响应头要全部核对,X-Robots-Tag 里残留 noindex、Vary 头异常都会让索引悄悄掉,这些在页面上是看不出来的。
也有没彻底解决的问题:?sid= 的重复页面在修复后一个月才从 GSC 的"重复网页"分类里清干净,Google 收回这些 URL 的速度远慢于我的预期,最后靠站点地图 + 内链清理双管齐下才压下去。另外他们百度那边的情况我没细查,但同一家工厂在百度收录同样从 800 多掉到 300 出头,症结是另一套(百度对 HTTPS 和 JS 渲染的处理和 Google 差异很大),那是另一篇文章的事了。
补一句和 GEO(Generative Engine Optimization,生成式引擎优化)的关系:这次修复让站点恢复干净、结构清晰,这既是传统 SEO 的底子,也是内容将来被 AI 搜索引擎引用的前提——索引都进不去的页面,谈不上被任何引擎引用。
参考与延伸
- Google Search Console 网页索引编制报告官方文档:https://developers.google.com/search/docs/monitoring-debugging/inspect-index
- robots.txt 规范与测试工具:https://developers.google.com/search/docs/crawling-indexing/robots/intro
- Google 抓取预算说明(大型站点必读):https://developers.google.com/search/docs/crawling-indexing/overview-google-crawlers
- MDN 的 X-Robots-Tag 与 robots meta 说明:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Robots-Tag
GSC覆盖率 · 访问日志对账 · 索引诊断 · robots.txt · 抓取预算 · SEO · 网站优化