IndexNow 是一种告知搜索引擎 URL 内容已更新的简单方式,它是网站端主动发起的,可以使搜索引擎快速响应这一变动。目前微软 Bing 搜索已经支持 IndexNow,Google 搜索对它的态度也是积极的,然后,我站也支持了这个新技术。

IndexNow 需要向搜索引擎提交包含变更 URL 的数据,数据是 JSON 格式的,我的思路是通过 Hugo 生成一个包含新增 URL 列表的 JSON 文件,再将 JSON 通过 cURL 发送给搜索引擎。当然,JSON 模板需要按照 IndexNow 规范来创建,发送方式也得符合 IndexNow 协议。

Hugo JSON 模板我直接使用了 Home Section,因为我没找到让 Hugo 渲染一个自定义 JSON 的方法,也可能 Hugo 不支持。创建 layouts/index.json IndexNow 数据模板,生成的 JSON 文件则在网站根目录下。

{
    "host": "xinlake.dev",
    "key": "72d80bb8d9f645ad9e246e46d336c997",
    "keyLocation": "https://www.xinlake.dev/indexnow.txt",
    
    {{ $index_time := (time now).AddDate 0 -3 0 }}
    "urlList": [
        {{ range where .Site.RegularPages "Type" "blog" }}
        {{ if ge (time .Date) $index_time }}
        "{{ .Permalink }}",
        {{ end }}
        {{ end }}
    ]
}

参考 IndexNow 文档 JSON 需要提供 host、key、keyLocation 等基本内容,host 是网站名称,key 可以在 Bing 生成,然后下载 key 文件放到网站,keyLocation 则是网站 key 文件的地址。

urlList 是变动列表,我设置的是列出最近三个月发布的文章,改时间的话可以参考一下 Hugo .AddDate 文档。这样,生成的 JSON 文件如下(去掉了空行)

{
    "host": "xinlake.dev",
    "key": "72d80bb8d9f645ad9e246e46d336c997",
    "keyLocation": "https://www.xinlake.dev/indexnow.txt",
    "urlList": [
        "https://xinlake.dev/blog/2022/05-voting-script/",
        "https://xinlake.dev/blog/2022/05-private-channel/",
        "https://xinlake.dev/blog/2022/05-blog-v2.2/",
    ]
}

接下来是把 JSON 文件发给 Bing,我这里都是脚本处理的环境就用 cURL 工具,通过 PowerShell 调用 .NET 能力或是写个 Flutter 跨平台应用也都可以。

#cspell: disable
#Requires -Version 5.1
$ErrorActionPreference = "Stop"

$header_host = '"Host: www.bing.com"'
$header_content = '"Content-Type: application/json; charset=utf-8"'
$bing_index = '"https://www.bing.com/IndexNow"'

$data = '"... ... \\index.json"'

Write-Host -ForegroundColor Magenta "Post new URLs to bing ..."
& curl.exe -v --http1.1 --header $header_host --header $header_content --data @$data $bing_index

Read-Host -Prompt "`nCompleted at $(Get-Date), any key to close"

IndexNow 需要走 HTTP POST 发送,同时需要设置 Host、Content-Type 等 HTTP 头,上面脚本就是使用 cURL 将前面 Hugo 生成的 JSON 文件发给 Bing(其实 Bing URL Submission 和 IndexNow 都很接近)。

最后,Hugo 生成的 JSON URL 变更数据通过 cURL 工具向 Bing 发送 IndexNow 请求,及 Bing 的回应大概是下面这样,Bing 搜索引擎回应 HTTP 200 则表示数据提交成功。

*   Trying 202.89.233.101:443...
* Connected to www.bing.com (202.89.233.101) port 443 (#0)
* schannel: disabled automatic use of client certificate
* schannel: ALPN, offering http/1.1
* schannel: ALPN, server accepted to use http/1.1
> POST /IndexNow HTTP/1.1
> Host: www.bing.com
> User-Agent: curl/7.79.1
> Accept: */*
> Content-Type: application/json; charset=utf-8
> Content-Length: 302
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Cache-Control: no-cache
< Pragma: no-cache
< Expires: -1
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< X-Cache: CONFIG_NOCACHE
< Accept-CH: Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version
< X-MSEdge-Ref: Ref A: C9107410449C4D1A837A53C5CB1D392C Ref B: BJ1EDGE0416 Ref C: 2022-06-15T14:11:21Z
< Date: Wed, 15 Jun 2022 14:11:21 GMT
< Content-Length: 0
< 
* Connection #0 to host www.bing.com left intact