docs: 移交 playbook 与 H10 需求草稿

将 sif 提炼的抓取微服务范式作为开发建议入库,并标明本仓移交其他团队落实开发;不含凭据与实现代码。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
chii 2026-08-07 11:52:55 +08:00
parent 7cc206e776
commit a1c8770e1e
4 changed files with 368 additions and 1 deletions

View file

@ -1,3 +1,21 @@
# amazon-h10-api # amazon-h10-api
H10抓取微服务 Helium 10(H10)相关数据抓取微服务 — **移交中**。
## 重要说明
| 项 | 说明 |
|----|------|
| 仓库状态 | **方法论与需求移交**;业务代码尚未实现 |
| 接手方 | 由其他开发团队落实编码、逆向、部署与交付 |
| Playbook | [`docs/scraper-service-playbook.md`](docs/scraper-service-playbook.md) — **开发建议**,非强制规范 |
| 移交说明 | [`docs/HANDOVER.md`](docs/HANDOVER.md) |
| 业务需求 | [`docs/requirements-h10.md`](docs/requirements-h10.md) |
对标参考(已上线同类服务):`amazon-sif-api`、`amazon-keepa-api`。
## 快速入口
1. 读 [`docs/HANDOVER.md`](docs/HANDOVER.md)
2. 读 [`docs/scraper-service-playbook.md`](docs/scraper-service-playbook.md)(建议范式)
3. 读 [`docs/requirements-h10.md`](docs/requirements-h10.md)(H10 功能范围)

26
docs/HANDOVER.md Normal file
View file

