提交了 Sitemap 但收录没动静,问题往往不在 Sitemap 本身
每个月都有站长在群里问同一句话:「我 sitemap 提交了,为什么还是没收录?」提问的人通常已经做了三件事——生成 sitemap.xml、在站长平台提交、然后每天刷新「覆盖率」页面看数字有没有涨。可三个月过去,收录数还是那几十个页面。
这里要先破除一个误解:sitemap 不是收录工具,它只是一份「可选提示」。搜索引擎官方的说法一直很明确,sitemap 是帮助爬虫发现 URL 的辅助手段,它不保证抓取,更不保证收录。真正决定一个页面能不能被收录的是另外几件事:页面能不能被抓到、抓到的内容值不值得进索引、站点的整体信任度够不够。这篇文章按这个顺序,把整条链路上的排查方法讲清楚,包括几个中文站特别容易踩的坑。
第一层:确认爬虫真的来了
在讨论收录之前必须先确认抓取。打开 Nginx 日志,筛出搜索引擎的访问:
grep -iE 'baiduspider|googlebot|bingbot|yisouspider|sogou' /var/log/nginx/access.log \
| awk '{print $1, $7, $9}' | tail -50更实用的是按小时统计抓取量,看趋势而不是看单条:
grep -i 'baiduspider' /var/log/nginx/access.log \
| awk '{print substr($4,2,14)"h"}' | sort | uniq -c | tail -24结果可能是三种情况,对应完全不同的处理方向:
- 完全没有记录:说明爬虫根本没来,或者来的请求被防火墙/WAF 挡了、被 CDN 拦了。这时讨论收录毫无意义,先解决可达性。
- 有记录但只抓首页:说明内链结构有问题,爬虫找不到通往深层页面的路径。
- 有记录且抓得很勤,但收录不涨:这是最难的一类,问题在内容质量或站点信任度,不在技术层面。
顺带说一个高频事故:UA 黑名单误伤正规爬虫。有些安全插件或 Nginx 防爬规则会把所有「看起来像爬虫」的 UA 一并封掉,包括 Googlebot 和 Bingbot。检查你的 Nginx 配置里有没有类似 if ($http_user_agent ~* (bot|spider)) { return 403; } 的粗暴规则——这条规则一旦存在,你就同时封掉了所有正规搜索引擎。正确做法是白名单正规爬虫,再对剩下的做限速。
第二层:验证 sitemap 能被正常读取
用 curl 以爬虫的视角完整拉一遍,不要只看浏览器里能不能打开:
curl -sI https://www.example.com/sitemap.xml
curl -s https://www.example.com/sitemap.xml | head -20
curl -s https://www.example.com/sitemap.xml | xmllint --noout -三个检查点:
- HTTP 状态码必须是 200。返回 301/302 到别处、返回 403 被防火墙拦、返回 200 但内容是一个 HTML 错误页,都是常见问题。
- Content-Type 应为
application/xml或text/xml。如果服务器把它当成text/html返回,某些爬虫会拒绝解析。 - XML 必须格式合法。
xmllint不报错才算过。中文站最常见的错误是标题里有未转义的&,或者文章里混进了控制字符,导致整个 sitemap 解析失败——一个字符错误会让整份文件作废。
还要注意 robots.txt 有没有误伤 sitemap 自己。下面这行是致命错误:
Disallow: / ← 全站禁止抓取,sitemap 提交了也没用
如果确实需要临时屏蔽,正确写法是 Disallow: / 的同时不能指望搜索引擎会去读 sitemap。反过来,如果只想屏蔽某些目录,要确认没把 /sitemap.xml 或者 CSS/JS 目录也屏蔽掉。
第三层:sitemap 的 URL 列表本身干不干净
sitemap 里列了 500 个 URL,但其中 200 个是 404、100 个是带参数的重复页、50 个是 noindex 页——这份 sitemap 就是在给爬虫制造垃圾任务,会浪费抓取预算,严重时降低站点整体评价。
用脚本做一次完整体检。下面这段可以直接跑,输入你的 sitemap,输出每个 URL 的状态码、canonical 和 robots meta:
#!/bin/bash
# check-sitemap.sh —— 逐条验证 sitemap 中的 URL
SM="https://www.example.com/sitemap.xml"
curl -s "$SM" | grep -oE '<loc>[^<]+</loc>' | sed 's/<loc>//;s/<\/loc>//' > /tmp/urls.txt
while read -r u; do
code=$(curl -s -o /tmp/page.html -w '%{http_code}' -m 15 "$u")
robots=$(grep -oiE '<meta[^>]+name="robots"[^>]*>' /tmp/page.html | head -1)
cano=$(grep -oiE '<link[^>]+rel="canonical"[^>]*>' /tmp/page.html | head -1)
printf '%s\t%s\t%s\t%s\n' "$code" "$u" "$robots" "$cano"
done < /tmp/urls.txt > /tmp/sitemap-report.tsv
# 只看有问题的
awk -F'\t' '$1!=200 || $3 ~ /noindex/ || $4 !~ /canonical/' /tmp/sitemap-report.tsv输出里需要处理的三类问题:
- 状态码非 200:从 sitemap 里剔除。sitemap 只应该包含 200 的、可索引的正式页面。
- 带
noindex:自相矛盾。既然告诉搜索引擎「别索引」,就不要同时把它列在 sitemap 里。 - canonical 指向别的 URL:说明这一页是重复内容,sitemap 里应该只保留 canonical 指向的那个版本。
第四层:规范链接与重复内容
中文站特别容易产生重复 URL,因为同一篇文章可以从多个入口访问到:
/archives/123/和/archives/123(尾斜杠差异)/2026/10/18/post-title.html和/post-title.html/category/tech/和/category/tech/page/1/- 带
?utm_source=xxx等追踪参数的版本 - HTTP 与 HTTPS、www 与非 www 同时可访问
每一种都会让搜索引擎把同一份内容当成多个页面,结果是「收录了很多,但都不是主版本」,或者干脆全部被判为重复而放弃索引。处理方式是两道:
1. 服务端做 301 归一化。Nginx 里对 www 与非 www 做强制跳转:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
return 301 https://www.example.com$request_uri;
}2. 页面里加 canonical。每个页面都必须有一条指向自己的、绝对 URL 的 canonical。Typecho 和 WordPress 默认都会输出,但要确认它输出的是最终版本而不是带参数的版本。检查方式:
curl -s https://www.example.com/某篇文章 | grep -i 'rel="canonical"'如果 canonical 里带了 ?replyTo=、?from= 这类参数,说明模板写错了,所有评论翻页链接都会被当成不同的规范页。
第五层:站点地图索引与分片策略
单个 sitemap 文件有硬限制:最多 50000 个 URL、未压缩不超过 50MB。个人站一般不会超,但如果做了标签页、归档页、分页,URL 数量会膨胀得很快。规范做法是用 sitemap index:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.example.com/sitemap-posts.xml</loc>
<lastmod>2026-10-18</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-categories.xml</loc>
<lastmod>2026-10-18</lastmod>
</sitemap>
</sitemapindex>分片的原则是:只收录你希望被索引的页面。标签页、搜索结果页、分页第 2 页以后、作者归档页,这些通常不值得进 sitemap——它们要么是重复内容,要么价值极低,只会稀释抓取预算。
lastmod 要写真实修改时间,不要用 date() 动态生成当前时间。这是另一个常见错误:每次请求 sitemap 都返回「刚刚更新」,搜索引擎很快就会发现这个时间戳不可信,之后完全忽略 lastmod 字段,你的新文章也就失去了优先抓取的机会。
第六层:主动推送,别只等爬虫
sitemap 是被动发现,速度慢且不确定。对中文站来说,主动推送能明显缩短新文章从发布到收录的时间。目前可用的几条通道:
IndexNow
Bing、Yandex、Seznam 等支持。先在网站根目录放一个 {key}.txt 文件,内容就是 key 本身,然后 POST 提交:
curl -X POST https://api.indexnow.org/indexnow \
-H "Content-Type: application/json" \
-d '{
"host": "www.example.com",
"key": "你的32位key",
"keyLocation": "https://www.example.com/你的32位key.txt",
"urlList": [
"https://www.example.com/new-post-1.html",
"https://www.example.com/new-post-2.html"
]
}'返回 200 或 202 表示接收成功,422 通常是 URL 不属于声明的 host,403 是 key 校验失败。
百度普通收录 API
在百度搜索资源平台获取 token 后,用 POST 推送:
curl -H 'Content-Type:text/plain' \
--data-binary @/tmp/new_urls.txt \
"http://data.zz.baidu.com/urls?site=https://www.example.com&token=你的token"返回 JSON 里 success 是成功条数,not_same_site、not_valid 分别对应域名不符和格式错误。remain 是当天剩余配额,个人站通常每天几十到几百条,要省着用——只推新发布的文章,别把历史文章一股脑推一遍。
接入到发布流程里
最省心的方式是把推送挂到发布动作后面。Typecho 可以在主题的 functions.php 里挂 finishPublish 钩子,WordPress 用 publish_post action,Shell 脚本的话直接在发布命令后面追加一行 curl。关键是失败不能阻塞发布,所以要加超时和错误容忍:
curl -m 10 -s -X POST "https://api.indexnow.org/indexnow" \
-H "Content-Type: application/json" -d @/tmp/payload.json \
>> /var/log/indexnow.log 2>&1 || true第七层:如果抓取正常、sitemap 干净,还是没收录
排除掉所有技术问题之后,剩下的就是内容和站点信任度的问题。这时候需要诚实地回答几个问题:
- 这个页面提供的信息,网上是不是已经有了几十份一模一样的? 采集站、AI 批量生成的低质内容、模板化的产品页,都属于这一类。搜索引擎的识别能力这几年提升很大,模板文的收录率会非常低。
- 页面有没有实质内容? 只有一段摘要加一个「阅读全文」按钮,正文要点击才展开,这类页面在抓取时往往只能看到摘要。
- 站点是不是新站? 新域名通常有 3 到 6 个月的观察期,这段时间收录慢是正常现象,不需要每天改配置。频繁改标题、改结构反而会让搜索引擎降低信任。
- 有没有站内重复? 同一个主题写了十篇内容高度相似的文章,搜索引擎通常只留一篇。
这一层的解法没有技术捷径,只有一条:把每一篇文章写成别人不会写的东西。具体来说就是带上真实的数据、真实的命令、真实的报错信息、真实的时间线。同样是写「Nginx 优化」,一篇只列参数的模板文和一篇记录「某天 TTFB 突然从 200ms 涨到 2s,最后定位到 upstream keepalive 没开」的复盘文,收录率和排名完全不在一个量级。
一套可以每周跑一次的检查清单
把上面七层压缩成可执行的例行检查,每周花十分钟:
grep日志统计各爬虫近 7 天抓取量与状态码分布(重点看 5xx 和 403)。curl -sI确认 sitemap 返回 200 且 Content-Type 正确。xmllint验证 sitemap 格式,确认没有解析错误。- 跑
check-sitemap.sh,剔除 404、noindex、canonical 指向他处的 URL。 - 抽查 10 篇文章的 canonical 是否指向自身绝对 URL。
- 确认
robots.txt没有误屏蔽 CSS/JS/sitemap。 - 新发布的文章是否已经推送(IndexNow / 百度),推送日志里有没有失败记录。
这七步里,前六步是技术问题,都有确定答案;只有第七步之后的「内容质量」没有标准答案。但恰恰是后者决定了长期结果。技术排查的作用是确保你不会因为一个 301 或者一行 Disallow 白白浪费三个月,而内容才是那个真正让收录数字涨起来的东西。