# Yxz Game Info Collector

> 游戏攻略站信息调研与素材收集。基于已选定的游戏主词，收集首页开发信息（官方链接/SEO元数据/主题色/多语言/内容JSON）、生成网站图标、多渠道收集内页素材（Google/YouTube/官网），并在交付搭站前做页面语义重叠自检（检出该合并/该拆分的页面，防关键词自噬）。字幕现已支持 AI 自动提取（10808 代理 + youtube-transcript-api，无需插件）；favicon.io 等仍需人工暂停。当需要为游戏站调研信息、收集建站素材、生成首页JSON、做favicon、收集内页攻略素材、检查页面是否语义重复或需要合并时调用。

- Skill: `byte886/yxz-game-info-collector` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add byte886/yxz-game-info-collector`
- Raw SKILL.md: https://api.skillmd.com/api/skills/byte886/yxz-game-info-collector/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Marketing & Growth
- Author: byte886 (https://skillmd.com/u/byte886)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/byte886/yxz-game-info-collector

---


# 游戏信息调研与素材收集器 (Game Info Collector)

## 核心原则

**AI 用于过滤和整理，不用于凭空编造。事实必须来自真实信息源。**

如果直接让 AI 编——它会把不同游戏的信息混在一起，或者编出不存在的人物、兑换码、关卡。Google 一旦发现内容不准确，就不会给你排名。

- 首页信息：事实必须来自官方链接、权威社群，禁止输出 404 / 打不开的链接
- 内页素材：同一信息至少在 **2 个来源交叉验证**，不要只靠一个来源
- 所有收集的信息都放进**一个以关键词命名的文档**，便于后续整理

---

## 前置条件

用户需提供：
- **游戏主词**（已确定的游戏名称，通常由 yxz-hot-word-miner 输出）
- **内页关键词清单**（通常由 yxz-keyword-miner 输出的页面矩阵，含需做素材收集的内页关键词）

> 注：首页信息由 AI 直接用 WebSearch + playwright 浏览器抓取，无需用户准备 ChatGPT。

---

## 工具与数据获取方式

**所有信息由 AI 直接抓取，不依赖 ChatGPT 网页端。** 数据获取优先级：

1. **WebSearch**（首选，快速获取概要）：用于游戏概览、发行日期、Metacritic 评分、新闻报道
2. **`mcp_playwright-extension` 浏览器**（精确数据）：用于 Steam 商店页/官网/YouTube 频道等 JS 渲染或反爬页面
3. **WebFetch**（补充）：playwright 超时时的备选（如官网 CDN 慢）

```
# 导航
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "https://..."})
# 等待加载
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
# 提取页面文本
run_mcp("mcp_playwright-extension", "browser_evaluate", args={"function": "() => document.body.innerText.substring(0, 8000)"})
# 提取页面所有链接（找官网/YouTube/Discord 等官方入口）
run_mcp("mcp_playwright-extension", "browser_evaluate", args={"function": "() => { const links = Array.from(document.querySelectorAll('a')); return links.map(a => ({text: a.innerText.trim(), href: a.href})).filter(x => x.text || x.href); }"})
# 截图（用于主题色判断等需要肉眼判断的场景）
run_mcp("mcp_playwright-extension", "browser_take_screenshot", args={"type": "png", "scale": "css", "fullPage": false})
```

**人工暂停机制（重要）**：遇到需要 Chrome 插件、在线工具（favicon.io）等 AI 无法直接完成的步骤时，**必须暂停等待**。暂停格式：

```
⏸️ 暂停等待人工处理

需要你手动完成以下操作：
1. 【具体动作】打开 xxx / 使用 xxx 插件
2. 【具体动作】...
3. 完成后，把结果（文本/链接/文件）粘贴回来

我会等你处理完后继续。
```

输出暂停提示后**结束当前回合**，等用户粘贴结果回来再继续。不要反复催促或自行编造数据填补。

---

## 执行流程

### 第一阶段：首页信息收集

首页围绕游戏主词，放置游戏整体信息和核心关键词模块。目标是获取网站开发所需的全部基础信息：官方链接、SEO 元数据、主题色、多语言优先级、首页各区块内容。

**AI 直接抓取，不依赖 ChatGPT。** 按以下 5 个子步骤顺序执行。

#### 步骤 1.1：WebSearch 获取游戏概览（快速建立认知）

用 WebSearch 并行搜索游戏核心信息，建立对游戏的基本认知（开发商、发行商、发行日期、Metacritic 评分、核心玩法、平台）。

```
# 推荐并行搜索 2-3 个查询：
WebSearch(query="{游戏主词} game Steam official website release date developer")
WebSearch(query="{游戏主词} game Metacritic score Steam reviews peak players")
WebSearch(query="{游戏主词} official trailer YouTube Discord reddit developer")
```

**输出**：记录开发商、发行商、发行日期、Metacritic 评分、核心玩法描述、平台、是否有官方 Discord/Reddit。

#### 步骤 1.2：playwright 抓取 Steam 商店页（精确数据主力来源）

Steam 商店页是数据最全的单一来源，包含：发行日期、开发商、发行商、价格、评测数与好评率、标签、支持语言、成就数、官方链接（官网/YouTube/Community Hub）、游戏描述。

```
# 1. 导航到 Steam 商店页（用游戏名搜索找到 appid，或直接用户提供 URL）
run_mcp("mcp_playwright-extension", "browser_navigate",
        args={"url": "https://store.steampowered.com/app/{appid}/{游戏名}/"})

# 2. 等待页面加载
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})

# 3. 提取页面全文（含发行日期、开发商、评测、标签、描述、语言等）
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => document.body.innerText.substring(0, 8000)"})

