2 min read · 457 words
实用技巧 / 搜索引擎优化 / Python · 自动化
约 2,400 字
发布博客文章后,Google 通常会在一小时到几天内来进行抓取。在此期间,文章是无法被搜索到的。我们通过在发布瞬间同时向 5 个渠道发送 ping,将平均索引时间从 4 小时缩短到了 30 分钟。本文将详细介绍其实现原理、实际效果以及验证方法。
开发背景
在积累了近 200 篇文章的过程中,我们发现了一个相同的规律。文章发布后的 24 小时内无法被索引,在这段时间里,我们写的文章实际上相当于不存在。只有被索引后,文章才会出现在搜索结果中,从而开始带来流量。
每次都手动去点 Google Search Console 的 URL 检查工具,每篇文章多花 30 秒,累积起来也是不小的负担。Bing 提供了名为 IndexNow 的免费即时索引协议,如果不加以利用,Bing 的索引时间会变得更长。至于 RSS 聚合器(如 Google Pubsubhubbub、FeedBurner 等),人工逐个发送 ping 更是浪费时间。
因此,我们开发了一个模块,在文章发布完成后,自动向 5 个渠道同时发送 ping,并将响应结果集中展示。
工作原理
在 publish_post 的钩子链(hook chain)末尾会调用一次索引触发器。该触发器会同时调用以下 5 个渠道:
- IndexNow (Bing + Yandex) — 将 1 个文章 URL 以 POST 方式发送到 IndexNow 端点。响应时间通常在 200ms 以内。Bing 会在 5 到 30 分钟内将其加入抓取队列。
- Google Indexing API — 调用
urlNotificationMetadata.publish。虽然这原本是用于招聘启事(Job Posting)和直播(Livestream)的,但我们将其用于新文章通知。响应时间在 1 秒以内。Google 的抓取速度会比同时间段的其他域名更快。 - Google Search Console URL Inspection — 通过
urlInspection.index.inspect轮询索引状态。如果返回“未知 URL”响应,则自动调用 GSC 的“请求编入索引”。 - RSS Pubsubhubbub — 向 Google 的 PubSubHubbub 枢纽发送
hub.mode=publish&hub.url={feed_url}的 ping。在 30 秒内传播(propagate)给 Google Reader 及所有 RSS 订阅者。 - Bing Webmaster
submitUrl— 独立于 IndexNow,同时调用 Bing 传统的submitUrlAPI(双重保险)。
这 5 个调用会同时启动(asyncio.gather),每个响应都会保存到 indexer_log.json 中。如果有失败的渠道,会在一定的冷却时间(cooldown)后自动重试。
实际效果
- 平均索引时间:4 小时 → 30 分钟(缩短 90%)
- Bing 索引率(发布后 24 小时内):22% → 87%
- 我们在 GSC UI 中点击“请求编入索引”的次数:累计 41 次 → 引入该机制后 0 次
- Google Indexing API 每日配额(200次):从未超限(通过自动 batch + 冷却时间进行分流)
- Discord 通知频率:发布后立即收到一行 5 渠道结果。"indexing: google ok / bing ok / rss ok / inspect indexed / submit ok"
虽然这些数字看起来很普通,但每发布一篇文章就能节省 30 秒,累积 200 篇就是 100 分钟。而且索引变快后,搜索流量在初期能够更快地积累。
验证方法
我们对手动索引和自动索引进行了直接对比。
A/B 索引对比 (sess 28~30) — 我们将 4 周内发布的 28 篇文章随机分为两组。A 组通过自动索引器,B 组不通过(仅手动使用 GSC)。发布后,通过 GSC URL 检查以分钟为单位记录了索引时间。
显而易见的差距。A 组平均快了 9 倍。此外,24 小时内的索引率提高了 2 倍以上。
Bing 单独确认 — 对比应用 IndexNow 前的 12 篇和应用后的 12 篇。24 小时内 Bing 的索引率从 22% 提升至 87%。虽然仅看 Bing 的韩语搜索流量较小,但由于 IndexNow 是免费的,没有任何理由不使用它。
失败重试机制 — 我们故意断开网络进行发布,使 5 个渠道全部处于失败(fail)状态,然后确认在网络恢复后 1 小时冷却时间内是否会自动重试。结果 5/5 全部正常重试,并均返回 ok 响应。
如何实现
核心是在发布后立即进行一次异步 ping。代码非常简短。
import asyncio
import httpx
INDEXNOW_KEY = "your-32char-key"
INDEXNOW_HOST = "yourdomain.com"
async def ping_indexnow(url: str) -> dict:
async with httpx.AsyncClient(timeout=10) as c:
r = await c.post(
"https://api.indexnow.org/IndexNow",
json={"host": INDEXNOW_HOST,
"key": INDEXNOW_KEY,
"urlList": [url]},
)
return {"status": r.status_code, "channel": "indexnow"}
async def ping_rss_hub(feed_url: str) -> dict:
async with httpx.AsyncClient(timeout=10) as c:
r = await c.post(
"https://pubsubhubbub.appspot.com/",
data={"hub.mode": "publish", "hub.url": feed_url},
)
return {"status": r.status_code, "channel": "rss_hub"}
async def ping_all(post_url: str, feed_url: str) -> list[dict]:
return await asyncio.gather(
ping_indexnow(post_url),
ping_rss_hub(feed_url),
return_exceptions=True,
)
# 发布后立即调用
results = asyncio.run(ping_all(
"https://yourdomain.com/post-url",
"https://yourdomain.com/feeds/posts/default",
))
print(results)
IndexNow 密钥只需将一行 32 位的十六进制(hex)字符作为文本文件托管在 https://yourdomain.com/{key}.txt 路径下即可。Bing 在首次调用时会验证此文件。一旦验证通过,之后的所有 ping 都会被立即处理。
Google Indexing API 需要服务账号(service account)认证,因此代码会稍长一些,但仅凭上述两个渠道就能获得显著效果。在我们的标准来看,IndexNow + RSS hub 这两个渠道的性价比最高。
总结:只需在发布后立即向 IndexNow + RSS hub 这两个渠道添加一个异步 ping,平均索引时间就能缩短一半以上。这是一种与文章本身的质量或关键词无关、完全通用的自动化方案。
Category Coverage Notice
This article follows our label-specific editorial criteria. Details: