# Yxz Bulk Page Factory

> 游戏站内页批量生产线。把关键词清单/页面矩阵/GSC 补页面清单变成内页清单表，固化一套「内页生成提示词」，分批产出真实内容并批量挂载（config 条目 + 路由 + 导航 + sitemap），最后过防灌水质量闸门（相似度/事实密度/占位符/CJK 残留）。当需要一次铺几十到上百个内页、把单篇内容能力放大成批量产能时调用。是 yxz-game-site-builder / yxz-game-site-template-maker 的下游放大技能。

- Skill: `byte886/yxz-bulk-page-factory` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add byte886/yxz-bulk-page-factory`
- Raw SKILL.md: https://api.skillmd.com/api/skills/byte886/yxz-bulk-page-factory/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: byte886 (https://skillmd.com/u/byte886)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/byte886/yxz-bulk-page-factory

---


# 内页批量生产线 (Bulk Page Factory)

> 来源：生财有术航海《AI 产品（国外-热词游戏站）》关卡 8：批量做内页（进阶）（2026.08.07）
> 实战基线：`your-game-wiki`（Your Game Wiki，17 个内容内页 + 3 个合规页，config-driven JSX 三层模板）

## 核心原则

**批量是放大器，它放大的是你"已经能做好单篇"的能力。**

一个游戏攻略站，首页拿不到多少搜索流量——真正带流量的是大量内页：每个 boss 一篇攻略、每个角色一篇介绍、tier list 一篇榜单、再加 codes 页、guide 页。几十到上百个内页合起来才是站的主力流量来源。

但**批量绝不等于灌水**。批量的本意是"用一套好结构 + 真实内容，把重复劳动省掉"，不是"换个名字复制粘贴"。关键词一换、内容千篇一律，老玩家一眼看穿是水站，Google 判定为低质量批量内容直接降权——**批量出来的反而不如不批量**。

所以这个技能做两件事，缺一不可：

| 做什么 | 怎么保证 |
|--------|----------|
| 把重复的**机械劳动**自动化 | 脚本批量挂载：config 条目、路由文件、导航、sitemap 全自动 |
| 把**内容质量**卡死在门槛之上 | 量化闸门：相似度、事实密度、样板句占比、占位符、CJK 残留 |

**机械部分交给脚本（100% 可靠），内容部分交给 AI 但必须过闸门（可能出错，所以要检）。** 这条分工是本技能所有设计的出发点。

---

## 技能关系

```
yxz-keyword-miner          → 关键词清单 + 页面矩阵 ─┐
yxz-game-info-collector    → 各内页素材文档 ────────┤
yxz-site-data-monetizer    → GSC 补页面清单 ────────┤
                                                    ↓
                                    【yxz-bulk-page-factory】批量铺内页
                                                    ↓
yxz-game-site-template-maker → 模板化后，换个站重复整条生产线
yxz-deploy-pipeline          → 重新部署 + sitemap 重新提交 GSC
```

- **上游（必须先有）**：`yxz-keyword-miner` 的页面矩阵（决定做哪些页）、`yxz-game-info-collector` 的素材文档（决定页里写什么）。
- **上游（可选）**：`yxz-site-data-monetizer` 的补页面清单——GSC 里"有展示但没做页"的词，是优先级最高的批量对象，因为需求已被真实数据验证过。
- **同级依赖**：站点结构必须是 `yxz-game-site-builder` 搭好、最好已被 `yxz-game-site-template-maker` 三层分离过。三层分离过的站，批量成本最低。
- **下游**：铺完内页要走 `yxz-deploy-pipeline` 重新部署，并确认 sitemap 已包含新页。

---

## 开工门槛（先过这道题，再谈批量）

源文档的判断标准，**必须逐条自问，任一条否 → 不要开批量**：

1. **你能稳定地把"一个"内页写成真实、有用、玩家愿意看的内容吗？**
   不能 → 回去把单篇做透。批量掩盖不了内容不行，只会批量生产垃圾。
2. **你对这个游戏足够熟，能判断 AI 写得对不对、有没有瞎编吗？**
   不能 → 先补调研（`yxz-game-info-collector`）。这个前提不成立，批量出来的错误你根本看不出来。
3. **每个待做内页都有对应的素材吗？**
   没有 → **这是编造的唯一源头**。素材缺口 = 生成缺口，宁可少做 10 个页，不做 1 个瞎编的页。

AI 执行本技能时，**第一件事就是把这三条对着项目现状核一遍**，并把结论明确告诉用户。第 3 条尤其要逐页核对，输出"有素材 / 无素材"两栏清单。

---

## 内页是怎么"变出来"的：两种承载形态

源文档描述的是理想形态（MDX 内容目录），但**实战项目常是另一种**。开工前必须先识别，否则脚本挂载会挂错地方。

### 形态 A：config-jsx（`your-game-wiki` 实战采用）

```
site.config.json ── pages.{slug} = { title, description, keywords, h1 }   ← SEO 唯一真相源
app/{slug}/page.jsx ── 引用 pages["{slug}"] 做 metadata，正文在 <article className="prose-game">
site.config.json ── nav.row1 / nav.row2                                    ← 导航
scripts/gen-seo.mjs ── 读 Object.keys(cfg.pages) 自动生成 sitemap.xml + atom.xml
```

**加一个内页 = 3 个动作**：写 `pages.{slug}` 条目 → 建 `app/{slug}/page.jsx` → （可选）加 nav 项。
sitemap 和 SEO 元数据**自动跟随**，一行都不用碰。

### 形态 B：mdx（源文档描述形态）

```
content/
├── en/gelum.mdx          → /gelum
├── en/beginner.mdx       → /beginner
├── ja/gelum.mdx          → /ja/gelum（日文版）
└── ru/beginner.mdx       → /ru/beginner（俄文版）
```

**加一个内页 = 往内容目录多放一个 mdx 文件**，框架自动渲染导航、SEO、面包屑、多语言链接、sitemap。

### 识别方法

```bash
# scaffold_pages.py / dedupe_check.py 都会自动识别，也可手动确认：
# 有 site.config.json 且含 pages 字典 + 有 app/ 目录  → config-jsx
# 有 content/ 目录                                    → mdx
```

> **不要假设**。同一套 `yxz-` 技能做出来的站，模板化前后形态可能不同。让脚本 `--mode auto` 自己判，或先跑一次 `--dry-run` 看它报的 `mode = ...` 对不对。

---

## 前置条件

1. 站点已搭好并能本地构建通过（`yxz-game-site-builder` 第三阶段）
2. 已有页面矩阵文档（`yxz-keyword-miner` 输出）或 GSC 补页面清单（`yxz-site-data-monetizer` 输出）
3. 待做内页**都有对应素材文档**（`yxz-game-info-collector` 输出）；无素材的页先挂起，别硬做
4. Python 3.10+（跑本技能三个脚本）、Node（跑构建与 sitemap 生成）
5. 建议站点已完成三层分离（`yxz-game-site-template-maker`），批量成本最低

---

## 工具与数据获取方式

本技能以**本地文件操作 + 脚本**为主，浏览器只在补素材/核实事实时用。

```
# 读上游文档
Read(file_path="{工作目录}/{日期}-{游戏主词}-页面矩阵.md")
Read(file_path="{工作目录}/{日期}-{游戏主词}-{内页关键词}-素材.md")

# 批量生成与挂载（本技能脚本）
Bash: python scripts/page_manifest.py ... -o manifest.json
Bash: python scripts/scaffold_pages.py {项目目录} --manifest manifest.json --batch N
Bash: python scripts/dedupe_check.py {项目目录}

# 写正文（AI 逐页填充 TODO_CONTENT）
Edit(file_path="{项目目录}/app/{slug}/page.jsx", old_string="...", new_string="...")

# 残留与 SEO 闸门（复用 yxz-game-site-builder 的脚本）
Bash: python validate_site.py {项目目录}/out

# 事实核实（只在素材不足时）
run_mcp: mcp_playwright-extension browser_navigate / browser_evaluate
```

**Windows 注意**：用托管 Python 绝对路径调用，且 `/tmp` 会被解析到当前盘符根目录（如 `E:\tmp`），要用真实临时目录或项目内路径。

---

## 执行流程

### 第一阶段：列出这个站到底要哪些内页

源文档第一步。**一个搜索意图 = 一个内页**，产出一张"内页清单表"，它就是后面批量生产的任务清单。

#### 步骤 1.1：汇总来源

三个来源，优先级从高到低：

| 来源 | 说明 | 为什么优先 |
|------|------|-----------|
| GSC 补页面清单 | 有展示、无对应页的真实搜索词 | 需求已被真实数据验证，转化确定性最高 |
| 页面矩阵 | `yxz-keyword-miner` 规划的页面 | 有搜索量依据，但未经线上验证 |
| 素材反推 | 调研时发现的高频问题（PAA / YouTube 弹幕高赞问题） | 补充长尾，需人工判断值不值得做 |

#### 步骤 1.2：生成清单表

```bash
python scripts/page_manifest.py \
  "20260806-BigWalk-页面矩阵.md" "20260809-BigWalk-补页面清单.md" \
  --game "Big Walk" --exclude-home \
  --existing ./your-game-wiki \
  --batch-size 4 \
  -o manifest.json
```

脚本会：解析所有 markdown 表格（按表头关键词匹配列，列序无所谓）→ 从关键词推 slug（自动去掉游戏名前缀）→ **扫描项目已存在的 slug 标成 `done`** → 按优先级排序 → 给待做页分配批次号。

实测输出（Big Walk）：

```
[ok] manifest.json: 17 pages (1 todo, 16 already built)
  batch 1: tools-items
```

#### 步骤 1.3：人工校清单（必做，别跳）

脚本推的 slug 是机械转换，**必须过一遍**：

- **slug 与实际路由对不上**：如 `Big Walk tools / items` 推出 `tools-items`，但站上已有的是 `tools` → 手动改回 `tools`，否则会重复建页、内容互相打架。
- **两行其实是一个意图**：如 `how to get map` 和 `where to find map` → 合并成一页，别做两个近义页（这正是相似度闸门后面会拦的东西）。
- **补 `question` 字段**：这个页到底要回答什么问题。这是后面生成提示词最重要的输入。
- **确认素材**：给每行标注素材文档路径；**无素材的行直接删掉或标 `status: "blocked"`**。

清单表最终形态（manifest.json 的 pages 数组）：

| 字段 | 含义 | 谁填 |
|------|------|------|
| `slug` | URL 路径 | 脚本推 + 人工校 |
| `type` | 页面类型（攻略页/导航页/角色页…） | 脚本 |
| `keyword` | 对应搜索词 | 脚本 |
| `question` | **这个页要回答什么问题** | 人工/AI |
| `priority` / `batch` | 优先级与批次 | 脚本 |
| `title` / `description` / `keywords` / `h1` | SEO 四件套 | **AI（第三阶段）** |
| `sections` | H2 小节骨架 | **AI（第三阶段）** |

---

### 第二阶段：确认挂载点

在写任何内容前，先确认这个站"多一个内页"到底要动哪些地方——**动错地方会导致页面建了但不被收录**。

```bash
# 先跑 dry-run，只看它识别的形态和将要创建的文件
python scripts/scaffold_pages.py ./your-game-wiki --manifest manifest.json --dry-run --allow-draft
```

确认输出里的 `mode` 正确，且"将创建"的路径符合项目结构。然后核对四个挂载点：

1. **SEO 元数据**：config-jsx 看 `site.config.json > pages`；mdx 看 frontmatter
2. **路由**：`app/{slug}/page.jsx` 存在且能被 Next 识别（不要放进 `[...]` 动态段里）
3. **导航**：`nav.row1/row2`——**不是每个页都要进导航**。核心页进导航，长尾页靠站内链接和 sitemap 就够，导航塞几十个链接反而稀释权重。
4. **sitemap**：确认 `gen-seo.mjs`（或等价机制）读的是 `pages` 而不是硬编码列表。硬编码的话，先改成动态读取，否则新页永远不进 sitemap。

```bash
# 验证 sitemap 是动态的：
grep -n "Object.keys(cfg.pages)" scripts/gen-seo.mjs   # 命中 = 动态，安全
```

---

### 第三阶段：写一份"内页生成提示词"（你的生产线）

源文档第二步，也是整个技能的核心资产。

**别一篇一篇临时想怎么写。** 先固定一套"内页结构 + 写作要求"，写成一份提示词，后面所有同类内页都按它产出——质量和格式才稳定。这份提示词存下来，就是你的内页生产线，换游戏也能复用。

#### 提示词必须包含的三块

| 块 | 内容 | 作用 |
|----|------|------|
| **结构部分** | 一篇内页需要哪些必备信息（按页面族不同） | 保证格式统一、字段不漏 |
| **数据部分** | 素材文档原文（第四关调研产出） | 保证内容有出处，不是凭空生成 |
| **红线部分** | 不准编造、拿不准标待确认、格式规范 | 防幻觉，这是质量底线 |

#### 通用主提示词（所有内页族共用的骨架）

```
你是这个游戏攻略站的内容编辑。基于我提供的素材文档，为下列内页产出内容。