# 4. 提取所有链接（找官网/YouTube/Community Hub/Discord 等官方入口）
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => { const links = Array.from(document.querySelectorAll('a')); const r = {}; links.forEach(a => { const t = (a.innerText||'').trim(); const h = a.href||''; if (t==='Visit the website') r.website = h; if (t==='YouTube') r.youtube = h; if (t==='Community Hub') r.communityHub = h; if (h.includes('discord')) r.discord = h; if (h.includes('reddit')) r.reddit = h; }); return r; }"})
```

**找不到 appid 时**：先 WebSearch "{游戏名} site:store.steampowered.com" 拿到 URL。

**Steam 页被地区/年龄限制时**：⏸️ 暂停，让用户提供 Steam 商店页 URL 或手动复制页面内容。

#### 步骤 1.3：playwright 抓取 YouTube 官方频道（找预告片）

从 Steam 页拿到的 YouTube 链接通常是开发商官方频道。访问频道/videos 页，提取最新视频列表，选**玩法概览类视频**（如 Gameplay Overview / Release Date Trailer）作为首页 videoLabel 链接。

```
# 1. 导航到 YouTube 频道 videos 页
run_mcp("mcp_playwright-extension", "browser_navigate",
        args={"url": "https://www.youtube.com/@{频道名}/videos"})

# 2. 等待视频列表加载（YouTube 懒加载，需等 4-6 秒）
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 5})

# 3. 提取视频列表（标题 + URL）
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => { const links = Array.from(document.querySelectorAll('a[href*=\"watch\"]')).slice(0, 15); return links.map(a => ({title: (a.getAttribute('title') || a.innerText || '').trim().substring(0, 100), url: a.href})); }"})
# 注：ytd-rich-item-renderer 等选择器常失效，直接用 a[href*="watch"] 最稳
```

**选择预告片优先级**：Gameplay Overview > Release Date Trailer > Reveal Trailer > Out Now Trailer。

#### 步骤 1.4：访问官网确认平台与社群（交叉验证）

用 WebFetch 或 playwright 访问官网，确认：游戏支持的所有平台（Steam 页可能只显示 PC）、是否有官方 Discord/Reddit、游戏调性（用于主题色判断）。

```
# WebFetch 优先（官网常是静态页，WebFetch 更快且能绕过部分 CDN 问题）
WebFetch(url="{官网URL}")

# 若 WebFetch 失败，用 playwright（设置更长超时）
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "{官网URL}"})
```

**官网找不到 Discord/Reddit 时**：用 Steam Community Hub 替代作为社群入口（footer.officialDiscord 字段填 "Steam Community Hub"）。

#### 步骤 1.5：AI 构建首页 JSON + 主题色 + 多语言

基于 1.1~1.4 抓取的数据，AI 直接构建首页 JSON。**不要让用户去问 ChatGPT。**

**构建要点**：
- **hero.stats**：选 5 个最贴近玩家直觉的真实数据（发行日期、Metacritic、Steam 评测、玩家数、成就数等），**纯字符串数组**
- **start.cards**：4 张卡片，第 1 张固定 Beginner Guide，后 3 张根据游戏特点选玩家前 2 小时最常搜的内容（参考 yxz-keyword-miner 输出的关键词清单），类型互不重复
- **aboutGame.stats**：label+value 对，含 Developer/Publisher/Platform/Genre/Release Date/Metacritic/Steam Reviews/Players/Crossplay/Achievements 等
- **sidebarCodes**：买断制游戏填"暂无"，有兑换码系统的游戏填 2 条最新码
- **主题色**：根据游戏调性选 HSL 色值（恐怖游戏暗红深紫、童话游戏粉蓝暖黄、户外探险暖橙黄+森林绿、科幻游戏蓝紫），**默认亮色主题**（与多数游戏明亮画面一致）
- **多语言**：按 Steam 支持语言 + 地区热度排，最多 4 门必须有英语，中文除外

**自查校验**（AI 必须逐项核对）：

| 校验项 | 标准 | 不达标处理 |
|--------|------|-----------|
| home.meta.title | ≤ 60 字符 | AI 自动精简 |
| metadata.title | ≤ 60 字符 | AI 自动精简 |
| metadata.description | 140-160 字符 | AI 自动调整 |
| metadata.keywords | ≤ 100 字符 | AI 自动精简 |
| home.hero.stats | 纯字符串数组（不含对象） | AI 自动修正 |
| home.start.cards | 4 个对象 | AI 自动补齐/删减 |
| home.aboutGame.stats | label+value 对 | AI 自动修正 |
| footer.about | 2-3 句介绍 | AI 自动补充 |
| 官方链接 | 全部可打开、无 404 | AI 用 playwright 抽检 1-2 个验证 |

**链接抽检**：AI 用 `browser_navigate` 访问官网 / YouTube 链接，确认非 404。playwright 超时不一定是 404（可能是 CDN 慢），改用 WebFetch 二次验证。

校验通过后，保存为 `{日期}-{游戏主词}-首页信息.md`（含 JSON 代码块 + 主题色 + 多语言优先级 + 链接抽检结果 + 自查校验表）。

---

### 第二阶段：网站图标（Favicon）生成

#### 步骤 2.1：AI 直接生成 favicon 图标（默认方式）

AI 直接调用 `GenerateImage` 工具生成 favicon，无需用户介入。

**prompt 构建要点**（基于第一阶段获取的游戏调性）：
- 描述游戏核心元素（如 Big Walk 是合作户外探险 → 用脚印/地图/对讲机等元素）
- 贴近游戏调性的配色（恐怖游戏暗红深紫、童话游戏粉蓝暖黄、户外探险暖橙黄+森林绿、科幻游戏蓝紫）
- 简洁图标风格（favicon 尺寸小，避免复杂细节），扁平化/极简风
- 明确用途："Website favicon icon for {游戏名} fan wiki, 512x512, flat icon style, centered, simple background"

```
GenerateImage(
  prompt="[Website favicon icon]: {基于游戏调性的具体描述}",
  path="{工作目录}/{游戏主词}-favicon",
  image_size="square_hd"  # 1024x1024，高清方形，favicon.io 会自动转多尺寸
)
```

**生成后**：AI 自动记录图片路径，供步骤 2.2 使用。

#### 步骤 2.2：加工成各种格式（人工暂停）

⏸️ **此步骤必须人工处理**——需要用在线工具转换图标格式（AI 无法直接生成 .ico 等多格式压缩包）。

向用户输出暂停提示：
1. 打开 https://favicon.io/favicon-converter
2. 上传步骤 2.1 AI 生成的 favicon 图标（路径：`{工作目录}/{游戏主词}-favicon.png`）
3. 下载压缩包（内含各种尺寸 png + 桌面/移动格式）
4. 把压缩包解压后的文件路径告诉 AI，AI 记录位置供后续编程工具使用

---

### 第三阶段：内页素材收集

内页承接具体游戏细分关键词的搜索需求（如 `{游戏名} classes`、`{游戏名} codes`）。**同一信息至少在 2 个来源交叉验证**。

对关键词清单中的**每个内页关键词**，依次执行 3 个来源的素材收集，全部汇总进一个以该关键词命名的文档。

#### 步骤 3.1：Google 搜索收集（AI 可自动完成）

用浏览器搜索内页关键词，找到排名前二的网页，提取内容。

```
# 1. Google 搜索内页关键词（如 "farever classes"）
run_mcp("mcp_playwright-extension", "browser_navigate", args={
  "url": "https://www.google.com/search?q={内页关键词URL编码}&hl=en&num=10"
})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})

