# 机会深挖研究方法论

Status: active
Date: 2026-06-10
Owner: validation-analyst
Review cadence: weekly

本文件解释 deep-dive 报告里的数据从哪里来、怎么采、怎么读，以及下一轮要如何升级。单个报告只保留结论和少量口径，避免每份报告重复解释。

## 一、读报告的四个标签

| 标签 | 含义 | 例子 |
|---|---|---|
| 观察 | 来自外部对象的公开证据 | 商店截图文案、App Store / Google Play 详情、公开评论、官网隐私政策 |
| 我们的判断 | 基于观察做的推断 | “睡眠类涉及健康 claim 风险”“LG remote 有商标/兼容性风险” |
| 我们建议 | 面向我们是否验证或开发的动作 | “先做 Timestamp Camera 窄 MVP”“BetterSleep 只验证 noise mixer wedge” |
| 待补 | 当前采集不到或还没做的证据 | App 内 paywall 截图、SKU 级 trial/renewal、真实广告库素材 |

报告里出现“推荐 wedge / 我们建议的验证路线 / 推进条件”时，都是我们的动作建议，不是竞品正在做的路线。

## 二、当前采集链路

| Lane | 当前实现 | 输出 | 局限 |
|---|---|---|---|
| 身份锁定 | batch `identity_lock` + `identity-lock.json`，旧报告兜底解析 `source_hints` / `evidence.csv` URL | `identity-lock.json`、store targets、`evidence.csv`、`collection-summary.json` | 需要 dashboard 触发时稳定传入 identity seed |
| 商店详情 | `collectors/store/collect_details.mjs`，US/GB，App Store + Google Play | 评分、评论量、版本、截图 URL、隐私链接、IAP range | App Store / Google Play 字段语义不同，需要 normalized metrics |
| 评论样本 | `collectors/store/collect_reviews.mjs`，当前通常每 app 80-120 条 | `review-clusters.csv` | 当前是 first-pass pain map，不代表全量口碑 |
| 截图 OCR | `scripts/radar/ocr_store_screenshots.py` | `assets/store-screenshot-ocr.csv`、本地截图文件 | OCR 会有符号噪声，关键 hook 需要人工/VL 归纳 |
| Trust / Pricing | `scripts/radar/resolve_trust_pricing.py` 抓 privacy/support/terms/refund 文本 | `pricing-matrix.csv`、`privacy-data-safety.csv`、`support-refund-quality.csv` | 不是 App 内 SKU 级 paywall |
| 广告库 | `ad-library-queries.csv` 生成查询任务；`plan_ad_library_browser_tasks.py` 生成 Meta/TikTok/Google 可打开任务；DataEye/ADX 结果可由 `ingest_ad_creatives.py` 回填 | `ad-library-queries.csv`、`ad-library-browser-tasks.csv`、`ad-creative-signals.csv` | 浏览器任务只是待采集入口，必须人工/账号化打开后回填素材 URL 才算 verified |

## 三、评论采样怎么理解

当前报告里的评论聚类是“第一轮用户声音”，不是最终用户研究。

本轮通常按已锁定商店对象、国家和平台抓公开可得样本。实际每个 App 取到 80-120 条，取决于平台可访问性和商店 API 返回情况。这个量足够发现明显的订阅、退款、首次结果、性能、权限和客服问题，但不够支持精细 LTV 或最终产品决策。

下一轮要做分层采样：

| 维度 | 做法 | 目的 |
|---|---|---|
| 时间 | 近 7 / 30 / 90 天分层 | 区分历史问题和当前版本问题 |
| 星级 | 1-2 星、3 星、4-5 星分别采 | 负反馈找风险，中评找可修复机会，好评找核心价值 |
| 平台 | iOS / Android 分开 | 避免把单平台 bug 当成产品本质 |
| 国家 | US/GB 之外加入目标投放国家 | 看价格、语言、文化和支付差异 |
| 版本 | 按 updated/version 标注 | 判断新版本是否修复旧痛点 |
| 主题 | 订阅、结果不符、性能、权限、客服、功能缺口 | 直接映射到 MVP guardrail |

