内容发出去还在等收录:IndexNow 协议与 Bing Webmaster 的即时提交接入规范
适用读者:负责外贸独立站的技术与 SEO 同学,站点跑在 .NET 上,Bing 带来的海外流量不能忽视,想搞清楚 IndexNow(即时索引协议)到底怎么接、接了会不会被判定滥用。
去年 11 月接手一个外贸独立站的技术支持,站点日均上新 30 个 SKU 页,sitemap 每天自动生成一次,但 Bing 的收录中位延迟长期卡在 7 到 14 天。运营负责人老周在周会上原话是:"产品页发出去两个星期,客户拿型号词去搜,连影子都没有,询盘全被同行截走了。"我们把发布链路改造成 IndexNow 推送加 Bing Webmaster API 兜底,今年 3 月拉了四周数据,收录中位延迟降到 26 小时。整个改造后端代码不到 150 行,难点不在写代码,而在协议细节和提交频次的拿捏。这篇文章把接入规范逐条拆开讲。
sitemap 为什么等不来快收录
sitemap 本质上是一份被动提交的 URL 清单。搜索引擎的抓取调度器会周期性读取它,但什么时候真正派爬虫来抓,完全取决于对方的抓取预算(Crawl Budget)分配。对中小体量的独立站,Bing 分配的抓取频次很保守,新页面往往要排好几轮队列。