# 2. 提取首页结果（域名 + 标题）
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => document.body.innerText.substring(0, 4000)"
})
# 从文本中识别排名前二的攻略/Wiki 页面 URL
```

**提取前二网页内容**：
```
# 逐个访问排名前二的页面，提取正文
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "{页面URL}"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => { const main = document.querySelector('article, main, .content, .post-body, #mw-content-text') || document.body; return main.innerText.substring(0, 8000); }"
})
```

**Google 搜索 IP 被标记对策**：若出现 429 + /sorry/ 重定向，⏸️ 暂停提示用户切换网络环境（更换 IP / 关闭代理 / 使用移动热点）后重试。**不要降级到 Bing**——Google 才是主要流量来源。

**提取失败对策**：若页面内容被反爬 / JS 渲染拿不到正文，⏸️ 暂停提示用户手动复制网页内容粘贴回来。

将两个网页提取的内容，按来源标注后放入关键词文档的「Google 搜索」区块。

#### 步骤 3.2：YouTube 字幕收集（AI 自动选视频 → 交叉校验 → 自动提取 → 回填文档）

**全程 AI 自动完成，无需 Chrome 插件、无需人工暂停**。四阶段：3.2a 搜视频 → 3.2b 主题匹配度校验（防选错）→ 3.2c 自动提取字幕（10808 代理 + youtube-transcript-api）→ 3.2d 回填文档关联。

##### 3.2a：AI 自动搜索筛选 YouTube 视频（AI 可自动完成）

用 WebSearch + playwright 搜索 YouTube，找与内页关键词相关的视频，按相关度+时效+观看量排序，列出 **5-8 个推荐视频**（第 1 个为「唯一必填」，由 AI 自动选定并脚本化提取字幕；其余作候选参考，唯一必填字幕缺失/质量差时从中替换，实现视频内部交叉验证）。

**关键：按内页关键词类型差异化搜索查询**（不同类型关键词用不同查询，避免推荐列表雷同）：

| 关键词类型 | 搜索查询示例 | 优先推荐视频类型 |
|-----------|------------|---------------|
| 通用技巧类（tips/beginner/guide） | `"{游戏名}" tips guide` / `"{游戏名}" beginner how to` / `"{游戏名}" gameplay co-op` | 评测类、实况类、官方玩法概览 |
| 流程顺序类（tower order/walkthrough/best route） | `"{游戏名}" walkthrough playthrough` / `"{游戏名}" ending complete full game` / `"{游戏名}" speedrun` | ⭐速通类、完整结局类、100%流程类（必然含实际通关顺序） |
| 位置收集类（locations/where to find/map） | `"{游戏名}" all locations` / `"{游戏名}" collectibles guide` / `"{游戏名}" 100% guide` | 收集类、100%流程类、地图展示类 |
| 角色职业类（classes/best build/skills） | `"{游戏名}" best build` / `"{游戏名}" class guide` / `"{游戏名}" skills tier list` | 角色解析类、Build 推荐类、Tier list 类 |
| 兑换码类（codes/redeem） | `"{游戏名}" codes 2026` / `"{游戏名}" active codes` / `"{游戏名}" redeem code` | 兑换码汇总类（通常是最新视频） |

```
# 方式 1：WebSearch 搜索 YouTube 视频（首选，快速）
WebSearch(query="site:youtube.com {按关键词类型选择的查询1}")
WebSearch(query="site:youtube.com {按关键词类型选择的查询2}")  # 补充搜索

# 方式 2：playwright 直接访问 YouTube 搜索页（WebSearch 结果不足时用）
# 按观看量排序 sp=CAMSAhAB
run_mcp("mcp_playwright-extension", "browser_navigate", args={
  "url": "https://www.youtube.com/results?search_query={查询URL编码}&sp=CAMSAhAB"
})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 4})
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => { const items = Array.from(document.querySelectorAll('ytd-video-renderer, ytd-rich-item-renderer')).slice(0, 15); return items.map(v => { const link = v.querySelector('a#video-title, a[href*=\"watch\"]'); const title = v.querySelector('#video-title, yt-formatted-string#video-title'); const meta = v.querySelector('#metadata-line, .inline-metadata'); return { title: title ? title.innerText.trim() : '', url: link ? link.href : '', meta: meta ? meta.innerText.trim() : '' }; }).filter(x => x.title && x.url); }"
})

# 方式 3：多查询补充（结果不足 5 个时用）
# 按上方映射表换不同查询再搜，把多个查询的结果合并去重，按观看量排序取前 5-8 个
```

**筛选标准**（按相关度+时效+观看量排序）：
1. **标题相关度**：视频标题包含内页关键词核心词（如 "tips" / "tower order" / "speedrun"）
2. **时效性**：游戏发售后的视频优先（发售前的视频多为预告/前瞻，无实际攻略价值）
3. **观看量**：优先观看量较大的视频（通常质量更高）
4. **视频类型**：按关键词类型优先推荐对应类型（见上方映射表），攻略类 > 实况类 > 评测类 > 预告片
5. **多样性**：尽量覆盖不同创作者、不同玩家数视角（2人/4人/7人等），便于交叉验证

**输出格式**（每个文档的「YouTube 字幕」区块先写候选表，标注唯一必填）：

```markdown
## 来源 2：YouTube 字幕