报告中的评论痛点图谱目前由关键词聚类 + representative review 生成。后续要升级为 embedding/topic clustering，并保留原文样本索引，减少关键词误判。

## 四、截图 URL 为什么很多，OCR 怎么选

`screenshot_count` 是商店 listing 返回的全部截图 URL。它可能包含：

- iPhone / iPad / Google Play 多尺寸截图。
- US / GB 不同 locale 的截图。
- 横竖图、旧素材、重复素材。
- 商店详情页里附带的多个 screenshot array。

所以 BetterSleep 出现 52 个 screenshot URL 并不表示我们读了 52 张图。当前为了控制噪声，每份报告默认最多 OCR 8 张，剩余计入 skipped。选择策略是按商店详情回填顺序取前 N 张，通常优先覆盖 App Store / Google Play 首屏素材。下一轮要改成按平台、国家、图片 hash 和视觉差异去重后再选样。

OCR 当前实现：

1. 下载截图到 `data/runs/research/<date>/...`。
2. 用本地 Tesseract 识别英文文本。
3. 如果空或低质量，做放大、灰度、增强对比、二值化后再跑 Tesseract。
4. 对 empty/failed 样本可使用 VL fallback，但只在必要时跑，避免成本和幻觉。
5. 报告正文只写人工归纳后的 hook；原始 OCR 文本保留在折叠表里做证据。

## 五、Pricing / Paywall Matrix 怎么读

当前 `pricing-matrix.csv` 主要包含三类信号：

| 类型 | 来源 | 能说明什么 | 不能说明什么 |
|---|---|---|---|
| `free_install` | 商店安装价格 | 是否免费安装 | 不能说明是否有 App 内订阅 |
| `iap_range` | Google Play IAP range | 大概付费区间 | 不能说明 SKU、trial、默认选中、续费价 |
| terms/support text | 官网、隐私、条款、退款文本 | 是否有取消、退款、删除路径线索 | 不能替代 App 内 paywall 截图 |

所以 pricing 表默认折叠。真正能支持开发决策的是下一轮 paywall capture：

- SKU 名称。
- 价格、周期、trial。
- 默认选中套餐。
- 是否 billed upfront。
- 关闭入口是否明显。
- 订阅前是否有真实 preview。
- 取消、退款、恢复购买路径。

## 六、报告版式原则

单个报告只保留：

- 决策摘要。
- 怎么读这份报告。
- 真实采集面板和采集口径。
- 身份锁定。
- 关键发现。
- 用户研究 / 评论痛点 / 合规红线 / 可迁移模式。
- 我们建议的验证路线。
- 下一步。

以下内容默认折叠或集中维护：

- 模块覆盖。
- 完整 Research Queue。
- 原始 Pricing / OCR / Privacy / Support 表。
- 每轮流程改进记录。

共性流程问题统一进入 `improvement-backlog.md`，避免每份报告重复。

## 七、Identity Lock 怎么做

`identity-lock.json` 是后续所有采集的身份锚点，不再把 App 身份藏在 Markdown 文本里。它允许一个机会同时记录多个 store identity，并显式区分关系。

| 来源 | 处理方式 | 置信度 |
|---|---|---|
| Google Play / radar dashboard 直接传 `package_id` | 直接作为 Android `store_id` / `package_id`，生成 store detail target | high |
| App Store URL / `app_store_id` | 直接作为 iOS `store_id`，store detail 后补 `bundle_id` / `app_id` | high |
| DataEye / ADX 有 package/store id | 映射为对应 platform identity，并保留 `source_record_id` | medium-high |
| DataEye / ADX 只有 title/developer | 先作为 `unverified_candidate`，需要商店搜索或人工确认后才升级 | low-medium |
| 同名、跨端主体不一致 | 写 `relationship=comparable_not_same_entity` 或 `same_product_line`，不能强行合并 | medium |

后续从 radar dashboard 发起 deep dive 时，推荐传：

- `title`
- `developer`
- `platform`
- `package_id`
- `app_store_id`
- `bundle_id`
- `store_url`
- `source_name`
- `source_record_id`
- `country`
- `relationship`
- `confidence`

