sitemap.xml 提交了却没用:分片、lastmod 与「已发现未编入索引」
很多站长都做过同一件事:在 Search Console 里提交 sitemap,看到状态显示「成功」,然后就等着收录上涨。两周过去,收录数一动不动,或者只增加了两三条。于是开始怀疑「搜索引擎是不是不收录新站了」。
这篇文章只讨论 sitemap 本身:它到底影响什么、不影响什么,以及三个最常见的配置错误——分片规则、lastmod 撒谎、以及「提交成功」的实际含义。
先纠正一个期待:sitemap 不是收录加速器
这是最根本的认知问题。Sitemap 的作用是发现(discovery),不是收录(indexing)。它告诉爬虫「我有这些 URL」,但它不承诺「爬虫会去爬」,更不承诺「爬完会收录」。
搜索引擎的收录决策取决于一套独立的判断:内容是否足够独特、是否有重复版本、页面质量如何、站点整体权重怎样。Sitemap 在此过程中的价值,是让一个本来需要靠外链才能被发现的 URL 有了被发现的机会。它解决的是「爬虫压根不知道这个页面存在」的问题,不解决「爬虫知道但觉得不值得收录」的问题。
所以如果你的站点收录上不来,先分清是哪一类:
- URL 在 Search Console 里完全没出现过 → 发现环节的问题,sitemap 可能真有用
- URL 显示「已发现,但尚未编入索引」 → 发现已经完成,问题在质量或抓取预算,改 sitemap 没用
- URL 显示「已抓取,但尚未编入索引」 → 爬虫已经看过内容,是内容判断问题,sitemap 更没关系
这三种状态在 Search Console 的「页面」报告里能直接看到,而且它们指向完全不同的修复方向。看到「已发现未编入索引」还在反复重传 sitemap,是在解决一个已经解决的问题。
误区一:把 sitemap 当成「URL 台账」,URL 越多越好
有些站长为了「让搜索引擎多收录」,把站点里所有能访问的 URL 都塞进 sitemap:分类页的每一页分页、标签页、搜索结果页、按日期归档页(/2026/09/)、作者页、甚至 ?page=2&sort=asc 这类带参数的排序页。
结果通常是反效果。原因是 sitemap 里的 URL 会共享同一个「抓取预算(crawl budget)」,而个人站的抓取预算非常有限——通常每天几十到几百次请求。你把 5000 个低价值 URL(分页、归档、参数页)塞进去,这些 URL 会消耗掉绝大部分抓取配额,真正重要的文章反而排在后面,等爬虫爬到已经是几天后了,而且这一轮爬完下一轮又要重新排队。
更糟的是,「已发现未编入索引」的 URL 数量会暴涨。这个数字本身会成为一个负面信号:它告诉搜索引擎「这个站里有大量页面不值得收录」。
合理的 sitemap 只包含你希望被收录的、内容唯一的、可以独立访问的页面:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/1109.html</loc>
<lastmod>2026-09-22</lastmod>
</url>
<url>
<loc>https://www.example.com/1108.html</loc>
<lastmod>2026-09-21</lastmod>
</url>
</urlset>注意这里没有 <priority> 和 <changefreq>。这两个标签 Google 早在多年前就明确表示会忽略,写了也是白写。很多教程还在教「首页 priority 设 1.0,文章设 0.8」,这套已经过时了——它不会带来任何效果,只是让文件变大。
误区二:lastmod 撒谎,把整个 sitemap 的可信度毁掉
这是三个错误里危害最大的一个,而且极其常见。
问题的成因往往在生成脚本里。比如有人这么写:
# 错误写法:每次生成都用当前时间 echo "<lastmod>$(date +%F)</lastmod>"
或者更隐蔽的,模板里写死了生成时间:
<url> <loc>.../1080.html</loc> <lastmod>2026-09-22</lastmod> <!-- 这篇三个月没改过 --> </url>
结果是:你每天重新生成 sitemap,每篇文章的 lastmod 都变成今天。Search Console 会看到「这个站 1000 个页面今天全部更新了」。
搜索引擎对 lastmod 是有条件信任的:当你长期、一致地提供准确的 lastmod,它会开始用它来优化抓取调度——只重爬真正更新过的页面,这能极大节省你的抓取预算。但一旦它发现 lastmod 是假的(比如某篇文章根本没变却说今天更新了),它就会停止信任整个 sitemap 的 lastmod,退回到「每次都全站重爬」的策略。你亲手把自己最有价值的一个信号作废了。
正确做法是从数据库里读真实的修改时间,而不是用生成时间:
SELECT cid, title, modified FROM typecho_contents WHERE type = 'post' AND status = 'publish' ORDER BY cid DESC;
把 modified 字段格式化后写进 lastmod。Typecho 的 typecho_contents 表自带 modified 列,它就是文章最后一次真正修改的时间戳,正好是这个字段需要的语义。
关于日期格式,补充一个容易踩的细节:lastmod 支持 YYYY-MM-DD 和完整的 W3C 格式(带时区)。如果你只精确到天,请不要输出时间部分然后随便填 T00:00:00+00:00——这会在 UTC 和非 UTC 之间造成一天的偏差,在某些情况下会让爬虫认为你的日期在未来。个人站用纯日期格式最简单也最不容易出错。
误区三:超过 50000 条不分片,或者分片了却不提交索引
Sitemap 协议有硬性上限:单个文件最多 50000 个 URL,且未压缩时不能超过 50MB。超了就是无效文件,搜索引擎会直接忽略整个文件——不是忽略超出部分,是整个文件都不处理。这一点很多人误解,因为文件本身可能还是能打开的,看起来「没问题」。
更常见的情况不是超上限,而是分片之后忘记提交索引文件。假设你的站点有 8000 篇文章,按 1000 条一个分片生成了 8 个文件:
https://www.example.com/sitemap-1.xml https://www.example.com/sitemap-2.xml ... https://www.example.com/sitemap-8.xml
然后在 Search Console 里提交哪个?正确答案是提交一个索引文件(sitemap index),让它指向 8 个分片:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.example.com/sitemap-1.xml</loc>
<lastmod>2026-09-22</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-2.xml</loc>
<lastmod>2026-09-22</lastmod>
</sitemap>
</sitemapindex>提交 sitemap.xml(索引),而不是逐个提交 8 个分片。逐个提交在 Search Console 里也能工作,但弊端是:每次新增分片你都要记得手动再去提交一遍,而且「索引里的 lastmod」这个能力你也用不上了——它能让搜索引擎知道哪些分片有更新,从而只重爬那部分。
另外,索引文件同样有上限(50000 个 sitemap 条目),但个人站远远到不了,不用操心。
robots.txt 与 sitemap 的配合:别把自己挡住了
这是一个「自我封锁」的经典错误:sitemap 里列了 8000 个 URL,但 robots.txt 里写着 Disallow: / 或者某条规则意外命中了文章路径。结果爬虫来了,发现所有 URL 都被禁止抓取,sitemap 里的 URL 全部变成「已发现未编入索引」,而且会一直卡在这个状态——因为爬虫不会去抓被 disallow 的页面。
更隐蔽的一种是 Disallow 和 sitemap 互相矛盾但不完全覆盖。比如:
User-agent: * Disallow: /*.php$ Sitemap: https://www.example.com/sitemap.xml
如果站点用的是「伪静态 + 部分页面走 .php」的结构,这条规则可能悄悄封掉了一些正常页面。排查方法很简单:打开 robots.txt 的「测试」工具,把 sitemap 里的某个 URL 贴进去,看它是否显示「已被封锁」。如果有,先修 robots.txt,sitemap 的事往后放——顺序反了怎么改都没用。
正确的配合方式是在 robots.txt 末尾声明 sitemap 位置:
User-agent: * Disallow: /admin/ Disallow: /search Sitemap: https://www.example.com/sitemap.xml
注意 Disallow 路径要写具体的目录,不要图省事用通配符封一大片。Sitemap 指令只是「提示」搜索引擎文件在哪,不是必须项——搜索引擎也会自己检查 /sitemap.xml 这个默认位置。但显式声明仍然值得做,尤其是 sitemap 不放在根目录的时候。
验证清单:提交之后到底该看什么
Sitemap 的工作不是「提交完就结束」,而是要按下面这几步验证:
- 文件本身能否访问:
curl -I https://www.example.com/sitemap.xml必须是 200,且Content-Type是 XML。如果服务器返回text/html(比如被伪静态规则劫持到了 404 页面),搜索引擎会判定格式错误。 - XML 格式是否合法:所有标签必须闭合,
&必须写成&(URL 里的参数尤其要注意)。一个未转义的&会让整个文件解析失败。 - URL 是否可访问:随机抽 5 个 URL 用
curl -I检查是否返回 200。sitemap 里放 404 或 301 的 URL,会浪费抓取预算并降低文件可信度。 - 是否与 canonical 一致:sitemap 里的 URL 必须和页面里的
canonical标签完全一致,包括是否带www、结尾有没有.html、协议是 http 还是 https。不一致会直接导致「备用网页(有适当的规范标记)」问题。 - 看 Search Console 的分类报告,而不是只看「成功」两个字。「已发现未编入索引」和「已抓取未编入索引」需要完全不同的处理,把这两类分开统计,才知道该优化什么。
最后回到最开始那句话:sitemap 是发现工具,不是收录工具。个人站真正的收录瓶颈几乎从来不在 sitemap 上,而在内容是否有独立价值和站内是否有合理的链接结构。一个正确配置的 sitemap 只需要做对三件事——列对 URL、说真话的 lastmod、不超过上限——剩下的精力应该花在内容和内链上,那才是真正决定收录的部分。把 sitemap 当救命稻草反复重传,是在一个已经解决的问题上耗时间,而那些时间本来可以用在写下一篇真正的文章上。