> ✅ **本页推荐字幕视频（唯一必填）**
> - 标题：**{标题}**
> - URL：{URL}
> - 匹配理由：{为什么该视频最契合本页主题}

### AI 推荐视频（按相关度排序，第 1 个为唯一必填，其余作候选参考）

| 序号 | 视频标题 | URL | 时长 | 推荐理由 | 匹配度 |
|------|---------|-----|------|---------|-------|
| 1 | {标题} | {URL} | {时长} | {理由} | ⭐⭐⭐ 必填 |
| 2 | {标题} | {URL} | {时长} | {理由} | ⭐⭐ 候选 |
| ... | ... | ... | ... | ... | ... |
```

> 说明：每页只**必填 1 个**字幕视频（降低工作量），其余候选作补充参考；若该视频字幕缺失/质量差，可从候选替换。

**「视频内部交叉验证笔记」区块模板**（紧跟在 AI 推荐视频表之后，3.2b 第 3 点所引用的「交叉验证笔记」即指此块）：

```markdown
### 视频内部交叉验证笔记

- **必填选定理由**：选视频 1（{标题}）而非候选 {序号/标题} —— {原因，如"1 是专门教程、候选是实况闲聊信息密度低；或 1 直击本页关键词、候选偏泛"}。
- **事实一致性**：{本页核心事实 A} 在视频 1 与候选 2 中均出现 → 可信，可写入正文；{事实 B} 仅视频 1 提及、候选无佐证 → 标注"单源，待官方/文字来源补证"，勿当定论。
- **字幕质量结论**：必填字幕 _（过关 / ⚠️ 质量差）_。若 ⚠️，已从候选 {序号} 替换（新 ID：{ID}）/ 或保留并标注"字幕稀疏，正文以文字来源为主"。
- **遗留缺口**：{无 / 候选均未覆盖的点 → 转入 Google/官网来源补证}。
```

> 模板要点：交叉验证不是"再提一遍字幕"，而是**留下可追溯的选型依据 + 事实可信度分级**。事实分三档：多视频一致（可信）、单视频提及（单源待补）、候选均无（缺口转其他来源）。

##### 3.2b：视频-页面主题匹配度交叉校验（防选错视频，AI 可自动完成）

为每个内页选定 1 个「唯一必填」视频后，**必须做匹配度校验**，避免选错视频：

1. **标题主题校验**：必填视频标题应直击本页关键词核心（如 beginner-guide 页选标题含 "Beginner Guide" 的视频；how-to-revive 页选含 "Spark/Revive/Recovery" 的视频）。若必填视频标题与页面主题弱相关，改选候选表中更贴切者。
2. **字幕内容校验（强校验，推荐）**：提取字幕后，用页面主题关键词 grep 字幕原文（见 3.2c），命中数应 > 0。若命中为 0，先排除「口语化表达」假阴性（如 co-op 视频用 "we/us/guys/body" 而非 "co-op/multiplayer"），再确认视频内容是否真的契合；仍不契合则换候选。
3. **候选对比说明**：在文档「交叉验证笔记」里写明「为何选视频 N 而非候选 M」（如 M 是实况、N 是专门教程），留下可追溯依据。

> 校验实例：co-op-guide 页选定 8v2IVi4SM-Q「Co-Op Horror Meets Extraction」，字幕关键词 co-op/multiplayer 命中 0，但逐读字幕确认是 4 人好友联机实况（"I'll get you a body" / "let's go down" / 大量笑声），属口语化假阴性，校验通过。

##### 3.2c：自动提取字幕（本机代理 + youtube-transcript-api，无插件）

**为什么需要代理**：Bash 沙箱直连 YouTube 超时；playwright 浏览器虽能访问 YouTube，但 YouTube 对 `api/timedtext` 接口做了反爬（fetch/导航均返回 200 空响应或重定向）。突破口：本机通常有代理软件（V2RayN/Clash 类）监听本地端口（实测 **127.0.0.1:10808**），WorkBuddy 托管的 Chromium 也走它才能访问 YouTube。Python 走该代理即可直连 YouTube 提取字幕。

**方法（纯 Python，零插件）**：

```python
import os
# 关键：让 youtube-transcript-api 走本机代理（端口按本机实际调整，常见 10808/7890/1087）
os.environ['HTTPS_PROXY'] = 'socks5://127.0.0.1:10808'
os.environ['HTTP_PROXY']  = 'socks5://127.0.0.1:10808'
from youtube_transcript_api import YouTubeTranscriptApi

def fetch_one(vid):
    api = YouTubeTranscriptApi()
    # 优先中文字幕，其次英文（多为自动生成 asr）
    for langs in (['zh-Hans','zh-CN','zh','en'], ['en']):
        try:
            return api.fetch(vid, languages=langs), langs[0]
        except Exception:
            continue
    raise RuntimeError('no transcript')