这样 Google Play 触发的机会能直接锁 package；App Store 触发的机会能直接锁 numeric id；ADX/DataEye 触发的机会如果只有标题，则先进入候选态，避免把同名 App、镜像 APK 或可比竞品混进同一报告。

## 八、广告库真实素材怎么解决

`ad-library-queries.csv` 只是查询任务清单，不代表已经找到广告素材。真实素材或明确无结果必须进入 `ad-creative-signals.csv`。

| 文件 | 含义 | 是否等于真实素材 |
|---|---|---|
| `ad-library-queries.csv` | 要去 TikTok / Meta / Google / DataEye 用什么 query、哪个市场、什么状态 | 否 |
| `ad-library-browser-tasks.csv` | Meta / TikTok / Google Ads 的可打开搜索 URL、identity 锚点、browser_ready 状态 | 否 |
| `dataeye-matches.json` | DataEye 记录按 title/package 等命中，可能是产品榜或素材榜 | 不一定 |
| `ad-creative-signals.csv` | 已归一化的 creative URL/video/image/rank/exposure/match_type/status | 是，或明确 `no_dataeye_creative_match` |

本仓库已跑通过 DataEye/ADX：2026-06-10 runner 返回 DataEye 400 行；`adx_short_drama` 的 playlet rank/product/creative 也已验证，VibeShort 类短剧方向能生成素材 digest。DataEye 通用 `creative_search` 当前用 `adx_game` + auth preflight + `searchKey/searchType/matchType` 定向参数；每次查询写 `ad-library-dataeye-runs.csv`，区分授权成功 0 结果、401、403、505 和真实素材命中。还没完全闭环的是 Meta/TikTok/Google 账号化打开搜索页、保存截图 manifest、creative URL 和广告主页面。

突破顺序：

| 优先级 | 动作 | 输出 |
|---|---|---|
| P0 | 用 `identity-lock.json` 的 package/app id/title/developer/domain 生成多 query | 更少同名误匹配 |
| P0 | DataEye 先跑 `creative_search`；短剧另跑 `playlet_creative`，按 `direct_creative_match` / `product_rank_match` / `lane_benchmark` / `no_public_result` / `blocked` 标状态；每次查询保留 run log | `ad-library-dataeye-runs.csv` + `ad-creative-signals.csv` |
| P0 | 生成 Meta/TikTok/Google Ads 浏览器任务，不伪装成已采集素材 | `ad-library-browser-tasks.csv` |
| P1 | 接 Google Ads Transparency：用官网域名、开发者、App 名查广告主 | advertiser/page/creative URL |
| P1 | 接 Meta Ad Library：用开发者、官网域名、品牌名查 page 和素材 | page id、creative snapshot |
| P1 | 接 TikTok Creative Center / Creative Library：用 App 名、开发者、store URL 查素材 | video URL、hook、country |
| P1 | 对每条素材做人审/VL：前 3 秒 hook、承诺、CTA、落地页一致性 | ad-to-product consistency |

报告里以后按这套状态解释：

- `complete`：有 direct/related creative 或平台明确返回可复核素材。
- `partial`：只有 lane benchmark、产品榜、广告信号或可比竞品素材。
- `browser_ready`：已生成可打开任务，等待账号化浏览器/人工采集。
- `blocked`：账号、权限、平台反爬、endpoint 未接好。
- `no_public_result`：查询成功但公开库无结果。

## 九、下一轮优先升级

| 优先级 | 改进 | Close criteria |
|---|---|---|
| P0 | 结构化 identity lock | batch 和 dashboard 触发都能写 `identity-lock.json`，store target 不依赖 Markdown |
| P0 | SKU 级 paywall capture | 每个订阅类 App 至少有 1 套真实 paywall 截图和 SKU 表 |
| P0 | 评论分层采样 | 每个 high-priority App 有平台/星级/时间窗分布 |
| P1 | OCR 视觉去重和 hook 归纳 | report 正文不出现 OCR 噪声，原始 OCR 可追溯 |
| P1 | 广告库真实素材 | query manifest 之外，有 `ad-creative-signals.csv` 的 creative URL / screenshot / match_type / status |
| P1 | normalized store metrics | listing table 不混用 ratings/reviews/install 字段 |
