---
title: 打破 Google 收录僵局：基于 Astro 与 Indexing API 的增量缓存推送实践
description: 利用 Astro 构建期生成的 sitemap lastmod 时间戳与本地状态缓存，精准推送增量与未收录页面，打破静态博客收录停滞并杜绝配额浪费。
image: "https://zengliangyi.com/og/blog/google-indexing-incremental-cache.png"
---

对于内容更新频繁的独立静态博客，Google Search Console（GSC）中最常见的困局莫过于“已发现 - 尚未编入索引”。爬虫通过 Sitemap 或外链发现了页面地址，但受限于站点初始权重与抓取预算（Crawl Budget），大量长尾文章被排入漫长的等待队列，数周乃至数月未见收录推进。

在 GSC 网页端手动进行“网址检查 -> 请求编入索引”虽然能插队优先抓取，但每日仅有 10–15 次配额，手动复制粘贴低效且不可持续。引入自动化推送是必然选择，但若缺少合理的过滤与增量机制，又会迅速撞上 API 配额墙。本文介绍如何结合 Astro 的构建输出与本地状态缓存，构建一套零配额浪费的增量推送流水线。

## 认识 Google Indexing API 与免费配额上限

Google 官方提供了 [Web Search Indexing API](https://developers.google.com/search/apis/indexing-api/v3/quickstart)，支持开发者主动向搜索引擎通知页面的更新（`URL_UPDATED`）或下线（`URL_DELETED`）。尽管官方文档最初声明该接口主要针对招聘信息（`JobPosting`）与直播活动（`BroadcastEvent`），但在全球 SEO 与开发者实践中，该 API 被广泛证实能够强行唤醒 Googlebot，在数小时至两天内对常规网页发起高优先级的抓取与渲染。

然而，每个 Google Cloud 项目对该 API 的默认免费配额为 **每日 200 次请求**。如果一个站点拥有上百篇文章、加上多语言对照、分页和标签聚合页，总 URL 数量会迅速超过 300 条。如果每次流水线都盲目全量提交：

- 配额瞬间见顶 ：单次构建即触碰 429 报错，排在后面的新文章无法送达。

- 无效重复刷新 ：未曾修改的历史文章重复占用抓取资源，稀释未收录页面的优先级。

- 低质页面抢占预算 ：标签归档页、分页目录等薄内容（Thin Content）消耗了本应留给深度长尾博文的宝贵额度。

## 第一层过滤：剔除聚合噪点，锁定核心内容

在推送前，必须从站点 URL 树中剥离低价值目录。对于基于内容集合（Content Collections）构建的 Astro 博客，核心内容是各语言下的博文与独立项目页：



```javascript
function   isEligibleContentPage  (  url  ) {  
    if   (  !  url)   return   false  ;  
  
    // 排除标签聚合页、列表分页等薄内容  
    if   (url.  includes  (  '/tag/'  )   ||   url.  includes  (  '/page/'  )) {  
      return   false  ;  
    }  
  
    // 严格匹配博文详情页与项目展示页，排除 /blog/ 与 /projects/ 列表主页  
    const   isBlogArticle   =  
      /  ^  https:  \/\/  zengliangyi  \.  com  \/  (?:  [a-z]  {2}  \/  )  ?  blog  \/  [a-z0-9-]  +  (?:  \/  )  ?$  /  .  test  (url)   &&  
      !  url.  endsWith  (  '/blog/'  )   &&  
      !  url.  endsWith  (  '/blog'  );  
  
    const   isProjectPage   =  
      /  ^  https:  \/\/  zengliangyi  \.  com  \/  (?:  [a-z]  {2}  \/  )  ?  projects  \/  [a-z0-9-]  +  (?:  \/  )  ?$  /  .  test  (url)   &&  
      !  url.  endsWith  (  '/projects/'  )   &&  
      !  url.  endsWith  (  '/projects'  );  
  
    return   isBlogArticle   ||   isProjectPage;  
  }
```



通过这一层剪枝，全站几百个 URL 会被收敛为 130 多篇具备完整图文结构的实质页面，从源头确保每次 API 调用都作用于最具搜索价值的长尾资产。

## 第二层比对：读取构建期生成的 sitemap lastmod

如何准确判断一篇文章是否被修改过？文件系统的 `mtime` 在 CI 或容器重新检出时会全部失效，不能作为内容修改依据。

在 Astro Rocket 的内容体系中，核心知识沉淀在 `blog` 内容集合内。构建期通过 `src/content.config.ts` 为博客提供 `publishedAt` 与可选的 `updatedAt`。构建集成（`scripts/article-sitemap.mjs`）解析生产 HTML 头的 `BlogPosting` 元数据，将准确的修改日期注入 `dist/client/sitemap-0.xml` 的 `<lastmod>` 标签中：



```xml
<  url  >  
    <  loc  >https://zengliangyi.com/blog/tailwind-v4-vite-setup/</  loc  >  
    <  lastmod  >2026-10-04T00:00:00.000Z</  lastmod  >  
  </  url  >
```



推送脚本直接解析该 XML 产物，提取每个有效 URL 及其对应的 `lastmod` 字符串。对于拥有确定时间戳的博文，这提供了精准比对的绝对依据；而对于尚未配置 `lastmod` 的展示页面，则由下层的状态缓存提供首次入库与兜底保护。

## 第三层持久化：本地状态缓存与增量决策

我们在本地维护一个轻量级的状态缓存文件 `.indexing-cache.json`（已加入 `.gitignore` 防止凭证与本地状态污染代码库）。该文件记录每个 URL 上次成功推送的时间及当时对应的 `lastmod`：



```json
{  
    "https://zengliangyi.com/blog/tailwind-v4-vite-setup/"  : {  
      "lastmod"  :   "2026-10-04T00:00:00.000Z"  ,  
      "submittedAt"  :   "2026-10-13T07:16:30.000Z"  
    }  
  }
```



在执行推送前，核心比对逻辑如下：



```javascript
const   pending   =   [];  
  
  for   (  const   item   of   allItems) {  
    const   cached   =   cache[item.url];  
  
    if   (  !  cached) {  
      // 1. 从未提交过的新页面或未入库页面  
      pending.  push  ({   ...  item, reason:   'new/unsubmitted'   });  
    }   else   if   (item.lastmod   &&   cached.lastmod   &&   new   Date  (item.lastmod)   >   new   Date  (cached.lastmod)) {  
      // 2. 页面内容修改，更新了 updatedAt / lastmod  
      pending.  push  ({   ...  item, reason:   'updated'   });  
    }   else   if   (  !  cached.lastmod   &&   item.lastmod) {  
      // 3. 历史缓存无 lastmod，本次构建补齐了时间戳  
      pending.  push  ({   ...  item, reason:   'lastmod-attached'   });  
    }   else   {  
      // 4. 无任何变更，跳过  
      skippedCount  ++  ;  
    }  
  }
```



该机制带来了显著的工程优势：

- 首轮平滑过渡 ：初次运行时，脚本按配额提交前 200 条；次日再次运行，自动跳过昨日已入库条目，继续消化剩余未推送内容。

- 日常极速静默 ：日常构建若无文章改动，比对耗时小于 10 毫秒且立即退出，不产生任何网络请求。

- 内容更新即响应 ：一旦某篇文章修正了代码或补充了细节，并在 frontmatter 标记了新的 `updatedAt`，脚本就会在下一次构建后精确锁定并推送这单篇内容。

## 纳入团队与 Agent 规范

自动化脚本的高效运行，高度依赖数据源的真实性。如果开发者或 AI Agent 修改了已有博文却未更新日期，增量流水线就无法感知变更。

因此，我们在仓库治理规范（`AGENTS.md`）中确立了硬性约束：

> Content updates require `updatedAt` : When modifying an existing blog post or project, update or set `updatedAt: YYYY-MM-DD` in its frontmatter. This controls `<lastmod>` in the sitemap and informs SEO indexers of content changes.

将该规则明确沉淀后，日常无论是手工撰写还是 Agent 辅助润色，均会在修改内容时同步校准日期，从而使得“内容修改 -> Sitemap 产出 -> 增量比对 -> Google 爬虫触达”形成全自动的正向闭环。

分享：

##  从文章到代码

到我的 GitHub 看看 ChatCrystal、开发者工具和日常学习记录，欢迎交流实现细节。

[访问我的 GitHub](https://github.com/ZengLiangYi)

```json
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "ZengLiangYi Blog",
  "alternateName": [
    "Zeng Liangyi",
    "ZengLiangYi",
    "zengliangyi.com"
  ],
  "url": "https://zengliangyi.com",
  "description": "曾亮懿的个人网站。记录 AI Native 探索、开发者工具与全栈产品实践。"
}
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "打破 Google 收录僵局：基于 Astro 与 Indexing API 的增量缓存推送实践",
  "description": "利用 Astro 构建期生成的 sitemap lastmod 时间戳与本地状态缓存，精准推送增量与未收录页面，打破静态博客收录停滞并杜绝配额浪费。",
  "url": "https://zengliangyi.com/blog/google-indexing-incremental-cache/",
  "image": "https://zengliangyi.com/images/blog/google-indexing-incremental-cache.svg",
  "datePublished": "2026-10-13T00:00:00.000Z",
  "dateModified": "2026-10-21T00:00:00.000Z",
  "author": {
    "@type": "Person",
    "name": "曾亮懿",
    "url": "https://zengliangyi.com/about"
  },
  "publisher": {
    "@type": "Organization",
    "name": "ZengLiangYi Blog",
    "logo": {
      "@type": "ImageObject",
      "url": "https://zengliangyi.com/favicon-96x96.png"
    }
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://zengliangyi.com/blog/google-indexing-incremental-cache/"
  }
}
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "首页",
      "item": "https://zengliangyi.com/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "文章",
      "item": "https://zengliangyi.com/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "打破 Google 收录僵局：基于 Astro 与 Indexing API 的增量缓存推送实践",
      "item": "https://zengliangyi.com/blog/google-indexing-incremental-cache/"
    }
  ]
}
```