t, lang = fetch_one('{VIDEO_ID}')
text = '\n'.join(s.text for s in t.snippets)
print(lang, len(t.snippets), 'segments')
```

- 依赖安装（隔离 venv）：`python -m venv env && env/Scripts/pip install youtube-transcript-api pysocks`
- 代理端口探测：脚本可先扫描 `7890,7891,7892,1080,1087,10808,8080,8118,8888` 等常见端口，命中开放的即作为代理。
- **语言现实**：绝大多数英文游戏视频**只有英文（自动 asr）字幕，无中文字幕轨道**。若 `fetch` 中文字幕失败、英文成功，如实记录「无官方中文字幕，以下为英文自动字幕」，不要编造中文。
- 视频禁用字幕时 `fetch` 抛 "Subtitles are disabled"，该视频标记「字幕缺失」，换候选或填「跳过」。

**配套脚本（位于技能 `scripts/` 目录，通用、无需改任何代码）**：

- `extract_subs.py`：扫描当前目录所有 `*-素材.md`，从「✅ 本页推荐字幕视频（唯一必填）」块**自动解析视频 ID**，经本机代理提取，输出 `subs/<素材文件名去扩展名>_<lang>.txt`。**提取后自动跑字幕质量闸门**：若 >40% 片段为 `[ __ ]` 消音/空白标记，打印 ⚠️ 预警提示换候选视频。用法：`python extract_subs.py [--dir <素材目录>]`。
- `inject_subs.py`：扫描 `*-素材.md`，把 `subs/` 下对应字幕回填进文档的 `{视频字幕文本}` 占位符（无对应字幕文件则填「字幕缺失」说明）。用法：`python inject_subs.py [--dir <素材目录>]`。
- `verify_videos.py`：扫描 `*-素材.md`，对每个「唯一必填」视频用 YouTube oEmbed 拉取真实标题/频道，与文档声称比对；标题不符或 ID 失效标红，并检测跨页复用。用法：`python verify_videos.py [--dir <素材目录>]`（依赖 requests，走本机代理）。
- `verify_consistency.py`：跨文档页数一致性闸门——校验「素材文档数 = 素材页面集合数 = 含必填视频页面数 = --matrix/--wiki/--summary 文档列出的页面集合」，任一不一致即报错并打印漂移明细。用法：`python verify_consistency.py --dir . [--matrix 页面矩阵.md --wiki wiki-素材.md --summary 素材完成汇总.md]`。
- 运行环境：用隔离 venv `python -m venv env && env/Scripts/pip install youtube-transcript-api pysocks requests`，随后 `env/Scripts/python scripts/<脚本> --dir .`。脚本会自动探测代理端口，无需手动指定。

##### 3.2d：字幕回填文档并关联（AI 可自动完成）

提取成功后，把字幕原文回填进对应文档的「字幕」区块，并标注语言、段数、完整原文文件相对路径。文档内保留完整原文（或前若干段 + 指向 `subs/` 全文），供后续撰写引用。回填可由配套 `scripts/inject_subs.py` 自动完成。目标文档结构示例：

```markdown
## 字幕

> **字幕（脚本自动提取，无插件参与）**：本视频无官方中文字幕轨道，以下为 **英文自动字幕**，共 {N} 段，完整原文见 `subs/subs_{page}_en.txt`。

{字幕原文前若干段；完整见 subs/ 文件}
```

> 回填后，AI 从字幕提取关键内容（玩法要点/数据/流程），与 Google/官网源交叉验证，填入「视频内部交叉验证笔记」。原始字幕与提取要点都保留。

#### 步骤 3.3：访问游戏官网 / Steam 页面（AI 可自动完成）

搜索游戏官网或 Steam 商店页，找该内页关键词相关的官方说明。

```
# 1. Google 搜游戏名找官网/Steam链接
run_mcp("mcp_playwright-extension", "browser_navigate", args={
  "url": "https://www.google.com/search?q={游戏名URL编码}+steam&hl=en"
})
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => document.body.innerText.substring(0, 3000)"
})

# 2. 访问官网/Steam页面，找内页关键词相关说明
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "{官网或Steam URL}"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => document.body.innerText.substring(0, 6000)"
})
```

**判断是否需要复制**：
- 若官网/Steam 页有该内页关键词的重要说明（如 classes 列表、codes 列表）→ 提取放入文档
- 若信息很少（如只有 4 classes 无其他说明）→ 不用复制，直接跳过

#### 步骤 3.4：汇总内页素材文档

每个内页关键词的素材文档结构：

```markdown
# {内页关键词} 素材收集

> 游戏主词：{游戏主词}
> 收集日期：{日期}
> 对应页面类型：{攻略页/导航页/物品页等}

## 来源 1：Google 搜索

### 网页 1：{标题} - {URL}
{提取的正文内容}

### 网页 2：{标题} - {URL}
{提取的正文内容}

## 来源 2：YouTube 字幕

### 视频：{视频标题} - {URL}
{原始字幕文本}

### 关键内容提取
{AI 从字幕提取的要点}

## 来源 3：官网 / Steam

### 页面：{标题} - {URL}
{相关说明内容，或标注"信息较少，跳过"}

## 交叉验证笔记
{同一信息在多个来源出现的，标注一致性；有冲突的，以官网为准}
```

保存为 `{日期}-{游戏主词}-{内页关键词}-素材.md`。

---

### 第四阶段：页面语义重叠兜底复核（交给 game-site-builder 之前必跑）

> ⚠️ **合并的主检查点不在这里，在上游 `yxz-keyword-miner` 第 3.5 步「意图聚类与页面合并闸门」**（SERP 重叠 / 实体计数 / 机制适配 / 反向拆分）。
>
> 实体数量与游戏机制在**规划期查一次 Steam 就能拿到**，重复页应当在画矩阵时就被合并掉。等素材收完再合并 = 白收一份素材、白挑一个视频、白提一份字幕。
>
> **本阶段是兜底复核**，覆盖两种情况：① 矩阵是在合并闸门上线前规划的（历史项目）；② 素材收集中发现了规划期不掌握的新事实（如攻略站列的实体数与实际不符）。若矩阵头部已标注「合并闸门：已跑」，本阶段仍要跑，但通常只需确认无新增重叠 + 检查视频跨页复用。

素材收完照旧矩阵直接搭站，会产生重复内容与关键词自噬。

#### 步骤 4.0：跑一致性闸门（视频 + 页数，先于重叠检测）

避免 GRAIN ROT 踩过的两个坑——视频标题写错、四份编排文档页数各自漂移：

```bash
# 视频 ID ↔ 真实标题/频道 一致性（oEmbed），并检测跨页复用
python scripts/verify_videos.py --dir "{素材目录}"
# 跨文档页数一致性：素材文档数 = 页面集合数 = 含视频页数 = 矩阵/wiki/汇总列出的页面集合
python scripts/verify_consistency.py --dir "{素材目录}" \
  --matrix 页面矩阵.md --wiki wiki-素材.md --summary 素材完成汇总.md