【输入】
- 页面清单行：slug / keyword / question / type
- 素材文档：{粘贴该内页的素材文档全文}

【输出格式】
先输出 manifest 字段（严格 JSON，用于回填 manifest.json）：
{
  "slug": "...",
  "title": "含关键词，≤60 字符",
  "description": "含关键词，140-160 字符",
  "keywords": "≤100 字符，逗号分隔",
  "h1": "用 {gameName} 占位游戏名，不要写死",
  "sections": ["H2 小节 1", "H2 小节 2", "H2 小节 3"]
}
再输出每个 H2 小节的正文，每段 3-4 句，适合扫读。

【结构要求】
1. 开头一句直接回答 question，不绕弯、不铺垫"在这款游戏中……"
2. 分 H2 小节；小节标题必须是玩家会搜的说法，不是文学化标题
3. 全文 500-1200 词（按页面族调整，见下）
4. 至少包含 3 个可验证的具体事实（数值 / 地点 / 物品名 / 版本 / 时间）

【红线（违反即作废）】
1. 忠于这个游戏的真实设定：数值 / 技能 / 打法 / 兑换码一律不准编造
2. 素材里没有的信息，标 "still being confirmed"，不要自行补全
3. 不准写中文（这是英文站）；不准出现 TODO / TBD / Lorem 等占位词
4. 游戏名用 <GameName /> 组件引用，不要硬编码字符串（三层分离原则）
5. 不要复用其他内页写过的句子；每页的开头句、结尾句必须各不相同

【差异化要求（防灌水）】
本批 N 个页面属于同一族。它们的结构可以一致，但：
- 具体事实必须来自各自的素材，不准互相套用
- 不准出现"把 A 的内容换个名字变成 B"的情况
- 每页至少有一个只属于它自己的独特小节
```

#### 按页面族的结构差异

| 页面族 | 必备小节 | 篇幅 | 特别红线 |
|--------|---------|------|---------|
| **boss 攻略** | 阶段拆解（每阶段技能+应对）、推荐配装、常见失误、掉落 | 800-1200 词 | 技能名、伤害数值必须来自素材，绝不推测 |
| **角色页** | 定位与强度、属性/技能、获取方式、搭配推荐 | 600-1000 词 | 强度评价要标明版本，避免过期即错误 |
| **codes 兑换码** | 当前有效码表、失效码表、兑换步骤、更新频率 | 300-600 词 | **只写素材中确认有效的真实码；一个都没有就诚实写"暂无"**，编码是最严重的翻车 |
| **tier list 榜单** | 评级表、评级依据、版本说明、变动记录 | 600-1000 词 | 必须标注数据来源与统计版本 |
| **how-to 攻略** | 前置条件、分步流程、卡关点、验证方法 | 500-800 词 | 步骤必须可复现，顺序不能想当然 |
| **导航/索引页** | 分类索引表、每项一句话说明、指向详情页链接 | 200-400 词 | 篇幅天然短，**质量闸门要单独放宽 `--min-words`** |

#### 把提示词存下来

```
{工作目录}/{游戏主词}-内页生成提示词.md
```

这份文件是可复用资产。换下一个游戏站时，只需替换素材和页面族清单，红线和结构部分原样搬。

---

### 第四阶段：分批生成，逐批过审

源文档第三步。**一次别塞太多，同类几个一批就够，塞多了质量会掉。**

#### 步骤 4.1：确定批次

`page_manifest.py --batch-size 4` 默认 4 页一批。经验值：

- **同族同批**：3-5 个 boss 页一批，AI 能保持结构一致又不至于串味
- **跨族不同批**：boss 页和 codes 页别混在一批，结构差太远
- **首批更小**：第一批只做 2-3 页，用来校准提示词。校准完再放大

#### 步骤 4.2：AI 生成 → 回填 manifest

把主提示词 + 该族结构要求 + 本批各页素材文档喂给 AI，拿到 JSON 字段后回填 `manifest.json` 对应行的 `title / description / keywords / h1 / sections`。

**正文先不写进项目**，先在对话里过一遍。

#### 步骤 4.3：人工过审（源文档要求："每批产出，你自己过一遍"）

逐条检查，**这是批量流程里唯一不能省的人工环节**：

| 检查项 | 怎么查 |
|--------|--------|
| 对不对 | 抽 2-3 个具体事实，回素材文档比对 |
| 有没有编造 | 素材里找不到的数值/名称/码 → 打回或标 still being confirmed |
| 格式对不对 | title ≤60、description 140-160、keywords ≤100 |
| 是不是套模板 | 把本批几页的开头句并排看，雷同就打回重写 |
| 中文泄漏 | 正文里有没有混进中文词 |

**打回重写比放行更省事**——放行的垃圾页会在闸门、构建、收录三个环节反复消耗你。

---

### 第五阶段：批量挂载

审过的批次才挂载。

```bash
# 挂载第 1 批（config 条目 + 路由骨架 + 导航）
python scripts/scaffold_pages.py ./your-game-wiki --manifest manifest.json --batch 1
```

输出示例：

```
[info] mode    = config-jsx
[info] batch   = 1 -> 2 page(s)
[ok] created: 2
  + app\gelum-boss\page.jsx
  + app\codes\page.jsx
