为什么要认真对待必应和 IndexNow
做中文站长的人,注意力几乎都被百度、Google 占满了,必应(Bing)往往被当成「顺手提交一下就行」的次要渠道。但过去两年这个判断需要更新了。一方面,必应在国内桌面端的份额稳定,尤其是 Windows 系统自带 Edge 默认搜索引擎,很多技术类、办公类查询的用户就是从这里进来的;另一方面,也是更关键的——IndexNow 协议正在把「收录」这件事从「等爬虫来」变成「主动推送」,而必应是最早、也是最彻底支持这个协议的搜索引擎。
IndexNow 的核心思想很简单:当你发布或更新了一个 URL,不要再傻等搜索引擎爬虫自己发现,而是直接调用一个 API,把一个或多个 URL「喊」给搜索引擎,告诉它「这些页面变了,快来抓」。这个动作是即时的,通常在几分钟到几十分钟内就能触发抓取。对于新闻、教程、产品页这类「时效性有价值」的内容,主动推送的收录速度和被动等待差着一个数量级。
这篇文章面向个人站长,把必应站长工具的核心功能、IndexNow 的落地写法、以及中文站常见收录问题,从零到可用讲一遍,给出可以直接抄用的脚本。
先搞清楚搜索引擎的收录流水线
在动手之前,必须建立一个准确的模型:搜索引擎处理一个网页,要经过「发现 → 抓取 → 索引 → 排名」四个阶段,每个阶段的瓶颈都不一样,而很多站长把「没收录」笼统当成一个问题,结果优化错了地方。
- 发现(Discovery):搜索引擎怎么知道这个 URL 存在?靠外链、站点地图(sitemap)、内链,或者主动推送(IndexNow)。这一阶段解决的是「知不知道」。
- 抓取(Crawl):爬虫真的来请求这个 URL 了。这一阶段受抓取预算、robots.txt、服务器响应速度、状态码影响。
- 索引(Indexing):抓回来的内容被判断为「值得入库」,写进倒排索引。这一阶段受内容质量、重复度、canonical、noindex 影响。
- 排名(Ranking):入库之后才有资格参与排序,受相关性、权威度、页面体验影响。
必应站长工具和 IndexNow 主要作用在第一阶段(发现)和辅助诊断第三阶段。理解了这一点,你就不会指望「提交了 IndexNow 就一定有排名」——它只是让爬虫早点来,后面的抓取和索引判断还得靠内容和配置本身过关。
必应站长工具:五个必看的报表
登录 Bing Webmaster Tools,把站点验证通过(推荐用 DNS TXT 记录验证,比上传文件更持久,换服务器也不用重做)之后,有五个报表值得每周花十分钟看一眼。
第一个是「站点资源管理器 / Sitemaps」。这里提交你的 sitemap.xml,并查看已发现、已抓取的 URL 数量。如果「已发现」远大于「已抓取」,说明爬虫来了但没抓完,通常是站点响应慢或者内链太深导致的抓取预算浪费。
第二个是「索引资源管理器 / Index Explorer」。这个报表的隐藏功能是「URL 检查」——你可以输入任意一个 URL,看它到底被必应处理成了什么状态:是已索引、已抓取未索引、被 robots 屏蔽、还是 canonical 指向了别处。这是排查单页收录问题最直接的工具,比 Query 各种命令行的感觉强得多。
第三个是「搜索性能 / Search Performance」。展示展现量(Impressions)、点击量、CTR、平均排名,并且可以按查询词、页面、国家筛选。中文站尤其要关注 CTR——如果某个查询词展现量很高但 CTR 极低,说明你的标题和描述没抓住人,优化 meta description 就能立刻见效。
第四个是「抓取信息 / Crawl Information」。这里能看到必应蜘蛛的抓取频率、响应时间、以及抓取错误(4xx、5xx)。如果 5xx 很多,说明你的服务器在面对爬虫时不稳定,这会直接拖慢收录。
第五个是「SEO 报告 / Site Scan」。必应会主动扫描你的站点并给出问题清单,比如标题重复、缺少描述、图片缺 alt、H 标签使用不当。它的判断标准跟 Google 略有不同,值得对照着改。
IndexNow 原理:一次推送,多家共享
IndexNow 最巧妙的设计是「一次推送,多个搜索引擎共享」。它由微软和 Yandex 共同发起,目前必应、Yandex、Seznam 等搜索引擎都接入了同一个端点。你往 api.indexnow.org 推一次,数据会自动分发给所有参与方,不需要分别对接。这大大降低了接入成本。
协议要解决的关键问题是「怎么证明这个 URL 是你的」。做法是密钥验证:你在站点根目录放一个文本文件,文件名叫 {你的密钥}.txt,内容就是密钥本身。然后在推送请求里带上这个密钥,搜索引擎会去请求 https://你的域名/{密钥}.txt,验证密钥一致,就认为你有权推送这个域名下的 URL。
密钥的生成很简单,随便一串 8 到 128 位的十六进制字符就行。比如用 Linux 命令生成:
head -c 16 /dev/urandom | xxd -p
假设得到 a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6,就在站点根目录建一个文件 a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.txt,内容写成同样的字符串。用 Nginx 的话,直接在站点根目录 root 指向的目录里放这个文件即可,注意不要被伪静态规则拦截,确保 curl https://你的域名/密钥.txt 能原样返回纯文本。
从命令行推送单个 URL
IndexNow 的 API 是一个简单的 GET 或 POST 请求。最简形式是 GET,只要 URL 里带上密钥和要推送的地址:
curl -s "https://api.indexnow.org/indexnow?url=https://www.example.com/post/123.html&key=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
返回 HTTP 200 表示推送成功,202 表示「已接收但密钥还在验证中」,403 表示密钥校验失败,422 表示 URL 跟密钥不匹配(比如密钥文件的域名和推送 URL 的域名不一致)。这几个状态码要记牢,排查问题时第一个看的就是它。
但 GET 一次只能推一个 URL,文章多的站点不现实。更实用的是 POST 批量推送,把一堆 URL 打包成 JSON:
{
"host": "www.example.com",
"key": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"keyLocation": "https://www.example.com/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.txt",
"urlList": [
"https://www.example.com/post/101.html",
"https://www.example.com/post/102.html"
]
}POST 到 https://api.indexnow.org/indexnow,Content-Type 设为 application/json; charset=utf-8。这里有个容易被忽略的约束:一次请求里的所有 URL 必须属于同一个 host,而且 keyLocation 的域名也必须跟 host 一致。如果你的站点有 example.com 和 www.example.com 两个域名,混着推会返回 422。解决办法是统一 301 到一个主域名,再统一推送主域名下的 URL。
用 Python 脚本接入发布流程
对个人站长来说,最有价值的做法是把 IndexNow 接进发布流程:每次发完新文章,脚本自动把新 URL 推给 IndexNow。下面是一个可以直接用的 Python 脚本,把要推送的 URL 写进一个列表循环推送,带重试和错误处理:
import json
import time
import urllib.request
HOST = "www.example.com"
KEY = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
ENDPOINT = "https://api.indexnow.org/indexnow"
def submit(urls):
payload = json.dumps({
"host": HOST,
"key": KEY,
"keyLocation": f"https://{HOST}/{KEY}.txt",
"urlList": urls[:10000],
}).encode("utf-8")
req = urllib.request.Request(
ENDPOINT, data=payload,
headers={"Content-Type": "application/json; charset=utf-8"},
)
with urllib.request.urlopen(req, timeout=30) as resp:
return resp.status
if __name__ == "__main__":
new_urls = [
"https://www.example.com/post/201.html",
"https://www.example.com/post/202.html",
]
for attempt in range(3):
try:
print("status:", submit(new_urls))
break
except Exception as e:
print("retry", attempt + 1, e)
time.sleep(5)
把这个脚本放在发布管线的最后一步,参数传新生成的 URL 列表即可。注意几个实践细节:一是不要盲目全量重推,IndexNow 是「增量通知」协议,只推新增或内容有实质更新的 URL,每天把整站几千个 URL 推一遍既没必要也可能被降权;二是推送频率不要过高,同一批 URL 短时间内反复推没有意义,搜索引擎会去重。
中文站在必应上的常见收录问题
第一个问题是中文 URL 或者带参数的 URL 被判断为重复。很多中文站的栏目页 URL 是 ?cat=3&page=2 这种,参数顺序一变、或者带上追踪参数(utm_source 等),必应会当成不同 URL,产生大量重复内容。解决靠 canonical 标签明确指向规范 URL,并在必应站长工具里配好 URL 参数处理规则。
第二个问题是编码声明不统一。中文站最常见的技术债是页面声明 UTF-8 但实际输出 GBK,或者反过来。这会让必应爬虫解出乱码,进而判断内容质量差、不索引。排查方法很简单:curl -sI https://你的域名/某个页面 看 HTTP 头的 Content-Type 里的 charset,再 curl -s 页面 | file - 看实际编码,两者必须一致。这个问题在收录表现上非常典型——「索引了但搜不到」,往往就是编码乱了。
第三个问题是服务器对必应蜘蛛响应不稳定。如果你上了 CDN 或者 WAF,可能会误伤必应爬虫。到必应站长工具的「抓取信息」里看抓取错误率,如果 5xx 偏高,就去 CDN 日志里查必应 IP 段有没有被拦截或限流。必应的爬虫 UA 是 bingbot,官方 IP 段可以在必应文档里查到,正规做法是给爬虫 IP 段加白名单,而不是放行整个 UA(UA 可以伪造)。
验证收录是否真的生效
推送完之后,怎么确认真的被收录了?最靠谱的方式是必应站长工具的 URL 检查功能,输入 URL 看状态。但更自动化一点的做法是用站点的 search 命令验证:
# 在必应搜索框里搜 site:yourdomain.com 看收录量
# 或者用命令行 curl 抓必应搜索结果(注意频率,别被反爬)
curl -s "https://www.bing.com/search?q=site%3Awww.example.com" | grep -o "约 [0-9,]* 条结果" | head -1
注意 site: 查询的收录数是近似值,会波动,不要拿它当精确指标,看趋势就好。真正有价值的是结合「搜索性能」报表:某个新发文章如果在几天内开始有展现量(哪怕 0 点击),说明它已经进入了索引并参与了排序,这才算真正「收录成功」。
小结
对个人站长,必应和 IndexNow 的投入产出比被长期低估。三件事值得立刻做:一是在站点根目录放好 IndexNow 密钥文件并用 curl 验证可访问;二是把 IndexNow 推送脚本接进发布流程,让新文章发布即被通知;三是每周看一眼必应站长工具的抓取错误和搜索性能报表,把「收录」这件事从玄学变成有数据可依的工程问题。
最后提醒一句:IndexNow 解决的是「发现」这个环节,它能显著加快爬虫到场速度,但页面能不能最终被索引、能不能拿到排名,仍然取决于内容质量、canonical 规范、编码一致和服务器稳定性。工具帮你把爬虫请到门口,进不进得来、坐不坐得住,还得看站点本身的底子。