```

任一脚本退出码非 0（有标题不符 / ID 失效 / 页数漂移）→ 先修再进下一步。

#### 步骤 4.1：跑重叠检测脚本

```bash
python scripts/check_overlap.py --dir "{素材目录}" \
  --extra-stopwords "{游戏名各词},{开发商},{发行商},{引擎}"
```

脚本输出三块：各页正文体量与来源数（剔除字幕后计算）、两两术语 Jaccard + 共享来源数、必填视频跨页复用检测。

`--extra-stopwords` 必须传，否则游戏名、开发商名会被算成"共享术语"抬高所有页面的相似度。

#### 步骤 4.2：人工研判（脚本只定位嫌疑，不下结论）

**决定是否合并的首要依据是「游戏本身的实体数量」，不是 Jaccard 数字。** 判定顺序：

1. **数实体**：这个主题下游戏里到底有几个实体？（几种角色、几张地图、几把武器）
   - **少于约 8 个 → 导航页 + 详解页必然重复，合并成一页**
   - 导航页的存在前提是"条目多到需要索引"，4 个条目让用户多点一次纯属多余
2. **查生成方式**：地图/关卡是不是程序化生成？
   - 程序化生成 → **不存在"地图坐标索引页"**，地图只做一页（讲空间结构与功能点类型）
3. **看搜索意图是否独立**：
   - 意图独立且明确的问答型页（`is X crossplay` / `X controller support`）→ **保留独立页**，即使内容薄。Google 对这类问题偏好直答页，合并会丢精准词
   - 意图重叠（两页都在回答"有哪些角色"）→ 合并
4. **反向检查该拆的页**：有没有一页混装了多类独立搜索需求？
   - 典型：`update` 页常混装「版本日志」与「崩溃/黑屏/闪退修复」，后者是独立高需求长尾词（`{游戏} crash fix` / `not launching` / `black screen`），**应拆出 `/troubleshooting` 独立页**
   - 新游戏发售初期，故障修复类词的搜索量往往高于 patch notes 本身

Jaccard 高但不该合并的情况（**共享游戏术语背景**，不是意图重复）：各攻略页天然都会提到同一批机制名词。这类**不合并，改为划定内容边界**——按"用户处在哪个阶段"切分，每页只写自己那段，其余改内链。

#### 步骤 4.3：处理视频跨页复用

同一视频的字幕会以大段相同文本出现在多个页面，直接制造重复内容。脚本第三块报出的复用组必须逐个替换，每页一个专属视频。

#### 步骤 4.4：产出调整方案并回写矩阵

产出 `{日期}-{游戏主词}-页面语义重叠分析.md`，含：量化结果表、每组合并/拆分的判定依据与合并后页面结构、内容边界划定表、视频替换清单、最终页面清单、执行清单。

**务必同步回写**：`页面矩阵.md`（页数与页面列表）+ `wiki-素材.md` 的全站导航结构（去掉被合并的条目、加上新拆的页），否则搭站时会按旧矩阵生成已废弃的页面。

---

## 执行要点

1. **事实必须来自真实信息源**：AI 只负责过滤、整理、交叉验证，绝不凭空编造人物、兑换码、关卡
2. **禁止 404 链接**：首页所有官方链接必须可打开，AI 用浏览器抽检
3. **至少 2 个来源交叉验证**：内页同一信息至少在 Google + YouTube、或 Google + 官网 两个来源出现
4. **竞对网站不放入首页**：首页只放官网和正经社群，不放竞品攻略站（官网除外）
5. **主题色贴近游戏调性**：恐怖游戏用暗红深紫、童话游戏用粉蓝暖黄，不用通用蓝白
6. **多语言最多 4 门且必须有英语**：新手先把英语做扎实再加其他语言
7. **内页文档一个关键词一个文档**：所有来源信息汇总进同一个文档，便于后续整理
8. **人工步骤必须暂停**：Chrome 插件、ChatGPT 网页端、favicon.io 等 AI 无法直接完成的，输出暂停提示后结束回合，等用户处理完粘贴结果再继续
9. **合并主战场在上游，本技能只做兜底复核**（第四阶段）：页面合并应在 `yxz-keyword-miner` 第 3.5 步闸门完成——实体计数与机制核查在规划期就可得，别拖到素材收完。本阶段跑 `check_overlap.py` 复核，重点看视频跨页复用与规划期未掌握的新事实。**实体少于约 8 个时，「导航页 + 详解页」两层结构必然重复**
10. **每页一个专属视频**：同一视频字幕出现在两页 = 大段重复文本，选视频时就要避免复用

---

## 浏览器抓取要点

1. **统一用 `mcp_playwright-extension`**：Google 搜索、官网/Steam 内容提取通过 `run_mcp` 调用本地浏览器
2. **等待加载**：每次 `browser_navigate` 后必须 `browser_wait_for`（等文本或等几秒）
3. **正文提取选择器优先级**：`article > main > .content > .post-body > #mw-content-text > body`，优先用语义化标签
4. **Google 搜索 IP 被标记**：出现 429 + /sorry/ → 暂停让用户切换网络环境，不降级 Bing
5. **反爬页面提取失败**：暂停让用户手动复制网页内容
6. **URL 编码**：关键词拼到 URL 时必须 `encodeURIComponent`
7. **YouTube 字幕现已可 AI 自动提取（无需插件）**：Bash 沙箱直连 YouTube 超时、playwright fetch `api/timedtext` 被反爬返回空响应；突破口是走本机代理（实测 127.0.0.1:10808，V2RayN/Clash 类）让 `youtube-transcript-api` 直连。favicon.io 等仍需人工暂停。其余 Chrome 插件（截图类）仍无法直接 playwright 调用。

---

## 输出文件

完成全部流程后生成：

1. **首页信息文档**：`{日期}-{游戏主词}-首页信息.md`
   - 含完整首页 JSON（home/footer/metadata）、主题色 HSL、多语言优先级