@ -0,0 +1,26 @@
# 仓库移交说明
## 状态
本仓库(`amazon-h10-api`)当前为**需求与方法论移交包**,**尚未实现抓取微服务代码**。
后续编码、浏览器逆向、契约沉淀、部署与冒烟,由**接手开发团队**落实。
## 文档清单
| 文档 | 性质 | 说明 |
|------|------|------|
| [scraper-service-playbook.md](./scraper-service-playbook.md) | **开发建议** | 从 sif 提炼的通用构建范式;非强制规范 |
| [requirements-h10.md](./requirements-h10.md) | 业务需求草稿 | H10 关键词反查 / 排名监控 / 排名表格抓取 |
## 建议起步顺序(仅建议)
1. 阅读 playbook(尤其 P1–P3、§4.1 是否引入 PG)。
2. 按 `requirements-h10.md` 做 P1 范围确认(首个交付域建议:产品词表反查)。
3. 对 [Helium 10 Members](https://members.helium10.com/) 做 P2 浏览器逆向,产出 `*-contract.md`(**凭据勿入库**)。
4. 再按 playbook P3–P7 实现与交付。
## 凭据与安全
- 目标站账号 / API Key / 会话 token:**不得提交进 Git**。
- 交接凭据请走团队既有密钥渠道(secret / 密码库),勿写进本目录 markdown。

56
docs/requirements-h10.md Normal file
View file

@ -0,0 +1,56 @@
# H10 关键词数据反查与导出 — 需求草稿
> **性质**:业务需求说明(草稿),供接手团队澄清与排期。
> **目标站**:https://members.helium10.com/
> **凭据**:向移交方索取,**禁止写入本仓库**。
## 功能概览
| # | 能力 | 说明 |
|---|------|------|
| 1 | 词表反查 | 按顺序:先产品词表反查,再全量词表反查;ASIN 由调用方/用户提供 |
| 2 | 排名监控录入 | 将 ASIN + 关键词加入 H10 排名监控;多组则循环添加 |
| 3 | 排名表格抓取 | 与词表反查独立,单独执行 |
---
## 1. 词表反查(顺序执行)
本品 ASIN、竞品 ASIN **由用户自行提供**。
### 1.1 产品词表反查
1. 进入 Helium 10 对应功能页,按产品词表反查流程操作。
2. 输入本品 ASIN。
3. 完成反查后导出。
4. **导出名**:`{本品ASIN}+反查词表`。
### 1.2 全量词表反查
在 1.1 完成后的界面继续:
1. 在本品 ASIN 基础上输入竞品 ASIN。
2. 按全量词表反查流程操作并导出。
3. **导出名**:`{本品ASIN}+全量词表`。
---
## 2. 排名监控录入
- 输入的 ASIN、关键词均由用户提供。
- 若提供多组「ASIN ↔ 关键词」,则**重复执行添加步骤**,直到全部录入完毕。
---
## 3. 排名表格抓取
- 与「词表反查」区分开,**单独任务**执行。
- 进入对应页面后按既定 UI 流程抓取排名表格数据。
---
## 实现提示(对接 playbook)
- 优先用浏览器逆向还原 HTTP 契约,再 HTTP 直连取数(见 [scraper-service-playbook.md](./scraper-service-playbook.md))。
- 若导出仅为浏览器下载文件,需在契约中明确:是直链下载、异步任务轮询,还是必须走浏览器下载流。
- 开放对外 API 前须确认 Helium 10 侧计费 / 风控 / ToS 边界。

View file

@ -0,0 +1,267 @@
# 数据抓取微服务构建通用范式(Playbook)
> **文档性质:开发建议(非强制规范、非已落地实现)**
>
> - 本文供接手 `amazon-h10-api` 的开发团队参考,说明「同类抓取微服务」推荐怎么做。
> - **本仓当前未实现业务代码**;落地开发、契约逆向、部署与运维由接手团队负责。
> - 内容提炼自 `amazon-sif-api` 的真实构建过程,属可复用方法论,可按 H10 目标站实际情况裁剪,不必逐字照搬。
> - 对标蓝本:`amazon-sif-api` / `amazon-keepa-api`(轻量、默认无 PG、api + auth + worker + mq)。
> 适用:目标是某个**有登录态的 SaaS/数据平台**,要把它已聚合的数据,以**自有 REST API** 稳定、低成本地对外提供。
---
## 0. 一句话范式
> **用浏览器把"人能看到的数据"逆向成"机器能调的接口契约",再用一套无状态取数 + 集中式会话 + 队列派发的微服务把它工程化、可运维地交付。**
核心信条:
1. **浏览器只用来"探路"和"拿钥匙",不用来"搬货"。** 登录/拿 token 用真浏览器;批量取数用 HTTP 直连(快、省、稳)。
2. **先抓契约,再写代码。** 没摸清请求/响应结构前不写业务逻辑。
3. **会话集中、取数无状态、派发异步。** 三者解耦,才能横向扩展又不互相拖垮。
4. **每个域(domain)闭环交付:探索→实现→冒烟→真实样本→文档。** 不堆半成品。
---
## 1. 阶段总览
| 阶段 | 目标 | 关键产出 |
|------|------|---------|
| P1 需求澄清 | 定边界、定形态、定蓝本 | 需求共识、对标项目、首个交付域 |
| P2 浏览器逆向 | 把页面行为还原成 HTTP 接口契约 | `*-contract.md`(登录+各数据接口) |
| P3 架构设计 | 定服务拆分、会话/鉴权/扩展策略 | `design.md`、里程碑、风险清单 |
| P4 编码实现 | 按域实现取数+归一化+对外路由 | 三服务代码 |
| P5 部署 | 按目标环境规范上线 | 部署脚本、stack/compose |
| P6 冒烟+取样 | 真实数据验证每个端点 | `samples/*.json` |
| P7 文档交付 | 给接入方可直接用的文档 | `api.md`(脱敏) |
> 后续每新增一个数据域,只重复 **P2(局部) → P4 → P6 → P7**,架构不动。
---
## 2. P1 · 需求澄清
**目标**:把"做个 XX 数据 API"收敛成可执行的最小闭环。
必须问清的 4 件事(缺一不可):
- **数据来源形态**:登录后聚合页?官方 API?纯爬 HTML?→ 决定逆向难度与合规风险。
- **对外形态**:REST / MCP / GraphQL?响应结构对齐谁?→ 本项目选「REST 为主,结构对齐目标平台的 MCP 工具语义」,让下游迁移成本最低。
- **首个交付域**:别想一次做全。挑一个**高价值 + 可独立验证**的域先打通(本项目=反查关键词)。
- **架构蓝本与体量**:找一个同类已上线项目对标(本项目=`amazon-keepa-api`),明确"要多轻"。避免过度设计。
**决策原则**:能用「合理默认 + 事后说明」就别反复追问;只有**范围/破坏性/不可逆**的点才必须确认。
---
## 3. P2 · 浏览器逆向(范式的灵魂)
**目标**:把"人在页面上点一下看到的数据",还原成一条可复现的 HTTP 调用(URL + headers + body + 响应结构)。
### 3.1 方法
1. **真人操作 + 拦截网络**:用浏览器自动化打开目标页,注入网络拦截器(或开 DevTools/CDP),触发一次目标操作,捕获 `XHR/fetch`。
2. **抓三类东西**:
- **鉴权机制**:token 在哪(localStorage/cookie/header)?格式(JWT?)?有无设备指纹/签名参数?过期时间?
- **公共参数**:每个请求都带的 query/header(时间戳、站点、`_m` 指纹…)。
- **业务接口**:路径、方法、请求体字段、响应外层与 `data` 结构。
3. **分域归档**:把接口按数据域分类记进 `*-contract.md`,每个接口标注「对应哪个对外功能」「是否计费」「关键返回字段」。
4. **标注噪音**:UI 辅助接口(弹窗、埋点、文案)明确标记"无需复刻",避免后人误抓。
### 3.2 本项目实证
- 发现鉴权 = `localStorage.token`(JWT, `exp`≈7天) 放进 `authorization` 头(**无 `Bearer` 前缀**)。
- 发现每个请求带设备指纹 `_m`(来自 `localStorage._murmur`)——**跨进程复用 token 必须连指纹一起带**,否则风控。
- 找到一个**不计费的探针接口**(`/api/user/sys/info`)用于校验会话有效性。
- 把"反查/流量/概览/广告"四域接口结构全部记入契约文档。
### 3.3 坑
- **入口不明 / 计费不清的功能先别碰**:本项目"市场需求/竞争"域因入口是耗积分的增值功能且契约未实测,**主动顺延**而非硬抓——避免在不确定处耗时跑偏。
- **逆向到的接口要立刻人工核对一次**:字段名、计费字段(`consumeIntegral`)、分页规则。
### 3.4 产出
`docs/*-contract.md`:逆向契约(**只记结构,不记真实凭据**)。
---
## 4. P3 · 架构设计(四服务范式)
**目标**:一套能横向扩展、会话自愈、低成本的拆分。
```
┌───────────┐ REST(+API Key) ┌──────────────┐
调用方 →│ api │───────────────────→│ account 池 │
│ 网关/缓存 │ └──────────────┘
└─────┬─────┘
│ 任务(MQ RPC)
┌─────▼─────┐ 按需要会话 ┌───────────┐ 无头登录 ┌────────┐
│ worker │──────────────→│ auth │──────────→│ 目标站 │
│ 取数+归一化 │ (HTTP直连取数)└───────────┘ 探针/重登 └────────┘
└───────────┘
```
| 服务 | 职责 | 为什么独立 |
|------|------|-----------|
| **api(网关)** | REST 路由、API Key 鉴权、账号池轮询、任务派发、TTL 缓存、运维 UI | 对外唯一入口,无业务取数逻辑,便于加缓存/限流/鉴权 |
| **auth(会话)** | 无头浏览器登录、token/指纹/cookie 落盘、有效性探针、巡检、**单飞重登** | 登录是最重、最易触发风控的环节,集中管理 + 串行化 |
| **worker(取数)** | 消费任务 → HTTP 直连取数 → 归一化;遇鉴权失败标记失效并重试一次 | **无状态**,可任意多副本横向扩展吞吐 |
| **mq(队列)** | api↔worker 的异步 RPC | 解耦派发与执行,削峰、天然负载均衡 |
### 设计要点(通用)
- **会话三道校验**:①取数前本地预检(零成本)②后台巡检(探针接口,不计费)③取数遇鉴权失败被动兜底 → 重登重试。
- **单飞重登**:同账号重登加锁,并发请求只触发一次登录,其余复用新 token——**防惊群触发风控**。
- **设备指纹随 token 走**:复用 token 时必须带登录时的指纹。
- **轻量优先**:文件会话 + 进程内 TTL 缓存,**默认无数据库**(对标蓝本体量,见 §4.1)。
- **凭据外置**:账号/密码走 `config.json`(不入库),对外 key 走环境变量/secret。
- 产出:`design.md`(含里程碑 + 风险清单:token 并发、指纹绑定、计费、风控、schema 漂移、合规、**PG 连接预算**)。
### 4.1 存储选型与 PostgreSQL 连接数(prod 实证)
> **结论先行**:与 sif / keepa / listing-scraper 同类的「轻量数据获取微服务」**默认不需要 PostgreSQL**,也**不需要 pgbouncer**。只有业务必须落库、或要做跨请求持久化查询时,才引入 PG,且**必须做连接预算**。
#### prod 同类服务调查(swarm-mgr3,排除 lsvdaas)
| 服务 | 用 PG? | 副本 | pgbouncer? | 连接风险 |
|------|---------|------|-------------|----------|
| **sif** | 否 | api 1 + worker 3 + auth 1 | — | 无 |
| **keepa** | 否 | api 1 + worker 3 + auth 1 | — | 无 |
| **listing-scraper** | 否 | api 1 + worker 3 | — | 无 |
| **jiimore** | 否 | api 1 + worker 3 + auth 1 | — | 无 |
| **voc-analysis** | 是 | api 1 + worker 1 | 否(直连) | 低(副本少,采样时连接≈0) |
| **onesvm-asinwarehouse** | 是 | backend 1 + proxy 1 + worker 10 | 有 stack 但未接线 | **中高**(理论峰值≈72,当前≈20/200) |
共享 PG(`postgres_db`)`max_connections=200`,采样时总连接约 55,**未见 `too many connections`**。
#### 何时不用 PG(推荐默认)
满足以下多数条件时,坚持「无 DB」范式(本项目的 sif / keepa 已验证):
- 数据可**实时从源站聚合**取回,无需本地持久化查询。
- 会话/配置用**文件**即可(`config.json` + `sessions/*.json`)。
- 去重用**进程内 TTL 缓存**或 MQ 天然串行即可。
- 不需要复杂报表、历史回溯、跨 ASIN 关联查询。
**收益**:零 PG 连接占用、部署简单、worker 随意扩副本无连接压力。
#### 何时需要 PG + 怎么做才不爆连接
引入 PG 前必须算清**连接预算**:
```
集群峰值连接 ≈ Σ (每服务副本数 × 每副本最大连接数)
每副本最大连接数 = pool_size + max_overflow # SQLAlchemy
或 max_size # asyncpg
```
**ASW 反例(prod 实测)**:
| 组件 | 副本 | 每副本池上限 | 集群峰值 |
|------|------|--------------|----------|
| backend | 1 | 30 (10+20) | 30 |
| proxy_manager | 1 | 8 | 8 |
| listing worker | 4 | 4 | 16 |
| reviews worker | 6 | 3 | 18 |
| **合计** | **12** | | **≈72** |
平台虽有 `asw-pgbouncer`(`:6432`),但 ASW 服务**全部直连 `postgres_db:5432`**,pgbouncer 未接线——这是典型「建了没用」的教训。
#### 引入 PG 的硬性规范
1. **多副本 worker 必须经 pgbouncer**,禁止每个 worker 进程各自开大池直连 PG。
2. **连接池要小**:worker 侧 `pool_size` 建议 2–5;`max_overflow` 0–3;宁可排队不要占连接。
3. **部署前做预算表**:写入 `design.md`,标明「副本数 × 池大小 = 峰值」,确认 `< PG max_connections × 30%`(留余量给其他服务)。
4. **优先异步单连接**:轻量写入/状态表可用「单连接 + 队列」而非每请求开连接。
5. **监控**:接入后观察 `pg_stat_activity` 按库/按应用计数;日志搜 `too many connections`。
#### 决策树(简版)
```
需要跨请求持久化查询 / 历史落库?
├─ 否 → 文件会话 + MQ + 进程缓存(sif/keepa 范式)✅
└─ 是 → 算连接预算
├─ 峰值 < 20 且单副本 → 可直连,小池(pool≤5)
└─ 多副本 worker / 峰值 > 20 → 必须 pgbouncer + 小池
```
---
## 5. P4 · 编码实现(按域可扩展)
**目标**:让"加一个数据域"成为填空题,而不是改架构。
落地模式(本项目验证有效):
- **worker 侧**:一个通用 `_request()`(统一拼公共参数、塞鉴权头、判 `code`、识别鉴权错误抛 `AuthError`)+ 每个域一个 `fetch_xxx()` + 一个 `normalize_xxx()`;`main.py` 用 `OPS = {op: (fetcher, normalizer)}` 表分发。
- **api 侧**:一个共享 `_dispatch(op, params, cache_key, ...)`(查缓存→选账号→MQ RPC→包 `meta`)+ 每个域一个瘦路由。
- **归一化原则**:拿不准全部字段时,**先"透传 data + 轻量字段映射"**,保证冒烟能跑、文档有内容,再按真实返回逐步精修字段(本项目 traffic-trend 就是先透传、看到真实键名后再对齐 `totalScore/nfScore…`)。
- **错误语义化**:鉴权类错误 → 触发重登重试;其余 → 明确 502/504/503。
> 扩展一个域的改动量 = 2 个函数(fetch+normalize)+ 1 条 OPS + 1 个路由。架构零改动。
---
## 6. P5 · 部署(按目标环境规范)
**目标**:一条命令可复现地上线到目标环境。
- **遵守目标环境规范**:本项目按 onesvm-ops——compose/stack、amd64、指定 registry、`placement.constraints` 固定节点、资源限制、`docker secret` 装敏感信息、`--resolve-image never`。
- **部署脚本要点(踩坑沉淀)**:
- 用**用户可写目录**同步源码(别假设 `/opt` 有权限)。
- `scp` 前先 `mkdir -p` 远端目录。
- 端口冲突先探测、可配置(本项目 8080→8088)。
- `docker service update` 会换容器,**之后要重取容器 ID**再 exec。
- **同名 tag 复用时**,worker 需 `--force` 才会真正滚动到新镜像(否则跑旧代码——本项目实测踩到)。
- 产出:`scripts/deploy-xx.sh` + `deploy/stack.yml` / `docker-compose.yml`。
---
## 7. P6 · 冒烟 + 取真实样本
**目标**:每个对外端点用真实请求验证,并把返回存成示例数据。
- **逐端点单独冒烟**,打印关键字段 + `meta`(延迟、计费、是否命中缓存)。
- **省成本**:注意计费额度,能一次验证就别重复;相同参数靠缓存。
- **把真实返回落盘** `docs/samples/*.json`——它既是回归基线,又是文档示例的事实来源(文档示例必须来自真实数据,不杜撰)。
- 冒烟暴露的字段不匹配 → 回 P4 精修归一化 → 重新取样。
---
## 8. P7 · 文档交付(给接入方)
**目标**:同事拿到就能调。
`api.md` 必含:
- 接入信息(base URL、鉴权方式、健康检查、在线 `/docs`)。
- 通用约定(公共参数、`meta` 结构、缓存、错误码)。
- **每个端点**:参数表 + 真实 curl + **真实裁剪响应** + 字段要点。
- **开放边界**:明确哪些开放(如"会员权益内、不计费、可无限查")、哪些关闭及原因(如"耗积分功能一律关闭")——让接入方不踩计费雷。
### 安全红线(务必)
- **真实 key / 账号 / 手机号绝不进仓库**。文档用占位符(`$API_KEY` / "向维护方索取")。
- 若敏感信息**已误提交**:移除 + **改写历史**(`reset --soft` 重做提交) + `force-with-lease` 覆盖远程 + 本地 `reflog expire && gc`,并 `git log -S '<secret>'` 验证为空。
- 误暴露过的凭据,最稳妥是**轮换**而非仅删除。
---
## 9. 复用检查清单(开新项目照着走)
```
[ ] P1 需求:来源形态 / 对外形态 / 首个域 / 对标蓝本+体量 都已确认
[ ] P2 逆向:鉴权机制 / 公共参数 / 指纹 / 不计费探针 / 各域契约 已记入 *-contract.md
[ ] P2 逆向:噪音接口已标注;入口不明或计费不清的域已显式顺延
[ ] P3 架构:api/auth/worker/mq 四服务;会话三道校验 + 单飞重登;凭据外置;默认无DB(见 §4.1)
[ ] P3 架构:若引入 PG → 连接预算表 + pgbouncer(多副本必走)+ 小池(pool≤5)
[ ] P3 文档:design.md(里程碑 + 风险清单)
[ ] P4 代码:通用 _request + 按域 fetch/normalize + OPS 分发 + 瘦路由;归一化先透传后精修
[ ] P5 部署:遵守目标环境规范;脚本处理权限/端口/容器ID/同tag强制刷新
[ ] P6 冒烟:逐端点真实验证 + meta;样本落盘 docs/samples
[ ] P7 文档:api.md(真实示例 + 开放边界);凭据脱敏;误提交则改写历史并轮换
```
---
## 10. 一页纸心法
- **浏览器探路,HTTP 搬货。**
- **先契约,后代码。**
- **会话集中、取数无状态、派发异步。**
- **按域闭环,架构不动。**
- **样本即文档,文档即事实。**
- **凭据永不入库,泄露即轮换。**
- **轻量抓取默认无 PG;要落库先算连接数,多副本必走 pgbouncer。**