这里有个容易被忽略的时间结构:sitemap 的更新周期加上调度器的轮询周期,再算上页面质量评估的排队时间,叠加起来就是那 7 到 14 天。你多发一篇产品页,这个延迟不会缩短半分,因为 sitemap 模式下站点对收录时机的干预能力约等于零。
IndexNow 把这个模式倒过来了:页面发布的那一刻,站点主动把 URL 推给搜索引擎端点,爬虫会尽快来抓。一个推、一个拉,时效差距就是这么来的。
IndexNow 协议规范逐条解读
IndexNow 是微软 Bing 和 Yandex 在 2021 年联合发起的开放协议,后来 Naver、Seznam 也加入了。规范本身不长,但每条都有坑,逐条过一遍。
key 文件验证。你要先生成一个 8 到 32 位十六进制字符的 key(比如 a1b2c3d4e5f6),然后把它做成一个文本文件放在站点根目录:https://yourdomain.com/{key}.txt,文件内容就是这个 key 本身,不要带换行以外的任何多余字符。搜索引擎收到提交请求后,会回源拉这个文件,确认提交者真的控制这个域名。一个站点只需要一个 key,子域名可以共用,但协议要求 host 与 key 文件所在域名一致,跨域名提交会被拒。Linux 环境两行命令就能生成并落盘:
# 生成 32 位十六进制随机串作为 key
# openssl -hex 输出正好符合 8-32 字符的协议要求
KEY=$(openssl rand -hex 16)
# key 文件名和文件内容都必须与 key 完全一致
# printf 不带 \n,避免文件末尾换行导致校验差异
printf '%s' "$KEY" > "/var/www/site/$KEY.txt"
# 最后把 KEY 值记录到配置中心,提交端要用同一个值
echo "IndexNow key: $KEY"
提交方式。单条 URL 用 GET 就够,浏览器或 curl 直接访问即可:
https://api.indexnow.org/indexnow?url=https%3A%2F%2Fyourdomain.com%2Fp%2Fsku-123&key=你的key
批量提交用 POST,往 https://api.indexnow.org/IndexNow 发一个 JSON,host 填主域名,keyLocation 可以省略(默认就是根目录 key 文件),urlList 一次最多放 10000 条 URL,报文总大小不能超过 2MB。建议每批控制在 1000 条以内,引擎处理起来更快。api.indexnow.org 是公共端点,提交一次会分发给所有接入协议的搜索引擎;你也可以直接用各家的专属端点,比如 bing.com/indexnow。
响应码语义。这部分官方文档写得比较散,实测整理成表格:
| 状态码 | 含义 | 处理建议 |
|---|---|---|
| 200 OK | URL 已收到并验证通过,进入抓取队列 | 正常,不用重试 |
| 202 Accepted | 请求收到,key 尚未验证,稍后回源验证 key 文件 | 首次提交的正常现象,别当错误重发 |
| 400 Bad Request | 报文格式不合法 | 检查 JSON 结构和 URL 编码 |
| 403 Forbidden | key 文件校验失败,提交被判定无效 | 检查 key 文件内容与 URL 是否一致 |
| 422 Unprocessable Entity | URL 不属于 key 文件所在域名 | 只提交本站 URL |
| 429 Too Many Requests | 提交过于频繁,触发限流 | 退避后降低频次 |
容易踩的规范细节。URL 必须经过 URL 编码;urlList 里不能混入其他域名的链接;key 文件如果被 CDN 缓存了旧内容,会导致 403,建议给 *.txt 这类路径在 CDN 上设置直通源站的缓存规则。我们在 12 月初就栽过一次,Cloudflare 把 key 文件缓存成了上一次部署的旧 key,提交全返 403,排查了一下午。
key 验证的机制拆解
这一节讲原理。IndexNow 的信任模型很朴素:它不搞账号体系,凭证只有一样:"你能控制某个路径下的某个文件"。引擎收到第一次提交时,会先回一个 202,同时异步去拉 keyLocation 指向的文件;拉到的内容与提交里声明的 key 一致,这个 host 才会被标记为已验证,后续提交直接走 200 的快车道。
sequenceDiagram
participant S as 站点(.NET 8 后台服务)
participant E as api.indexnow.org
participant C as 搜索引擎抓取调度器
S->>E: POST urlList + key
E-->>S: 202 Accepted(key 未验证)
E->>S: GET /{key}.txt 回源验证
S-->>E: 返回 key 原文
E->>E: 比对一致,标记 host 已验证
E->>C: 把 URL 注入高优先级抓取队列
C->>S: 爬虫抓取产品页
验证通过之后,之前 202 状态下积压的提交不会丢,会一并入队。这个设计的好处是接入成本极低——不用注册账号、不用 API token——代价是 key 一旦泄露,任何人都能替你提交垃圾 URL 污染你的站点配额。所以 key 文件路径虽然公开,也别在公开仓库里到处贴。
整个推送链路放一张全景图:
flowchart LR
A[商品发布事件] --> B[领域事件: ProductPublished]
B --> C[后台推送服务]
C --> D{提交方式判断}
D -- 单条 --> E[GET 端点提交]
D -- 攒批 --> F[POST 批量提交<br/>urlList 最多 10000 条]
E --> G[200/202 响应]
F --> G
G -- 403/422/429 --> H[记日志+退避重试]
G -- 200 --> I[等待爬虫抓取]
I --> J[Bing Webmaster 后台核对收录状态]
J -- 超过 72 小时未抓 --> K[API 兜底再提交一次]
.NET 8 后台发布事件触发提交
环境说明:.NET 8 Web API 项目,HttpClient 走 IHttpClientFactory 注册,推送逻辑放在一个继承 BackgroundService 的常驻服务里,消费内存通道里的发布事件。依赖只有框架自带的 System.Text.Json,不引第三方包。
// IndexNow 推送服务:消费商品发布事件,攒批后提交
// 放在 BackgroundService 里跑,失败不影响商品发布主流程
public sealed class IndexNowPushService : BackgroundService
{
// 批量上限 10000,实际攒 500 条就发,避免单批过大被限流
// 日均 30 条的量级攒大批纯属浪费等待时间
private const int BatchSize = 500;
private readonly ChannelReader<PublishedEvent> _reader;
private readonly IHttpClientFactory _httpFactory;
private readonly ILogger<IndexNowPushService> _logger;
public IndexNowPushService(
Channel<PublishedEvent> channel,
IHttpClientFactory httpFactory,
ILogger<IndexNowPushService> logger)
{
// 从 DI 容器取通道读取端,事件由发布流程写入
// 构造函数注入即可,不需要手动管理生命周期
_reader = channel.Reader;
_httpFactory = httpFactory;
_logger = logger;
}
// ExecuteAsync 随宿主启动,宿主关闭时通过取消令牌优雅退出
protected override async Task ExecuteAsync(CancellationToken ct)
{
// 用一个缓冲区把短时间内的发布攒成一批
var batch = new List<string>(BatchSize);
// WaitToReadAsync 无事件时挂起等待,不空转占 CPU
while (await _reader.WaitToReadAsync(ct))
{
while (_reader.TryRead(out var evt))
{
// 只推标准产品页,营销落地页走另一条链路
// URL 要完整带上 https 前缀,相对路径会被判 400
batch.Add($"https://shop.example.com/p/{evt.Sku}");
// 攒满一批立刻发出,不等下一个时间窗口
if (batch.Count >= BatchSize)
{
await PushAsync(batch, ct);
// 提交后清空缓冲区,开始攒下一批
batch.Clear();
}
}
// 批未攒满也要发,否则低峰期 URL 会滞留
// 窗口期结束就落一次盘,保证准实时语义
if (batch.Count > 0)
{
await PushAsync(batch, ct);
batch.Clear();
}
}
}
private async Task PushAsync(List<string> urls, CancellationToken ct)
{
// 按协议组装批量报文,host 必须与 key 文件所在域名一致
var payload = new
{
host = "shop.example.com",
key = "a1b2c3d4e5f60718",
urlList = urls
};
// 命名客户端在 Program.cs 里统一配置了 10 秒超时
var client = _httpFactory.CreateClient("indexnow");
var resp = await client.PostAsJsonAsync(
"https://api.indexnow.org/IndexNow", payload, ct);
// 200 与 202 都算提交成功,区别只在 key 是否已验证过
if (resp.StatusCode is HttpStatusCode.OK or HttpStatusCode.Accepted)
return;
// 429 说明触发限流,退避 10 分钟再走重试队列
// 重试任务交给独立的 Hangfire 队列,这里只负责记录
if (resp.StatusCode == HttpStatusCode.TooManyRequests)
_logger.LogWarning("IndexNow 限流,{Count} 条 URL 进入退避队列", urls.Count);
else
// 403/422 多半是 key 文件或域名不匹配,直接告警人工介入
// 这两类错误重试无意义,先修配置再补交
_logger.LogError("IndexNow 提交失败 {Code},批次 {Count} 条",
(int)resp.StatusCode, urls.Count);
}
}
两个实现细节值得说。一是 BatchSize 定在 500 而不是上限 10000,是因为日均 30 条的量根本攒不满大批,攒批窗口一长反而拖慢首条 URL 的时效,实测 5 分钟内的小批提交响应最快。二是不要在 HTTP 请求线程里同步等响应,推送失败不能阻塞商品发布主流程,这也是为什么放后台服务而不是发布接口里顺手调一下。
Bing Webmaster Tools 的 API 和 sitemap 怎么配合
IndexNow 负责增量,Bing Webmaster Tools(BWT)负责全量和可观测性,两条腿缺一不可。BWT 后台先把 sitemap 地址登记好,这是引擎做全量对账的基线;然后在 BWT 的 API 访问页生成一个 API Key,就能调用它的 URL Submission API,每天有单独的配额(普通站点每日数千条),和 IndexNow 的配额互相独立。
| 手段 | 定位 | 时效 | 适用场景 |
|---|---|---|---|
| sitemap | 全量清单,被动等待 | 天级到周级 | 兜底,保证不漏页 |
| IndexNow | 增量推送,事件驱动 | 小时级 | 新发布、内容更新的页面 |
| BWT URL Submission API | 手动/脚本补交 | 小时级 | IndexNow 异常时的兜底重试 |
这里要专门纠正一个流传很广的误解:Google 不支持 IndexNow。协议端点只会分发给接入的引擎(Bing、Yandex、Naver、Seznam),Google 的普通页面收录仍然依赖 sitemap 和 Google Search Console,它自家的 Indexing API 只对职位发布和直播视频开放。所以别指望接了 IndexNow,Google 那边的收录也跟着提速,那是两套体系。
Naver、Seznam、Yandex 共享同一个 key 文件和提交规范,独立站如果做韩国或东欧市场,用公共端点 api.indexnow.org 一次提交就能覆盖这几家,不需要逐家对接,这也是这个协议对中小团队最实惠的地方。
提交频次与滥用风险
协议免费开放,但搜索引擎对滥用毫不客气。官方给的边界是:只提交新增或内容有实质变化的 URL,重复提交没变化的链接、提交已经 404 的页面、用脚本高频轰炸端点,都会触发 429 限流,严重的会拉低整个域名的提交信任度,后续请求被长期降级。
我们自己定的内部基线:单条 URL 从发布到提交至少间隔一次内容变更;批提交每 5 分钟最多一轮;429 之后指数退避,10 分钟、20 分钟、40 分钟,三轮之后进人工队列。上线头两周我们有个bug,商品改一次库存也会触发发布事件,等于同一 URL 一天被推十几遍,Bing 直接回了 429,把事件去重逻辑加上之后才恢复。频次这件事,宁可保守。
误区澄清或趋势预判
两个常见误区先摆平。误区一是"提交了就会收录"——IndexNow 只解决"尽快被抓",抓完之后页面质量评估、去重、排名照旧走搜索引擎自己的流程,低质量页面照样不收。误区二是"key 文件越隐蔽越安全"——key 本来就是公开验证用的,真正的安全边界是别泄露到能被第三方替你提交的程度即可,过度包装没有意义。
再往趋势上看一眼,即时提交这件事对 GEO(Generative Engine Optimization,生成式引擎优化)也有间接价值。AI 爬虫(GPTBot、ClaudeBot 这类)的抓取频次普遍比传统爬虫低得多,新页面进入 AI 语料的窗口期更长;而 Bing 的索引同时是 ChatGPT 搜索引用的数据源之一,IndexNow 把页面送进 Bing 索引的速度提上来,等于顺带压缩了页面被 AI 引擎发现的时间。对以外贸询盘为生的独立站,这个时间差有时就是订单差。
参考与延伸
- IndexNow 官方协议文档(key 规范、提交格式、响应码):https://www.indexnow.org/documentation
- Bing Webmaster Tools 产品与功能入口:https://www.bing.com/webmasters/about
- Bing Webmaster API 官方文档(URL Submission、sitemap 管理):https://learn.microsoft.com/en-us/bingwebmaster/
IndexNow、Bing Webmaster、收录提速、sitemap、独立站SEO、即时提交