2. **Favicon 文件**：`{游戏主词}-favicon.png`（1024×1024，由 GenerateImage 生成）+ favicon.io 转换的多格式压缩包路径
3. **内页素材文档**（每个内页关键词一个）：`{日期}-{游戏主词}-{内页关键词}-素材.md`
   - 含 Google 搜索（2 个网页）、YouTube 字幕、官网/Steam 三个来源内容 + 交叉验证笔记
4. **页面语义重叠分析**：`{日期}-{游戏主词}-页面语义重叠分析.md`（第四阶段产出）
   - 含量化重叠表、合并/拆分判定依据与合并后页面结构、内容边界划定表、视频替换清单、最终页面清单、执行清单
   - 结论须同步回写 `页面矩阵.md` 与 `wiki-素材.md` 的导航结构，否则搭站会生成已废弃的页面

### 首页信息文档结构

```markdown
# {游戏主词} 首页信息

> 调研日期：{日期}
> 游戏主词：{游戏主词}
> 数据来源：AI 通过 WebSearch + playwright-extension 浏览器实时抓取（Steam 商店页 + 官网 + YouTube 频道）
> 链接抽检：已用 playwright/WebFetch 访问关键链接，均非 404

## 1. 主题基础信息

### 官方链接
- **官方网站**：{URL}
- **Steam 商店页**：{URL}
- **Steam 社区 Hub**：{URL}（或 Discord/Reddit 如有）
- **官方 YouTube 频道**：{URL}
- **官方预告片**：{视频标题} {URL}

### 用户关心的 4 组数据
1. {数据1}
2. {数据2}
3. {数据3}
4. {数据4}

## 2. 首页 JSON

```json
{完整 JSON}
```

## 3. 主题色

{根据游戏调性说明选色理由}

```css
/* 导航页主题色 - 亮色主题 */
--nav-theme: H S% L%;
--nav-theme-light: H S% L%;
/* 导航页主题色 - 暗色主题 */
--nav-theme: H S% L%;
--nav-theme-light: H S% L%;
```

默认主题：亮色 / 深色

## 4. 多语言优先级

| 优先级 | 语言 | 本地化名称 | 流量预估 | 理由 |
|--------|------|-----------|----------|------|
| 1 | English | ... | ... | ... |
| ... | ... | ... | ... | ... |

## 5. 链接抽检结果

| 链接 | 状态 | 备注 |
|------|------|------|
| 官网 | ✅/❌ | {URL} |
| Steam | ✅/❌ | {URL} |
| YouTube | ✅/❌ | {URL} |

## 6. 自查校验

| 校验项 | 标准 | 结果 |
|--------|------|------|
| home.meta.title ≤ 60 字符 | ≤ 60 | ✅/❌ {实际字符数} |
| metadata.description 140-160 字符 | 140-160 | ✅/❌ {实际字符数} |
| （其余校验项...） | | |

**所有校验项通过 ✅**（或标注未通过项及处理方式）
```

---

## 实战踩坑教训（Big Walk 实测，2026-08-06）