[ok] site.config.json pages += 2: gelum-boss, codes
[ok] nav += 1: row2:Gelum
[warn] SEO length (1):
  ! codes: description 10 chars (want 140-160)
```

脚本行为要点：

- **SEO 闸门**：manifest 里 `title/description/h1` 为空的页，**直接拒绝挂载并退出 1**。理由：SEO 字段是页面的搜索契约，没有它就是建了个排不上任何词的路由。确需先建骨架时加 `--allow-draft`。
- **幂等**：已存在的路由文件默认跳过，`--force` 才覆盖。可以反复跑。
- **正文留 `TODO_CONTENT` 标记**，等第 5.2 步 AI 填。
- **自动规避两个致命坑**（见踩坑 1、2）：不写花括号、不把中文字段写进英文站。

#### 步骤 5.2：AI 填正文

逐个打开生成的 `app/{slug}/page.jsx`，用 `Edit` 把 `TODO_CONTENT` 段落替换成第四阶段审过的正文。

- 游戏名一律用 `<GameName />`，不要硬编码
- 保持 `<article className="prose-game">` 容器和 `<h2>` 层级不变
- 列表用 `<ul className="diamond">`，要点提示用 `<div className="note">`（沿用模板既有样式类）
- 收尾的 `<FinalCta />` 建议按页定制 `title/text/href/cta`，指向相关内页，形成站内链接网

#### 步骤 5.3：重新生成 sitemap

```bash
npm run gen-seo          # 或直接 npm run build（prebuild 会自动跑）
grep -c "<loc>" public/sitemap.xml    # 确认条数 = 首页 + pages 数量
```

---

### 第六阶段：防灌水质量闸门（本技能的核心保险）

源文档只给了警告，本技能把它变成**可执行、可量化、能卡住的闸门**。

```bash
python scripts/dedupe_check.py ./your-game-wiki
```

#### 六个指标

| 指标 | 默认阈值 | 不达标意味着 |
|------|---------|-------------|
| `words` | ≥ 400 | 内容太薄，排不上任何词 |
| `facts/100w` | ≥ 1.5 | 全是空话套话，没有可验证事实 |
| `boilerplate` | ≤ 40% | 正文大半是和别的页共用的句子 |
| `todo` | = 0 | 有页面还没填完就想上线 |
| 两页 5-gram 相似度 | < 30% | **"换个名字复制粘贴"，最严重的灌水** |
| 跨页重复句 | 人工看 | 开头/结尾套话，需要改写 |

合规页（about / contact / privacy 等）默认排除——它们为 AdSense 合规而存在，不是内容页，用内容标准衡量纯属噪声。

#### 实测：真实站点（Big Walk，17 个手写内页）

```
slug                              words  facts/100w   boiler  todo
puzzles                             219       11.87       0%     0
achievements                        207       11.11       0%     0
walkthrough                         612        9.97      13%     0
guide                               729        6.45       0%     0
tips                                613        3.75       0%     0

--- most similar pairs ---
  0.130  secret-ending  <>  walkthrough
  0.032  controls  <>  tools
```

最高相似度只有 0.130（secret-ending 与 walkthrough 确实共享结局内容，脚本还列出了具体的 5 条共用句），远低于 0.30 阈值——**这就是健康批次的样子**。

#### 实测：灌水样本（同一段文字只换 boss 名）

```
ERROR (1):
  x gelum-boss <> vael-boss: 72% 5-gram overlap (>= 30%) — same page with words swapped
