站点上线两周,搜自己的域名,搜索结果里什么都没有。
被动等爬虫来发现新内容,快则几天,慢则几周。但百度和 Bing 其实都开放了主动推送的通道,发布文章的同时就能把网址告诉它们,等待时间可以压到几小时。这篇记录一遍完整的接入过程,顺便把踩过的坑写下来——其中有一个卡了我半天,官方文档只字未提。
三家能做的事差别很大
不少教程会把三家并列讲,容易让人以为接入方式大同小异。实际上:
百度有主动推送 API,站长自助拿 token,没有审核,推完通常几小时到一两天就能收录。Bing 走 IndexNow 协议,同样不需要申请,而且这个协议 Yandex 等也接入了,推一次多家生效。
Google 没有。
它确实有个 Indexing API,但官方限定只对招聘信息(JobPosting)和直播(BroadcastEvent)两类结构化数据开放。普通博客、企业站调用它属于滥用,不会生效,还可能被判违规。网上那些"用 Indexing API 实现秒收录"的文章,是错的。
Google 这边唯一正规的加速手段就是提交 sitemap,然后等爬虫自己安排。心里先有这个预期,后面就不会因为"怎么还没收录"反复折腾。
先把域名收敛到一个
这一步经常被跳过,但它是地基。
很多站同时能从多个域名打开,example.com 和 www.example.com,或者主域名和某个子域名指向同一份内容。如果它们都能访问且不跳转,搜索引擎会当成两个站上的重复内容,权重分散,两边都排不上去。
选定一个规范域名,然后做两件事。服务端加 301,把其它域名全指过去:
server {
server_name www.example.com;
return 301 https://example.com$request_uri;
}
页面里加 canonical,明确告诉搜索引擎收录哪一个:
<link rel="canonical" href="https://example.com/posts/hello">
canonical 必须是绝对地址,而且始终指向规范域名,哪怕用户是从 www. 进来的。站长平台里也只提交这一个域名,别两个都提交。
后面所有环节——sitemap 里的网址、推给搜索引擎的网址——都用这个域名。
sitemap.xml 和 robots.txt
这两个文件三家都认,是搜索引擎理解站点结构的基础。
sitemap 的格式没什么可说的:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://example.com/posts/hello</loc>
<lastmod>2026-08-01T10:00:00Z</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
</urlset>
几个容易做错的地方。<loc> 要用绝对地址而且是规范域名。<lastmod> 要真实,如果图省事每次生成都填当前时间,搜索引擎发现这个字段不可信之后就会忽略它。搜索结果页、后台、草稿预览、带筛选参数的列表页别塞进去,收录它们只会制造一堆重复内容。
sitemap 应该由程序按数据库里已发布的内容动态生成。手工维护的 sitemap,三个月后一定是过期的。
robots.txt 放根目录:
Sitemap: 那行必须写绝对地址。另外要清楚 robots.txt 只是君子协定,不是访问控制,真需要保护的路径得靠鉴权。把敏感路径写进去反而等于公开告诉别人这些路径存在。
百度
国内站这一步收益最大,百度的被动抓取相当慢,但推送很灵。
到 ziyuan.baidu.com 登录,用户中心 → 站点管理 → 添加网站,填域名(注意选对协议)和站点属性,验证方式选 HTML 标签验证。它会给你一段:
<meta name="baidu-site-verification" content="codeva-XXXXXXXXXX" />
只取 content 的值,把这个 meta 加到首页的 <head> 里,回去点完成验证。
建议把验证码做成后台可配置项,别硬编码在模板里。三家加起来有三个验证码,将来换域名或重新验证时,改配置比改代码重新部署一次省事得多。
验证通过后,左侧「普通收录 → 资源提交 → API 提交」,页面上会显示接口调用地址:
token= 后面那串就是准入密钥。推送的请求体是纯文本,一行一个网址:
curl -X POST "http://data.zz.baidu.com/urls?site=https://example.com&token=你的TOKEN" \
-H 'Content-Type: text/plain' \
--data-binary 'https://example.com/posts/hello'
成功会返回 {"remain":4999,"success":1},success 是本次推成功的条数,remain 是当天剩余配额。个人站点通常每天有几千条额度,正常写作节奏根本用不完。
site 参数千万不要 URL 编码
这就是卡了我半天的那个坑。
用代码拼 URL 时,很多语言的标准做法是对查询参数做转义,Go 的 url.QueryEscape、Python 的 urllib.parse.quote 都是。https://example.com 转义之后变成 https%3A%2F%2Fexample.com,看起来完全正常。
但百度不对这个参数做 URL 解码,它是拿这个字符串跟平台登记值做字面量比对的。转义之后就成了另一个字符串。同一个 token,两种写法结果完全不同:
# 原样
{"remain":4999,"success":1}
# 转义后
{"error":400,"message":"site init fail"}
site init fail 这个报错也很坑,字面看像是"站点初始化失败",会让人往"是不是站点没验证好""是不是百度那边还没准备就绪"的方向查。我一开始就是这么查的,还去对了半天平台上登记的域名格式。
所以 site 要原样拼接。但不转义就得自己保证内容安全,万一这个值来自用户配置,里面带个 & 就会把查询参数结构冲掉。稳妥点的做法是先规范化成 scheme://host,把可能存在的路径和查询串丢掉:
u, _ := url.Parse(configuredSiteURL)
site := u.Scheme + "://" + u.Host
endpoint := fmt.Sprintf("%s?site=%s&token=%s", baseURL, site, url.QueryEscape(token))
token 转不转义都行,它本来就是字母数字,转义结果一样。只有 site 不能动。
200 不代表成功
百度即使返回 HTTP 200,响应体里也可能带错误:
{"error":401,"message":"token is not valid"}
所以不能只看状态码,必须解析响应体里的 error 字段。否则日志会一直显示推送成功,实际一条都没进去。
Bing 和 IndexNow
Bing 这块有个很省事的地方,也有个容易混淆的地方。
省事的是验证。到 bing.com/webmasters 登录后,如果你已经在 Google Search Console 验证过站点,直接点导入并授权 Google 账号,Bing 会把站点连同所有权验证状态一起同步过来。这条路走下来完全不需要 msvalidate.01 标签。
前提是 GSC 那边已经验证成功,所以顺序上建议先做 Google 再回来做 Bing。如果 GSC 还没弄,就手工添加站点,验证方式选 HTML 元标记,同样取 content 的值加到首页。
容易混淆的是 IndexNow。它和上面选哪种验证方式没有关系,两种情况下都得单独做一遍。站点验证解决的是"这个站是不是你的",IndexNow 解决的是"有新内容时主动通知",两套独立机制,走导入路径不会自动带上 IndexNow 密钥。
IndexNow 不需要账号也不需要审批,自己生成一个密钥就能用:
openssl rand -hex 16
# 3f2a9c1e8b7d4056a1c3e5f7092b4d6e
把这串密钥原文放到网站上一个能公开访问的位置,文件内容就是密钥本身。然后推送:
curl -X POST "https://api.indexnow.org/indexnow" \
-H 'Content-Type: application/json; charset=utf-8' \
-d '{
"host": "example.com",
"key": "3f2a9c1e8b7d4056a1c3e5f7092b4d6e",
"keyLocation": "https://example.com/indexnow-key.txt",
"urlList": ["https://example.com/posts/hello"]
}'
返回 200 表示已接收,202 表示已接收但密钥还在校验中,都算成功。
注意上面 keyLocation 我写的是固定文件名,不是协议默认的 /<密钥>.txt。协议允许用这个字段指定任意地址,只要文件内容和 key 对得上就行。
这么做是有原因的。如果密钥是后台可改的配置项,按默认约定就得整一个根级动态路由(/:key.txt)。而这种路由在不少框架里会退化成通配路由,把 /、/posts 这些正常页面也一并接管掉。我在 Nitro 上就撞过一次,加完路由整站首页直接 404,排查了一会儿才反应过来是它干的。换成固定文件名就没这个问题。
Google Search Console
到 search.google.com/search-console 添加资源,会让你在"网域"和"网址前缀"里二选一。网域需要去 DNS 加 TXT 记录,能覆盖所有子域名和协议;网址前缀支持 meta 标签验证。想用 meta 标签就选网址前缀,它会给你:
<meta name="google-site-verification" content="XXXXXXXXXXXXXXXXXXXX" />
两种方式选一个就行,不用都做。
验证通过后去左侧的 Sitemap,输入框里填 sitemap.xml 提交。因为 Google 没有推送接口,sitemap 就是它发现新内容的主要途径,这一步比另外两家更重要。
顺手把 sitemap 在百度和 Bing 也提交一次,都是一次性操作。百度在「资源提交 → sitemap」,Bing 在左侧「站点地图」。
怎么确认真的推成功了
写完推送代码之后,很容易陷入"到底推没推进去"的迷茫。
最直接的是看自己的日志,但前提是日志得写对。这里有个特别容易犯的错误:
if err := push(urls); err != nil {
log.Warn("推送失败", err)
} else {
log.Info("推送成功")
}
如果 push() 在"没配置凭证"的情况下直接 return nil,上面这段就会在什么都没做的时候打印"推送成功"。你去看日志验证,看到一片绿,实际一条都没推。我自己就写出过这个 bug,而且是靠对比日志字段才发现的。
正确做法是把三种状态显式分开:真的发了请求并被接受、发了但被拒绝、没配置凭证所以压根没发。日志里最好还带上对方返回的实证,比如百度的 success=1 remain=4999,有这个数字才叫真推进去了;被拒绝的话把对方的原话透出来,排查时能省很多事。
第二种是看平台统计。百度那个 API 提交页面有"今日剩余可提交条数",发布前后各看一眼,数字减了就说明推到了。注意它有分钟级延迟,刚推完立刻刷新可能还没变。
第三种是手工 curl 一次,绕开自己的代码直接打接口。如果手工能成而代码不行,那问题在代码里,重点查参数拼接方式;如果手工也失败,那就是平台侧的配置问题。当时我就是靠这一步把范围缩到了 URL 转义上。
还有个概念别混淆:推送成功不等于已经收录。推送只是把网址告诉搜索引擎,收不收、多久收由它自己决定。想查是否已收录用 site:example.com 搜一下,或者看各家平台的索引量工具。
另外几件事
分页和筛选页要 noindex。 ?page=2、?tag=xxx、?sort=hot 这类组合页内容高度重复,全收录只会稀释主列表页的权重。给它们加上:
<meta name="robots" content="noindex,follow">
<link rel="canonical" href="https://example.com/posts">
noindex,follow 是"别收录这页,但请继续跟进这页上的链接",既避免重复内容,又不影响爬虫顺着分页发现深层文章。
推送要异步,而且不能影响主流程。 把推送同步挂在发布文章的接口里,对方接口一卡,你的发布操作就跟着卡。应该立即返回,推送丢后台跑,失败只记日志。如果你的语言里请求上下文会随 HTTP 响应结束而取消,异步推送还得脱离这个上下文,否则响应一返回推送就被连带取消了(Go 里对应 context.WithoutCancel),同时记得另设一个总超时避免协程泄漏。
改了 URL 要新旧地址一起推。 编辑文章导致 slug 变化时,旧地址就变成 404 了。新地址推是为了尽快收录,旧地址推是为了让搜索引擎尽快回来发现它失效,把搜索结果里那条死链清掉。同理,下架或删除文章时也该推一次,否则结果里会长期挂着一条点进去 404 的记录。
开发环境的 robots 屏蔽是正常的。 有些框架的 robots 插件在开发环境会故意输出 Disallow: /,第一次见别以为是 bug,部署到生产才会输出真实规则。反过来更要小心测试环境别被抓到,一旦测试域名被收录,和正式站构成重复内容,清理起来很麻烦。
最后一件和 SEO 没直接关系但更要紧的事。 如果你的域名下还挂着公网能直接打开的自建服务管理面板——容器管理、下载工具、NAS 面板之类——有可能被 Google Safe Browsing 判成"欺骗性内容",因为它看到的是一个索要账号密码的登录框。一旦被标记,Chrome、Edge、Firefox、Safari 都会给访客弹整页红色拦截警告,那个损失比 SEO 优化能带来的收益大得多。这类服务本来也不需要被公网和搜索引擎访问到,别用公网子域名暴露,或者至少在反向代理层加一层 Basic Auth 或 IP 白名单。
顺序
如果从零开始,按这个顺序做比较省事:先把域名收敛到一个并配好 301 和 canonical,再生成 sitemap 和 robots,然后去 Google 验证站点(因为 Bing 可以从这里导入),接着 Bing 加 IndexNow,最后百度验证并接上主动推送。
前两步是地基,做不好后面全打折。真正能立竿见影的是百度推送和 IndexNow,Google 那边把 sitemap 提上去之后就只能等了。

评论 1
可以先写评论,登录后草稿会自动恢复。
非常好