1. **Steam 商店页是数据最全的单一来源**：发行日期、开发商、发行商、价格、评测数与好评率、标签、支持语言、成就数、官方链接（官网/YouTube/Community Hub）、游戏描述——全部能从 Steam 一个页面拿到。**优先抓 Steam 商店页**，比 WebSearch 多个查询更高效。
2. **Steam 页链接提取要用 innerText 匹配**：Steam 页的 "Visit the website" / "YouTube" / "Community Hub" 是 `<a>` 标签的 innerText，用 `document.querySelectorAll('a')` 遍历 + innerText 匹配最稳，不要依赖 class 或 id 选择器。
3. **官网访问常超时，改用 WebFetch 兜底**：Big Walk 官网 `bigwalk.game` 用 playwright navigate 60 秒超时，但 WebFetch 能成功抓取完整内容。**官网抓取优先用 WebFetch**，失败再试 playwright。
4. **YouTube 频道视频列表选择器常失效**：`ytd-rich-item-renderer` / `ytd-video-renderer` 等选择器在 /videos 页经常返回空数组。**改用 `a[href*="watch"]` 直接提取所有视频链接**，配合 `getAttribute('title')` 拿标题，最稳。
5. **YouTube 视频懒加载需等待 4-6 秒**：navigate 后立即 evaluate 会拿到空列表，必须 `browser_wait_for` 至少 4 秒（建议 5 秒）让视频列表渲染完成。
6. **官方无 Discord/Reddit 时用 Steam Community Hub 替代**：House House 工作室只有 Twitter/Bluesky/YouTube/邮件列表，没有 Discord。Big Walk 官网也只有 FAQ 没社群链接。**对策**：用 Steam Community Hub（`steamcommunity.com/app/{appid}`）作为社群入口，footer.officialDiscord 字段填 "Steam Community Hub"。
7. **Reddit 反爬"Prove your humanity"**：直接 navigate reddit.com 搜索会触发人机验证。**对策**：用 WebSearch `site:reddit.com {游戏名}` 找子版块；若 WebSearch 也无结果，说明该游戏暂无活跃 Reddit 社区，用 Steam Community Hub 替代。
8. **Steam 页显示平台不完整**：Steam 商店页只显示 PC（Windows/macOS），但 Big Walk 实际同时上线 PS5 和 Switch 2。**必须访问官网交叉验证平台列表**，否则 aboutGame.stats 的 Platform 字段会漏掉主机平台。
9. **WebSearch 中文结果偏新闻性，缺精确数据**：搜 "Big Walk Metacritic" 中文结果多是新闻报道（"M站93分"），但缺 Steam 评测数、价格、成就数等精确数据。**WebSearch 用于建立认知，精确数据必须用 playwright 抓 Steam 页**。
10. **买断制游戏无兑换码系统**：Big Walk 是买断制合作游戏，没有兑换码（codes）系统。sidebarCodes 字段填 "暂无"，不要硬编。Roblox/手游等免费游戏才有兑换码。
11. **游戏调性决定主题色**：Big Walk 是轻松温暖户外探险（截图以阳光、草地、海岸为主），适合暖橙黄+森林绿，默认亮色主题。不要套用通用蓝白。**主题色理由要写清楚**，便于后续设计一致性。
12. **多语言优先级按 Steam 支持语言 + 地区热度**：Steam 页列出 14 种支持语言，但不需要全做。按地区热度选 4 门（必须有英语，中文除外）：English > Spanish > German > French。德语优先于法语因德国 Steam 市场更大、付费意愿更强。
13. **YouTube 搜索词必须加引号和 game**：搜 "Big Walk tips guide" 不加引号时，YouTube 会把 "Big Walk" 拆成 "walk" 单词，返回 gimbal 摄影技巧等无关视频（如 "10 Gimbal Moves To Make ANYONE Look EPIC"）。**必须用 `"Big Walk" game tips guide` 加双引号 + game 限定词**，才能拿到游戏相关视频。
14. **YouTube 搜索结果页懒加载严重**：navigate 后立即 evaluate 返回空数组，`browser_wait_for` 4-5 秒后 ytd-video-renderer 才渲染。**必须等待后再提取**，且选择器用 `ytd-video-renderer, ytd-rich-item-renderer` 双重兜底。
15. **新发售游戏纯攻略视频滞后**：Big Walk 2026-08-04 发售，8-06 搜 "Big Walk walkthrough beginner" 只有 1 个崩溃修复视频，搜 "Big Walk tower blorbs puzzle" 完全为空。**攻略类视频通常滞后 1-2 周**，新发售游戏只能拿到实况游玩/评测类视频。对策：在推荐视频表里如实标注"纯攻略视频尚未出现"，让用户自行决定是否提取字幕或跳过。
16. **YouTube 视频时长在搜索结果页常显示为"未显示"**：搜索结果页的 `#metadata-line` 通常只返回观看量+发布日期，时长在另一个元素里。**不必强求填满时长字段**，留"未显示"即可，用户点进视频页就能看到时长。
17. **YouTube 字幕步骤改为 AI 预筛 + 自动提取 1 个必填视频**：原技能让用户自己搜 YouTube 找视频，体验差。优化后 AI 先用 playwright 多查询搜索 YouTube（差异化查询见上方映射表），合并去重后按相关度+观看量列出 5-8 个推荐视频（含标题/URL/时长/观看量/发布日期/类型/推荐理由），**并自动选定第 1 个为「唯一必填」视频**。`extract_subs.py` 解析「唯一必填」块自动提取字幕（无需人工选 3 个）。文档中预留唯一必填 + 候选表 + 视频内部交叉验证笔记区块，字幕缺失/质量差时从候选替换，也可填"跳过"。
18. **不同内页关键词必须用差异化搜索查询**：Big Walk 实测时，"tips" 和 "tower order" 两个关键词用了相同的 3 个查询（tips guide/gameplay co-op/friends funny），导致两个文档的 8 个推荐视频完全雷同。**正确做法**：按关键词类型选查询——流程顺序类（tower order/walkthrough）应搜 `walkthrough playthrough` / `ending complete full game` / `speedrun`，优先推荐速通和完整结局视频（必然含实际通关顺序）；通用技巧类（tips/beginner）才搜 `tips guide` / `gameplay co-op`。技能中已新增"关键词类型→搜索查询映射表"。Big Walk 实测发现：搜 `ending complete full game` 拿到速通(8:41)、100%结局、普通结局 3 个流程类视频，对 tower order 价值远高于通用评测视频。
19. **页面矩阵会规划出实际不成立的页（GRAIN ROT 实测，2026-08-10）**：矩阵在收集素材之前规划，那时不知道游戏实体数量，容易照惯例规划「导航页 + 详解页」两层。实测 GRAIN ROT 全站只有 **4 种 vessel**，`characters` 与 `characters-guide` 两页 Jaccard 0.351、共享 88 术语，是全站最高重复对；`map` 与 `map-guide` 同理——官方标注 "Procedurally shifting underground dungeons"，**根本没有固定地图**，所谓"地图索引页"立不住。**规律：实体少于约 8 个 → 两层结构必然重复，合并成一页；程序化生成的地图 → 只做一页。** 即便上游 `yxz-keyword-miner` 第 3.5 步合并闸门已跑，素材期若发现规划期未掌握的新事实（如实体数与规划不符、需拆出 troubleshooting），仍要跑第四阶段兜底复核。
20. **该拆的页比该合的页更容易被忽略**：GRAIN ROT 的 `update` 页抓到 5 个来源，其中 3 个是崩溃/黑屏/无限加载修复文——这些是独立高需求长尾词（`{游戏} crash fix` / `not launching` / `black screen`），新游发售初期搜索量常高于 patch notes 本身。混在更新日志页里两头不讨好，应拆出 `/troubleshooting`。**做重叠自检时要双向看：既找该合的，也找一页混装多类需求该拆的。**
21. **Jaccard 高不等于该合并**：游戏站各攻略页天然共享大量机制术语。GRAIN ROT 的 `best-weapons × co-op-guide` 达 0.317 却不该合并——两个关键词意图独立，高重叠只是因为都引用了同一篇 pixelnitro Multiplayer Guide。**正确处理是划定内容边界**（按"用户处在哪个阶段"切分，每页只写自己那段，其余改内链），而不是合并。同理 `crossplay` / `controller` 这类问答型页即使内容薄也保留独立页，Google 偏好直答页。
22. **必填视频要按页去重**：GRAIN ROT 出现 3 组跨页复用（`aRReKt_DOqs` → characters-guide + wiki，`8v2IVi4SM-Q` → co-op-guide + crossplay，`i3Hr8vQ8CUc` → price + system-requirements）。同一视频字幕落到两页 = 大段完全相同的文本，直接制造重复内容。**选视频阶段就要记录已用 ID，避免复用**；`check_overlap.py` 第三块会兜底检出。
23. **Grep 工具对含中文括号的路径匹配会失效**：素材目录名含「（国外-热词游戏站）」时 Grep/Glob 命中为空，误判成"文件不存在"。**改用 Python 直接 `glob` + `open` 读取**，这也是 `check_overlap.py` 全程用 Python 而非 shell 的原因。

