搜索索引生成自动化 - IndexNow

힘센캥거루
2025년 12월 13일(수정됨)
4
19

在向 Bing 提交站点收录时才发现,Bing 提供了一个叫做 IndexNow 的功能。

核心在于,可以利用 API Key,在写完文章的瞬间就立刻发起索引请求。

搜索索引生成自动化 - IndexNow-1

只要用 fetch 写出类似下面这样的请求,并把它串联到「写文章」流程里,就可以在把文章保存到 DB 的同时发送索引生成请求。

POST /IndexNow HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: api.indexnow.org
{
  "host": "www.example.org",
  "key": "f9ee84af58564dacb6bfe55d808a252c",
  "keyLocation": "https://www.example.org/f9ee84af58564dacb6bfe55d808a252c.txt",
  "urlList": [
      "https://www.example.org/url1",
      "https://www.example.org/folder/url2",
      "https://www.example.org/url3"
      ]
}

于是顺便看了看其他网站的 API,发现 Naver 和 Google 也有各自的 api。

Naver 的站长工具也支持 IndexNow。

除了 host 不同以外,其余元素都完全一样。

所以就决定先用 IndexNow 试试看。

搜索索引生成自动化 - IndexNow-2

1. 什么是 IndexNow?

搜索索引生成自动化 - IndexNow-3

以往的搜索方式,是搜索引擎自动来爬取我的网站,检查是否有更新,然后再进行索引。

如果迟迟没有触发爬取,那就只能干等。

为了解决这个问题登场的技术,就是 IndexNow

搜索索引生成自动化 - IndexNow-4

每当在网站上创建、删除、修改文章时,主动向服务器 push 一次。

只要网站主动发起请求,搜索引擎就会把这些 url 加入索引队列。

2. 支持的搜索引擎

目前支持 IndexNow 的搜索引擎如下。

顺带一提,不同网站的 API host 会稍有差异。

搜索索引生成自动化 - IndexNow-5

Naver 的官方说明可以看下面这个链接。

3. 实现方法

1) 生成 Key 文件

在站点根目录放置 <key>.txt 文件,用来认证站点所有者。

这个文本文件里面只能写一行 key 字符串。

https://example.com/1234567890ABCDEF.txt

2) 向搜索引擎发送 URL 变更

通过 POST 传递如下 JSON。

搜索引擎接收到请求后,会为这些 URL 预约一次快速的重新爬取。

{
  "host": "example.com",
  "key": "1234567890ABCDEF",
  "keyLocation": "https://example.com/1234567890ABCDEF.txt",
  "urlList": [
    "https://example.com/post/123",
    "https://example.com/about"
  ]
}

4. 在 Nextjs 中使用

IndexNow 也有对应的 npm 库,但因为代码本身很简单,就决定自己写一个函数来用。

当然自己写也行,不过让 gpt 或 claude 大哥来写会更漂亮。

反正不是什么大事,就让它们帮忙生成一段,然后认真读一遍就行。

type IndexNowPayload = {
  host: string;
  key: string;
  keyLocation: string;
  urlList: string[];
};

const INDEXNOW_ENDPOINT = "https://api.indexnow.org/indexnow"; // Bing/공용용

export async function submitToIndexNow(
  urls: string[],
  options?: {
    host?: string;
    key?: string;
    keyLocation?: string;
    endpoint?: string; // 필요하면 네이버용 endpoint 등으로 바꿔 쓰기
  }
): Promise<void> {
  if (!urls.length) return;

  const host =
    options?.host ??
    process.env.INDEXNOW_HOST ?? // 예: "earthscience.kr"
    new URL(urls[0]).host;

  const key = options?.key ?? process.env.INDEXNOW_KEY;
  const keyLocation =
    options?.keyLocation ??
    process.env.INDEXNOW_KEY_LOCATION ?? // 예: "https://earthscience.kr/1234567890ABCDEF.txt"
    `https://${host}/${key}.txt`;

  const endpoint = options?.endpoint ?? INDEXNOW_ENDPOINT;

  if (!key) {
    throw new Error("IndexNow key가 설정되지 않았습니다. 환경변수 INDEXNOW_KEY를 확인하세요.");
  }

  const payload: IndexNowPayload = {
    host,
    key,
    keyLocation,
    urlList: urls,
  };

  const res = await fetch(endpoint, {
    method: "POST",
    headers: {
      "Content-Type": "application/json; charset=utf-8",
    },
    body: JSON.stringify(payload),
  });

  if (!res.ok) {
    const text = await res.text().catch(() => "");
    throw new Error(
      `IndexNow 요청 실패: ${res.status} ${res.statusText} ${text ? `- ${text}` : ""}`
    );
  }
}

