搜索索引生成自动化 - IndexNow

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

在向 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 里面操作了,想到能自动被抓取就轻松多了。

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

댓글을 불러오는 중...