```

72% 直接判死。**这正是源文档警告的场景，现在它跑不掉了。**

#### 阈值调整

```bash
# 导航/索引页天然短，单独放宽
python scripts/dedupe_check.py ./site --only tools,puzzles --min-words 150

# 构建后查真实渲染产物（比查源码更贴近 Google 看到的）
python scripts/dedupe_check.py ./site --mode html

# 出报告给用户看
python scripts/dedupe_check.py ./site --json 内页质量报告.json
```

#### 串联既有闸门

```bash
NODE_OPTIONS="" npm run build
python /path/to/yxz-game-site-builder/scripts/validate_site.py out --ref-name farever
```

`validate_site.py` 补上本脚本不管的三类：对标站名残留、CJK 泄漏、SEO 长度。
两个脚本都过 = 这批内页可以提交。

---

### 第七阶段：脚本化提效（进阶，跑顺手动流程之后再做）

源文档明确的顺序警告：**先把手动流程彻底跑通，再考虑写脚本提速。脚本只是把"你已经会做的事"加速，救不了"你还不会做的事"。**

新手别一上来折腾脚本——光调通脚本的时间，够你手动铺好几个站。

跑顺之后，值得自动化的环节（按投入产出排序）：

| 环节 | 自动化方式 | 收益 |
|------|-----------|------|
| 挂载（config/路由/导航/sitemap） | 已由 `scaffold_pages.py` 覆盖 | 最高，纯机械 |
| 质量检查 | 已由 `dedupe_check.py` + `validate_site.py` 覆盖 | 高，人眼查不过来 |
| 素材抓取 | 写脚本从 wiki / YouTube 批量抓 boss / 角色数据 | 中，省掉手抄 |
| 内容生成 | 脚本调 API 批量产出并写入目录 | 中，但**必须保留人工过审环节** |
| 批量翻译多语言 | 从 `en` 派生 `ja` / `ru` 等 | 中，前提是英文版已达标 |

> **红线**：无论自动化到什么程度，第四阶段的"每批人工过一遍"不能省。全自动流水线 = 全自动生产垃圾。

---

## 复用脚本

本技能自带三个脚本（`scripts/` 目录），全部在真实项目上实测通过。

### `page_manifest.py` —— 页面矩阵 → 内页清单表

```bash
python page_manifest.py <matrix.md> [more.md ...] --game "Big Walk" -o manifest.json
    [--exclude-home] [--include-types 攻略页,导航页] [--existing <项目目录>] [--batch-size 4]
```

解析任意含管道表格的 markdown（按表头关键词匹配列）→ 推 slug → 扫已建页标 done → 排优先级 → 分批次。

### `scaffold_pages.py` —— 批量挂载

```bash
python scaffold_pages.py <项目目录> --manifest manifest.json
    [--mode auto|config-jsx|mdx] [--lang en] [--batch 1] [--slugs a,b]
    [--nav-row row2] [--allow-draft] [--force] [--dry-run]
```

自动识别承载形态；写 config 条目 / 建路由骨架 / 加导航；SEO 缺失即拒绝；幂等可重跑。

### `dedupe_check.py` —— 防灌水闸门

```bash
python dedupe_check.py <项目目录> [--mode auto|config-jsx|mdx|html]
    [--threshold 0.30] [--min-words 400] [--min-facts 1.5] [--max-boiler 0.40]
    [--only a,b] [--exclude about,contact,privacy] [--json report.json] [--soft]