另外要注意的是,Naver 的 endpoint 不一样,如果连 Naver 也想一起通知,就得 fetch 两次。

现在只要把这段逻辑轻轻挂到「写文章」「修改文章」「删除文章」这些 API 上就可以了。

export async function Post(request: NextRequest){
    
	...

    const post = await createPost({
      title,
      excerpt: excerpt || "",
      content,
      category: category || "기타",
      categoryId: categoryId || null,
      thumbnail: thumbnail || null,
      published: published || false,
    });

    // IndexNow에 새 글 알림 (published인 경우만)
    if (post.published && post.slug) {
      try {
        const postUrl = `${process.env.NEXT_PUBLIC_URL}/post/${post.slug}`;
        await submitToIndexNow([postUrl]);
        console.log('IndexNow 제출 성공:', postUrl);
      } catch (indexError) {
        console.error('IndexNow 제출 실패:', indexError);
        // IndexNow 실패해도 글 발행은 성공으로 처리
      }
    }
	
	...

}

5. 故障排查

在 bing 上能正常提交,但在 Naver 上却总是提交失败。

查了一下发现,在 Naver 那里,设置 host 时必须去掉 https://

需要通过下面这样的步骤,只抽取出真实的 host。

options?.origin ??
process.env.NEXT_PUBLIC_URL ?? // 보통 https://도메인
new URL(urls[0]).origin;

const originUrl = new URL(origin);
const host = options?.host ?? originUrl.host; // ✅ 도메인만

比如需要像下面这样改:

{
  "host": "https://earthscience.kr"  // 会出现 422 错误!
  "host": "earthscience.kr"		 // 这样就能通过
}

6. 使用感受

搜索索引生成自动化 - IndexNow-6

把现在正在写的这篇文章作为测试发布、修改了一下,看起来工作得挺正常。

以后就不用再单独进 bing 或 naver 里面操作了,想到能自动被抓取就轻松多了。

接下来还得再观察一段时间,看看长期效果如何。

관련 글

Next.js 全栈博客开发记
Next.js 全栈博客开发记
在第一次接触网页开发大约 1 年之后,我开始想着想要拥有一个属于自己的博客。于是我就大概花了 6 个月几乎只埋头做这件事。前端部分的功能,参考金度亨先生的博客就已经足够了。我用 mdx 搭建起一个博客,其实连一周都没花到。事实上,仅靠前端也并不会给博客运营带来什么大问题。有一阵子我也觉得,只要写 m...
使用 Caddy 实现 Next.js 无停机部署(本地服务器)
使用 Caddy 实现 Next.js 无停机部署(本地服务器)
每次一有想在主页上加点什么的念头就去 build,结果中间好像偶尔会有人访问。于是 Search Console 上的分数开始一点点往下掉。觉得这样不行,就开始思考要怎么做无停机部署。1. 两个项目文件夹 + 两个终端答案出乎意料地简单:开两个终端。在一个终端里 build,另一个终端里让服务器跑着...
谷歌搜索索引自动化 - Web Search Indexing API
谷歌搜索索引自动化 - Web Search Indexing API
继上次搞完 IndexNow 之后,也决定在谷歌这边做一下自动化。查了一下,发现谷歌是通过一个叫 Web Search Indexing 的 API 来支持这个功能的。1. 适用范围官方文档中,这个 API 正式支持的范围是招聘公告和流媒体视频服务。说是为了给对实时性要求高的内容创建索引用的,但搜了...
被入侵的 Nextjs、React 服务器经历
被入侵的 Nextjs、React 服务器经历
我最初接触到这次安全问题是在 12 月 5 日凌晨。据说在 React 中可以在未认证的情况下进行远程代码执行。看到这条新闻后,我虽然告诉了别人,但总觉得自己应该没事,就什么想法也没有地略过了。1. 发现被入侵的痕迹结果当我想登录更新博客代码时,在终端里发现了有命令被执行过的痕迹。/bin/sh:...
在博客中添加多语言功能(NextJS、next-intl、Vercel AI SDK)
在博客中添加多语言功能(NextJS、next-intl、Vercel AI SDK)
最近我觉得博客需要多语言功能。于是决定用 next-intl 来实现多语言服务。1.i18n首先,在做多语言服务时有一些必须遵守的原则。这被称为 internationalization,单词太长,所以把首字母 i 和尾字母 n,以及中间 18 个字母合在一起,写成 i18n。1) i18n 的原则...
配置 Nextjs 的多语言支持
配置 Nextjs 的多语言支持
为了增加我的博客的访问量,我考虑尝试设置多语言。找到了多种方法,首先的一步是为语言设置不同的路由。决定使用 next-intl 来实现。1. 安装 yarn add next-intl 2. 应用...

댓글을 불러오는 중...