本文是一次真实排查记录:站点在 Google Search Console 里显示大量页面“未编入索引(Not indexed)”,通过逐条定位,最终锁定并修复了 4 类问题。适合用静态生成(SSG)+ CDN 部署的站点参考。
一、先看懂 GSC 的“未收录”分类
打开 Search Console 的“网页 → 未编入索引”,Google 会按原因分组。常见的几类,性质完全不同:
| 原因 | 含义 | 要不要处理 |
|---|---|---|
| Page with redirect | 该 URL 有重定向 | 一般正常(如 http→https) |
| Alternate page with proper canonical tag | 被判为“别的页面的替代页” | 要查 canonical 是否指对 |
| Crawled - currently not indexed | 抓了但暂未收录 | 内容页要关注;sitemap.xml 属正常 |
| Duplicate / Soft 404 | 重复或软 404 | 要处理 |
关键心态:GSC 里的“示例 URL”是历史抓取快照(看 last crawled 日期),不代表页面当前状态。判断线上真实情况,一律以 curl 实测为准。
二、问题 1:canonical 全部指向首页
症状
每个详情页的 <head> 里 canonical 都写成了首页:
<link rel="canonical" href="https://example.com/">
后果非常严重:Google 认为所有页面都自称是首页的副本,于是只保留首页、其余全部当“替代页”丢弃,收录数几乎归零。
排查
直接抓线上 HTML 看 ground truth:
curl -s https://example.com/some/page.html | grep -o 'rel="canonical" href="[^"]*"'
如果每个页面都输出首页地址,就是 canonical 生成逻辑坏了(或部署的是旧文件)。
修复
每个页面的 canonical 必须指向它自己的绝对 URL:
<!-- 章节页 -->
<link rel="canonical" href="https://example.com/n/book/001.html">
<!-- 分类页 -->
<link rel="canonical" href="https://example.com/c/beauty/">
模板里用“页面自身路径”生成,别用默认值兜底成 /。改完记得重新生成 + 重新部署——很多时候代码早修好了,只是线上跑的是旧静态文件。
三、问题 2:www 与非 www 重复内容
如果 https://example.com/ 和 https://www.example.com/ 都返回 200(都能访问),就是重复内容。应当二选一为主,另一个 301 跳过去。
验证是否已跳转:
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" https://example.com/
用 Cloudflare 的话,加一条重定向规则(或页面规则)把非 www 打到 www:
- 匹配 URL:
example.com/* - 转发到:
https://www.example.com/$1,状态码 301
四、问题 3(最隐蔽):软 404 —— 不存在的路径返回“200 + 首页”
症状
随便访问一个根本不存在的路径,却返回了首页内容、且状态码是 200:
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.com/this-path-not-exist-xyz/
# 期望 404,实际却是 200
这就是软 404(soft 404)。很多 SSG + Cloudflare Pages / SPA 部署会默认对“找不到的资源”回退到 index.html 并返回 200。后果:
- 任何打错的、过期下架的 URL 都变成“200 + 首页内容”;
- Google 认为你有无数个跟首页重复的页面 → 判为“首页的替代页 / soft 404” → 浪费抓取预算、稀释收录。
这往往是“大量页面未收录”的真正大头,比 canonical 更隐蔽。
修复:让不存在的路径返回真正的 404
Cloudflare 的静态资源服务由 not_found_handling 控制:
single-page-application:找不到就返回200 + index.html(SPA 才需要);404-page:找不到就返回最近的404.html+ 真正的 404 状态码。
对内容站/静态站,做法是在输出目录放一个 404.html。Cloudflare Pages 检测到它后,会对未命中的路径返回该页 + 404 状态码。404 页记得加 noindex:
<meta name="robots" content="noindex,follow">
修完再测一次,乱打路径应返回 HTTP 404。
五、问题 4:静态生成要清理“幽灵页面”
增量生成通常只覆盖/新增,不会删除已下架内容对应的旧 HTML。这些旧文件继续被部署,就成了“幽灵页面”。
建议:全量生成前先清空该站点的输出目录再重建,保证下架的内容能真正从站点消失(清空时务必做路径安全校验,只允许删“输出目录/域名”这一层,避免误删)。
六、关于 sitemap.xml 的正确认知
两个常见误解:
- sitemap.xml 出现在“Crawled - currently not indexed”是正常的。它是给爬虫读的数据文件,本就不该作为网页被收录,会一直停在这个状态,不是错误。
- sitemap 里应当只列真实存在、可收录的页面,且用绝对 URL、带
lastmod。下架的内容要从 sitemap 移除。
改完后在 GSC 重新提交 sitemap,并对想收录的页面用“网址检查 → 请求编入索引”。
七、排查清单(收藏备用)
- 用
curl抓线上 HTML,核对每页canonical是否自指; - 确认 www/非 www 只有一个主版本,另一个 301;
- 访问一个不存在路径,确认返回 404 而非 200+首页;
- 全量重建时清空旧产物,杜绝幽灵页;
- sitemap 只列真实页面,GSC 重新提交;
- 记住:GSC 数据有滞后,改完通常几天到两周才更新,耐心等重爬。
小结:静态站 SEO 的坑大多不在“写了什么”,而在“部署出去的到底是什么”。养成用
curl验证线上真实响应(状态码 + canonical)的习惯,能省下大量猜测时间。