```

逐页算字数/事实密度/样板句占比/占位符，跨页算 5-gram Jaccard 相似度与重复句。有 ERROR 或 WARN 退出 1。

### 跨技能复用

- `yxz-game-site-builder/scripts/validate_site.py` —— 构建产物残留 + SEO 长度闸门
- `yxz-game-site-template-maker/scripts/new_site.py` —— 换新站时重开一条生产线

---

## 执行要点

1. **先过开工门槛三问**，任一条否就别开批量。这不是形式，是省时间。
2. **无素材不生成**。素材缺口是编造的唯一源头，宁可少做 10 页。
3. **人工校 slug**。脚本推的 slug 与站上已有路由撞车，会建出内容打架的重复页。
4. **一批 3-5 页，首批 2-3 页**用来校准提示词，校准完再放大。
5. **每批必须人工过审**，这是唯一不能自动化的环节。
6. **提示词存成文件**，它是可复用资产，换游戏只换素材和族清单。
7. **导航不要塞满**。核心页进导航，长尾页靠站内链接 + sitemap。
8. **正文用 `<GameName />`**，不硬编码游戏名，否则破坏三层分离、模板化时全部返工。
9. **挂载前先 `--dry-run`**，确认识别的形态和路径对。
10. **两个闸门都要过**：`dedupe_check.py`（灌水）+ `validate_site.py`（残留/SEO）。
11. **铺完必须重新生成 sitemap 并重新部署**，否则新页 Google 看不到。
12. **分批提交 git**，一批一个 commit，出问题好回滚。

---

## 实战踩坑教训

1. **`{{TODO}}` 这类花括号标记会直接炸构建（本技能开发时实测）。**
   在 JSX 里 `{{TODO_CONTENT}}` 被解析成对象字面量 `{ {TODO_CONTENT} }`，引用了未定义变量 → Next 渲染该页时 `ReferenceError: TODO_CONTENT is not defined`，构建失败；MDX v2 同理，`{` 也会开启表达式。
   **对策**：占位标记一律用**不含花括号**的纯文本 `TODO_CONTENT`。它同样能被 `validate_site.py` 的 placeholder 闸门（匹配 `todo`）抓到，但不会破坏编译。`scaffold_pages.py` 已内置此规避。
   > 顺带：SWC 只做语法解析，`{{TODO_CONTENT}}` **能通过语法检查**却在构建渲染期才炸——所以别用"能 parse"当作安全依据，要真跑 build。

2. **中文字段直接写进英文站 = CJK 硬错误。**
   内页清单表的 `页面类型`（攻略页/导航页）和 `解决用户问题` 列都是中文。若脚本把 `type` 当 kicker、把 `question` 当 lede 直接写进页面，`validate_site.py` 的 CJK 闸门会报 ERROR，且线上真的会显示中文。
   **对策**：`scaffold_pages.py` 内置 `KICKER_MAP` 把中文页面类型映射成英文（攻略页→Guide、导航页→Index…），并在 `question` 含 CJK 时自动回退到英文 `keyword`。自己手写页面时同样注意。

3. **slug 机械转换会和已有路由撞车。**
   `Big Walk tools / items` → 脚本推 `tools-items`，但站上已有 `tools`。不校正就会多出一个内容重复的页，两页互相稀释排名。
   **对策**：`page_manifest.py --existing <项目目录>` 会扫描 `site.config.json > pages`、`app/*/page.jsx`、`content/**/*.mdx` 三处标记已建页；剩下的 todo 仍需人工扫一眼。

4. **sitemap 硬编码会让新页永远不被发现。**
   若 `gen-seo.mjs` 里 URL 列表是写死的数组而非 `Object.keys(cfg.pages)`，批量铺的页全都进不了 sitemap，GSC 永远看不到。
   **对策**：第二阶段挂载点核对时用 `grep -n "Object.keys(cfg.pages)" scripts/gen-seo.mjs` 确认是动态的。

5. **合规页会污染质量指标。**
   about / contact / privacy 的事实密度天然极低（实测 contact 1.75、about 2.01，而真实内容页 4-12），拿内容标准衡量它们会刷出一堆假警报，久了就没人看报告了。
   **对策**：`dedupe_check.py` 默认排除这批 slug，需要时用 `--include-all`。

6. **导航/索引页天然短，会误报字数不足。**
   索引页 200 词是合理的（它的价值是链接结构不是正文）。用统一 `--min-words 400` 卡它没有意义。
   **对策**：对索引页单独跑 `--only <索引页 slug> --min-words 150`。

7. **相似度阈值不能一刀切定太低。**
   实测健康站点里，`secret-ending` 与 `walkthrough` 有 0.130 的正常重叠（都讲结局），若把阈值设到 0.10 会误杀合理的内容关联。0.30 是实测下来能区分"合理重叠"与"换名复制"的分界（灌水样本实测 0.72）。

8. **Windows 下 `/tmp` 会被解析到当前盘符根目录。**
   托管 Python 在 Git Bash 里收到 `/tmp/x.json` 会写成 `E:\tmp\x.json`，产生莫名其妙的目录。
   **对策**：用项目内相对路径或真实临时目录（`C:/Users/<user>/AppData/Local/Temp/...`）。

9. **一次塞太多页，AI 会串味。**
   同一批塞 10 个 boss 页，后几页会开始复用前几页的句式和数值，相似度飙升。3-5 页一批是实测甜区。

10. **审核放行比打回更贵。**
    放行的低质页会在质量闸门、构建、GSC 收录三个环节反复消耗时间，最后还是要重写。第一次就打回最省。

---

## 输出文件

执行完成后产出：

1. **内页清单表**：`{工作目录}/{日期}-{游戏主词}-内页清单.json`（manifest，含批次与状态）
2. **内页生成提示词**：`{工作目录}/{游戏主词}-内页生成提示词.md`（可复用生产线资产）
3. **新增内页文件**：
   - config-jsx：`site.config.json` 的 `pages` 新增条目 + `app/{slug}/page.jsx` 若干
   - mdx：`content/{lang}/{slug}.mdx` 若干
4. **质量报告**：`{工作目录}/{日期}-内页质量报告.json`（`dedupe_check.py --json`）
5. **批次记录**：`{工作目录}/{日期}-批量铺页记录.md`

批次记录模板：

```markdown
# 批量铺页记录 - {日期}

## 本次批量
- 游戏主词：{游戏主词}
- 承载形态：config-jsx / mdx
- 清单来源：页面矩阵 / GSC 补页面清单
- 计划页数：X，实际完成：Y，因无素材挂起：Z

## 批次明细
| 批次 | 页面 | 族 | 过审 | 备注 |
|------|------|-----|------|------|
| 1 | gelum-boss, vael-boss | boss 攻略 | 通过 | vael 掉落表标待确认 |

## 质量闸门结果
- dedupe_check：最高相似度 X%，事实密度最低 Y/100w，结论：通过 / 打回
- validate_site：残留 0，SEO 长度告警 X 条

## 挂起清单（无素材，待补调研）
| 页面 | 缺什么素材 | 下一步 |
|------|-----------|--------|

## 下一步
- [ ] 重新生成 sitemap 并部署
- [ ] GSC 重新提交 sitemap
- [ ] 1-2 周后看新页收录情况
```

---

## 常见问题排查

### 新页建好了但访问 404

1. 路由文件名对不对：必须是 `app/{slug}/page.jsx`（不是 `{slug}.jsx`）
2. 静态导出模式下是否需要重新 build：`NODE_OPTIONS="" npm run build`
3. slug 是否含大写或下划线：URL slug 只允许小写字母、数字、连字符

### 新页在站上正常，但 GSC 一直不收录

1. `public/sitemap.xml` 里有没有这条 URL（`grep {slug} public/sitemap.xml`）
2. sitemap 是否重新生成并重新部署（改了 config 不 build 是不会更新的）
3. GSC 里重新提交 sitemap，并用 URL 检查工具对新页做一次"请求编入索引"
4. 参考 `yxz-deploy-pipeline` 的 sitemap 无法抓取诊断流程

### `scaffold_pages.py` 报 "cannot detect content mode"

项目既没有 `site.config.json > pages`，也没有 `content/` 目录。说明站点结构不是本套技能的标准形态：先用 `yxz-game-site-template-maker` 做三层分离，或手动指定 `--mode`。

### 构建报 "XXX is not defined"

正文里残留了花括号表达式（见踩坑 1）。搜一下：`grep -rn "{{" app/`。

### `dedupe_check.py` 报一堆字数不足，但内容其实没问题

先看页面族：索引页/短问答页天然短。用 `--min-words` 按族分别跑，别用一个阈值卡全站。若确实是内容偏薄，回素材文档补事实——**补事实，不要补形容词**。

### 两个页面相似度高，但它们确实是不同意图

说明结构模板套得太死（开头、结尾、小节标题全一样）。保留结构，改写开头句和结尾句，并给每页加一个只属于它的独特小节。若改完仍高于阈值，那大概率这两个意图本来就该合并成一页。

---

## 后续衔接建议

- 铺完一批 → `yxz-deploy-pipeline` 重新部署 + GSC 重新提交 sitemap
- 观察 1-2 周 → `yxz-site-data-monetizer` 看哪些新页有展示、哪些是哑弹，用数据决定下一批铺什么
- 这个站铺顺了 → `yxz-game-site-template-maker` 把整条生产线（模板 + 提示词 + 脚本）打包，换下一个游戏词复制

---

## 免责声明

本技能用于提升内容生产效率，不替代事实核查。批量产出的内容若包含未经核实的游戏数据，可能导致用户误导与搜索引擎降权，责任由发布者承担。涉及第三方游戏的名称、图片、数据时，请遵守对应版权与商标规定，并在站点保留免责与联系渠道。

