Amazon US 市场分析报告 Skill
概述
此 Skill 实现从数据抓取到 HTML 报告生成的完整工作流,基于 assets/template.html 模板生成市场分析报告。报告涵盖 9 大板块:KPI 概览、销量趋势、品牌格局、品牌明细、自营vs第三方、价格分析、竞品追踪、热销产品、运营建议。
触发识别
当用户提出以下类型的请求时,加载此 Skill:
- "生成/更新 [品类] Wxx-Wxx 市场报告"
- "分析 [类目] Top100 数据"
- "追踪以下竞品 ASIN 的表现"
- "把 [品类] 报告更新到 Wxx"
工作流程(务必按顺序执行)
Phase 1: 解析请求参数
从用户输入中提取以下参数:
| 参数 | 来源 | 示例 |
|------|------|------|
| 品类名称 | 用户指定 | "Tower Fan" / "取暖器" / "空气净化器" |
| NodeID | 用户指定或工作记忆中已知 | 241127011 |
| 周期范围 | 近6周自动计算(见下方规则) | W18-W23 |
| 竞品 ASIN 列表 | 见下方「各品类竞品 ASIN 清单」 | 每个品类固定 10-12 个 |
| 价格筛选条件 | 可选 | price ge 90 / price 20-90 区间 |
| 输出路径 | 默认为 D:\市场分析\ | 用户可覆盖 |
近6周周期自动计算规则
默认数据周期为近6周,根据当前日期按以下公式自动计算:
1. 找到"昨天"所在的周一 → 即上周一
2. 从上周一往前推 5 周 → 得到最早周一的日期
3. 最早周一 → 上周日为 6 周完整周期
示例(当前日期 2026-06-10):
- 昨天 = 2026-06-09(周二)
- 上周一 = 2026-06-01
- 最早周一 = 2026-04-27(W18)
- 上周日 = 2026-06-07(W23)
- 完整周期:2026-04-27 至 2026-06-07 = W18-W23
各周日期(始终按周一到周日):
- W18: 2026-04-27 至 2026-05-03
- W19: 2026-05-04 至 2026-05-10
- W20: 2026-05-11 至 2026-05-17
- W21: 2026-05-18 至 2026-05-24
- W22: 2026-05-25 至 2026-05-31
- W23: 2026-06-01 至 2026-06-07
Python 实现:
import datetime
today = datetime.date.today()
yesterday = today - datetime.timedelta(days=1)
# 找到上周一
days_since_monday = yesterday.weekday()
last_monday = yesterday - datetime.timedelta(days=days_since_monday + 7)
# 往前推5周得最早周一
first_monday = last_monday - datetime.timedelta(weeks=5)
# 上周日
last_sunday = last_monday + datetime.timedelta(days=6)
# 生成6周的起止日期
weeks = []
for i in range(6):
mon = first_monday + datetime.timedelta(weeks=i)
sun = mon + datetime.timedelta(days=6)
week_num = mon.isocalendar()[1]
weeks.append({'label': f'W{week_num}', 'start': mon.strftime('%Y-%m-%d'), 'end': sun.strftime('%Y-%m-%d')})
询问规则:如果用户提供了品类名但没有 NodeID,先查询 Sorftime 确认 NodeID。如果品类在下方的竞品清单中,直接使用清单中的 ASIN,无需询问。
Phase 2: 获取数据(通过 MCP 工具)
2.1 Sorftime MCP — 类目 Top100 报告
使用 Sorftime MCP 的 category_report_from_history 获取每周的 Top100 报告:
调用方式: mcp__sorftimeMCP__category_report_from_history
参数: nodeId, startDate (该周周一), endDate (该周周日)
对每个周分别调用一次(6 次调用,按 Phase 1 中自动计算的周范围),从每次返回中提取:
- 总销量(sum of monthly sales)
- 总销售额(sum of monthly revenue)
- 平均价格(weighted average)
- 各品牌销量 & 份额
- 亚马逊自营占比
- Top 产品列表(ASIN, 品牌, 销量, 价格, 评分)
注意:Sorftime 趋势类工具(category_trend, product_trend)返回的是月度数据,不适用于周度报告。周度数据必须从 category_report_from_history 按周提取。
数据来源一致性规则:不同品类、不同周次的报告如需复用数据(如旧报告中的过滤后数据),必须先用当前 API 抽查至少 1 周数据验证一致性。若差异超过 50%,必须全量重抓。严禁直接复制旧报告的品牌和销量数据而不验证。本条规则适用于价格过滤品类(压缩机除湿机、半导体除湿机等需按价格区间筛选的场景)。
2.2 SellerSprite MCP — 补充数据(可选)
当需要关键词分析或竞品深度数据时,使用 SellerSprite MCP:
调用方式: mcp__sellersprite_mcp__[工具名]
可用工具包括关键词调研、竞品对比等。
2.3 竞品单品数据
如果用户提供了竞品 ASIN 列表,对每个 ASIN 从每周的 Top100 报告中查找匹配的 ASIN 数据,提取:
- 周度月化销量
- 周度单价
- 周度排名
- 最新周评分
Phase 2.5: 数据完整性校验与异常检测(强制执行)
核心原则①:严禁使用近似值/估计值/取整值。 所有数字必须直接从 MCP API 返回数据中精确提取,不得人为四舍五入、不得基于趋势估算缺失周数据、不得用平均值插值。每个指标(月化销量、销售额、均价、自营占比、品牌份额)必须是 API 返回的精确计算结果。
核心原则②:严禁复用旧报告中的任何数据。 所有品牌销量、KPI、竞品数据必须从当前 MCP 调用中提取。不可从旧 HTML 报告或旧 JSON 文件中复制。
规则 1:禁止复用旧报告数据
- 任何品类、任何周次的数据必须从 MCP 实时获取,不得从旧 HTML 报告或旧 JSON 文件中复制
- 包括过滤后的子品类数据(如 ">= $90 压缩机"、"$20-$90 半导体")也必须从当次 API 调用中重新过滤
- 原因:Sorftime 持续优化销量估算模型,历史数据会被追溯修正。实测同一日期范围、间隔数周调用 API,W20 销量可能差 9%、W21 差 22%。旧报告中的数据 = 当时算法的快照,不可信。
- 识别伪造数据的信号:如果一份报告中连续多周数据完全相同(如 W20=W21=W22=15,743),说明数据不是来自 API 实时调用,报告不可用
规则 2:新旧报告对比复核(生成后必须执行)
- 若工作区存在该品类的旧报告,新报告生成后必须对比重叠周数据
- 重叠周的 Top100 销量偏差超过 10% → 必须核实哪份数据正确
- 如果新数据正确:保留新数据,在报告中标注「旧报告该周数据已修正」
- 如果旧数据正确:说明 MCP 返回异常,需要重新拉取
- 品牌排名若发生重大变化(Top3 品牌不同),同样需要复核
规则 3:生成前全量检查
- 每份报告生成前,至少抽查 1 周的原始 API 数据(未经处理的产品列表)
- 对比该周的 Top100 销量、Top1 品牌销量、Top3 品牌份额是否与报告一致
- 价格过滤品类(压缩机 $90+、半导体 $20-90)需核实过滤后产品数量是否合理(不应少于 Top100 中同类产品的 90%)
- 若发现任何不一致,必须全量重抓该周数据
异常值检测(具体阈值):
- 亚马逊自营占比:与同品类其他 5 周均值偏差超过 20 个百分点 → 标注为「API 数据异常」
- Top100 销量:与相邻两周相比变化超过 40% → 核查原始数据
- 平均价格:与相邻两周相比变化超过 30% → 核查原始数据
若发现异常值,在报告的对应分析块中注明,不可将异常值当作真实市场变化来分析。
Phase 3: 数据处理与计算
基于原始数据计算以下指标:
1. KPI 汇总:
- **Top100 月化销量 = API 返回的 100 个产品月销量之和**(使用 `统计` 汇总数据)
- **Top100 月化销售额 = API 返回的 100 个产品月销额之和**
- 6周累计 → sum(all_weeks)
- 周均销量 → avg(weekly_sales)
- 平均客单价 → 总销额 / 总销量
- Top3 品牌集中度 → avg(top3_share across weeks)
2. 品牌分析:
- **品牌销量 = 该品牌在 Top100 中所有 ASIN 的月销量之和**(使用 API `统计` 字段的品牌销量排名)
- 不可用单个 ASIN 代表整个品牌(如 MOOKA 有 9 个 ASIN,品牌合计 22,837 ≠ 单个 ASIN 的 4,466)
- 每周 Top10 品牌销量排名(按品牌合计销量排序)
- 每周各品牌份额(%) = 品牌合计销量 / Top100 总销量
- 最新周品牌份额用于饼图/环形图
- Top5 品牌 6 周趋势数据
3. 渠道分析:
- 每周亚马逊自营占比
- 每周第三方卖家占比 = 100 - 自营占比
4. 竞品追踪:
- 每个 ASIN 的 6 周销量数组
- 每个 ASIN 的 6 周价格数组
- 最新周评分
5. 热销产品:
- 最新周 Top10 产品的 ASIN、品牌、销量、价格
Phase 4: 生成 HTML 报告(基于模板)
4.0 核心原则:模板占位符替换,禁止修改结构
报告生成 = 准备数据 → 填充模板。 不再修补旧报告。
模板文件:assets/template.html
变量文档:references/template-variables.md
流程(3 步):
- 从 MCP 数据计算所有变量值(JS 数据、分析文字、表格行、KPI 卡片、数轴范围)
- 读取
assets/template.html→ 用str.replace逐个替换{{KEY}}占位符 - 写出 HTML → 运行验证脚本
关键约束:
- 模板中只有
{{KEY}}是变量,其他 HTML/CSS/JS 结构一字不改 - 所有
{{KEY}}都必须被替换,不允许残留任何占位符 - Chart 数轴范围(
{{CHART*_*}})必须根据实际数据计算,不得使用模板中的默认值 - 变量文档
template-variables.md列出了全部占位符和计算规则
4.1 使用模板
报告必须完全遵循 assets/template.html 的结构和样式。仅替换数据,不改变布局、CSS、图表类型或显示风格。
4.2 需要替换的内容
-
报告标题和元数据(header 区域)
- 品类中文名 + 英文名
- NodeID
- 周期范围
- 生成日期
-
KPI 卡片(kpi-grid 区域)
- 累计月化销量
- 累计月化销售额
- 周均销量和平均客单价
- Top3 品牌集中度
-
Chart.js 数据变量(script 区域)
weeks数组(6 周标签,如 ['W18','W19','W20','W21','W22','W23'])sales数组(每周 Top100 月化销量)revenue数组(每周 Top100 月化销售额)avgPrice数组(每周平均价格)top3Share数组(每周 Top3 品牌份额)amzShare数组(每周亚马逊自营占比)brandNames数组(Top10 品牌名)brandSalesData对象(每个品牌 6 周销量)brandColors对象(品牌配色映射)latestWeekShares数组(最新一周各品牌份额%,替换 w22Shares)compLabels/compKeys/compData(竞品数据)tpNames/tpSales/tpPrices(热销产品数据)
-
分析解读文字(analysis-block 区域)— 必须基于实际数据重新撰写,严禁保留旧模板文字
品类专家视角(核心原则):
- 站在该品类的独立专家角度撰写分析,不做跨品类数值对比
- 严禁出现跨品类数值对比(如对比其他品类的品牌集中度、自营占比等)
- 该品类数据高或低,只能与该品类自身历史趋势对比,或引用行业通用基准
- 分析应聚焦本品的季节性、竞争格局、价格带、渠道特点
各分析块内容要求:
- 趋势解读:引用实际的峰值周、变化百分比、品牌数据
- 品牌格局分析:引用实际 Top10 品牌名和实际份额数据
- 渠道结构分析:引用实际亚马逊自营占比范围,异常值需标注
- 价格策略洞察:引用实际均价区间和变化趋势
- 竞品洞察:引用实际 ASIN 的销量变化(使用本次获取的数值)
- 运营决策建议:结合该品类季节性特点和实际数据撰写
- 自查规则:生成后搜索旧品牌名、旧周引用、其他品类名(当前品类无关的品牌/品类名),若有残留必须清除
-
数据表格
- 品牌份额明细表
- 竞品周度追踪表
- 类目核心数据汇总表
4.3 图表要求(务必严格执行)
核心库版本:Chart.js 4.4.0 + chartjs-plugin-datalabels 2.2.0(CDN 加载)
JS 语法完整性检查(生成后必须验证):
- 每个
const声明必须独占一行或以;结束,严禁多个 const 挤在同一行 - 必须恰好 9 个
new Chart(...)调用,对应 9 个 canvas 元素 - JS script 块不得重复(不能有两个
<script>块) - 所有 canvas id 必须与 new Chart 调用的 id 一一匹配
关键修复:datalabels 插件在 v2.2.0 中 context.label 不可用,必须使用以下方式获取标签:
context.chart.data.labels[context.dataIndex]
配色方案:
- 涨(增加、上升)→ 红色 (
#e53935) - 跌(减少、下降)→ 绿色 (
#43a047) - 品牌配色:每个品牌分配独立颜色,区分度足够
9 个图表清单及其类型(不可更改):
chart_sales_trend— Bar + Line 双轴(销量柱状 + 销售额折线)chart_brand_share_latest— Doughnut(最新周品牌份额环形图,显示品牌名+百分比)chart_brand_trend— Line(Top5 品牌 6 周趋势折线)chart_brand_share_bar— Horizontal Bar(最新周品牌份额横向柱状图)chart_amz_vs_3p— Stacked Bar(亚马逊自营 vs 第三方堆叠柱状图)chart_price_trend— Line(平均价格趋势折线)chart_brand_concentration— Line(Top3 品牌集中度趋势)chart_competitor_sales— Line(竞品销量趋势,默认仅显示前5条)chart_top_products— Bubble(最新周 Top10 产品气泡图,x=价格, y=销量, r=销售额)
Phase 5: 验证
生成 HTML 后,使用 preview_url 预览报告,确认以下全部通过。
严格执行自查流程(报告生成后必须逐项核对,通过后才可交付):
JS 层验证(自动检查,用 Python 脚本跑):
- 恰好 9 个
new Chart(...)调用(模板有 2 个 script 块时可能是 18 个,属于正常) - 零个「多 const 挤一行」的语法错误行
- 零个
const brandColors重复声明(同一 script 块内) - 所有 canvas id 与 getElementById 参数一一对应
- 数轴范围检查:所有
min:/max:硬编码值必须适配当前品类数据范围,不得保留模板中的旧值
内容层验证(自动检查,用 grep/count):
- 全文中搜索旧品牌名(DREO/LEVOIT/Amazon Basics/Honeywell/Dyson等)——必须为 0
- 全文中搜索旧周期引用 → 必须为 0
- 全文中搜索旧模板中的品类名 → 必须为 0
- 全文中搜索其他品类名(净化器/取暖器/除湿机)——analysis block 中必须为 0
- 全文中搜索跨品类对比短语("远低于""远超""品类之外")——必须为 0
Section 全覆盖检查(报告有 9 个 section,每个都必须更新):
- Section 1: 趋势解读文字 → 必须基于当前品类数据
- Section 2: 品牌格局分析文字 + 品牌份额百分比表(10行) → 必须更新
- Section 3: 品牌销量表 → 必须更新
- Section 4: 渠道分析文字 → 必须更新
- Section 5: 价格分析文字 → 必须更新
- Section 6: 竞品追踪表(2个副本) + 竞品分析文字 → 全部更新
- Section 7: 热销产品分析文字 → 必须更新
- Section 8: 4个洞察卡片 → 全部更新
- Section 9: 类目核心数据汇总表 → 表头+数据行全部更新
严禁跳过的关键陷阱:
- 模板中竞品表出现 2 次(Section 6 内 + 另一个副本),两个都必须替换
- 品牌份额百分比表(Section 3)与品牌销量表是不同的两张表,不得混淆
- 分析文字在 Section 1-5 和 Section 6-7 分散出现,不得只替换部分
Phase 5.5: 数据准确性复查(输出前强制执行)
生成报告后、交付给用户前,必须逐项复查。不通过则不得输出。
复查 1:竞品 ASIN 数量核对
- 打开 Skill 中的「各品类竞品 ASIN 清单」
- 数一数报告中的竞品表
compKeys数组长度是否等于该品类的 ASIN 数量 - 空气净化器=12个,塔扇=10个,取暖器=9个,压缩机=10个,半导体=10个
- 不匹配 = 立即修正
复查 2:品牌数据来自全部 Top100 产品
- Top100 的销量/销售额 = 全部 100 个产品的月销量/月销额之和,来自 API 返回的
统计字段 - 品牌销量 = 该品牌在 Top100 中所有 ASIN 的月销量之和,不是单个 ASIN 的数据
- 特例:如 MOOKA 在 Top100 中有 9 个 ASIN(PR1、B-D02L、KJ190、M05、M01 等),品牌销量=所有 9 个 ASIN 之和
- API 返回的"统计-品牌销量排名"已经聚合了各品牌总销量,直接使用此数据
- 错误做法:取品牌下销量最高的一个 ASIN 代表全品牌
- 正确做法:使用 API
统计中的品牌汇总数据,或遍历 Top100 按品牌名累加
复查 3:分析文字数据一致性
- 抽查报告中引用的具体数字(如"MOOKA W23 22,837台")是否与 JS 数据(brandSalesData)一致
- 品牌排名是否与实际数据匹配(不能 W23 说 MOOKA 排名第 7 但实际数据是第 2)
复查 4:跨品类引用 + 旧数据残留
- 执行 Phase 5 中的 grep 验证脚本
Phase 6: 清理
完成报告后,删除所有中间脚本和数据文件(_extract_*.py, _gen_*.py, _v*_data.json 等),仅保留最终 HTML 文件。
Phase 7: 记录
在 D:\市场分析\.workbuddy\memory\YYYY-MM-DD.md 追加本次任务摘要,更新 MEMORY.md 如有新增品类/NodeID/竞品信息。
各品类竞品 ASIN 清单
重要:以下竞品 ASIN 为固定追踪列表。生成报告时自动使用对应品类的 ASIN,无需用户每次输入。
塔扇 (Tower Fan)
NodeID: 241127011 | ASIN 数量: 10
B0BVZFQ4DF, B09MKPDJRT, B08P5NNNL5, B0GH7X9FGS, B08P4Z3B5X,
B01N0LQJN6, B0DZ6VRPT7, B0GLH4CDHV, B09M8PMW26, B0GHNVWQKZ
取暖器 (Heater)
NodeID: 19240644011 | ASIN 数量: 10(去重后 9)
B0C6FCKQML, B074MX8VN5, B07V6M3PDX, B097RG67QB, B095PP1GZR,
B0FBRW761D, B0CCJGKY4M, B0C8TX47J6, B0DBQV5DG2
注:B097RG67QB 在表格中出现 2 次,去重后共 9 个独立 ASIN。
空气净化器 (Air Purifier HEPA)
NodeID: 需查询 | ASIN 数量: 12
B07VVK39F7, B0FNDG2TNK, B0B4ZSKPNL, B0B9SL7894, B0DTHSRTD4, B08PJQ3MWB,
B09QZDKQLF, B0GQT9S6V4, B0DSC36LB6, B0DCBC8KKV, B0GGH7HTCQ, B0GK5WP7TV
压缩机除湿机 (Compressor Dehumidifier)
NodeID: 需查询 | 典型价格: $90+ | ASIN 数量: 10
B0D1C6HWFF, B08ZMY8BC8, B0B5V2YZPZ, B0D1H9DXJZ, B0DR7TZGV8,
B0BVZ62Y3M, B07NRDBBH5, B0DMW1GCFV, B0DBLKHJC1, B0FRQVWSS4
半导体除湿机 (Semiconductor Dehumidifier)
NodeID: 需查询 | 典型价格: $20-$90 | ASIN 数量: 10
B0DXKRFFGM, B0H13ZY2W4, B0DR26KDBG, B0GYFR2YM2, B0GR5F4CJ9,
B0GZL6VPT7, B0F62JT6S6, B0FJ1F5V5B, B0GZMFX3TN, B0BZYLH1RQ
常见品类参考
| 品类 | NodeID | 典型价格范围 | 竞品 ASIN 数 | |------|--------|-------------|-------------| | Household Tower Fans (塔扇) | 241127011 | $25-$200 | 10 | | 取暖器 (Heaters) | 19240644011 | $30-$150 | 9 | | 空气净化器 HEPA | 需查询 | $50-$300 | 12 | | 压缩机除湿机 | 需查询 | $90+ | 10 | | 半导体除湿机 | 需查询 | $20-$90 | 10 |
核心陷阱与经验教训
以下从半导体除湿机报告 6 轮重做中总结,生成任何品类报告时必须严格遵守:
陷阱 1:禁止用 str.replace 修补模板
错误方式:复制旧报告 → 用 Python str.replace 逐个替换数据。
后果:JS 变量重复声明、图表 JS 语法错误、模板残留旧数据。
正确方式:从零程序化生成完整 HTML,数据变量和 chart 配置全部由代码产出。
陷阱 2:参考模板的 chart 配置必须原样复制
错误方式:自己手写简化版 new Chart(...) 配置。
后果:图表呈现效果与参考模板不一致(缺少 grid 虚线、tick 格式不同、datalabels 缺配置等)。
正确方式:从参考模板的 <script> 块中提取全部 9 个 new Chart(...) 配置,一字不改复制。只替换 chart 标题中的 W22→W23 和品牌引用(Uthfy 等)。
陷阱 3:参考模板的 chart section 夹带旧数据
参考模板的 script 块中除了 new Chart(...) 之外,还可能包含旧的 const compLabels = [...]、const tpNames = [...] 等数据声明。复制 chart 配置前必须清洗掉这些旧声明,否则会导致:
- 新旧品牌名共存(DREO 残留)
- JS 变量重复声明错误
陷阱 4:图表数轴 min/max 必须适配当前品类
assets/template.html 中图表数轴使用 {{CHART*_*}} 占位符,生成时必须根据实际数据计算,不可填入固定值:
| 图表 | 占位符 | 计算规则 |
|------|--------|---------|
| 价格趋势 y 轴 | {{CHART6_YMIN}}, {{CHART6_YMAX}} | min(avgPrice)-2 ~ max(avgPrice)+2 |
| 品牌集中度 y 轴 | {{CHART7_YMIN}}, {{CHART7_YMAX}} | min(top3Share)-10 ~ max(top3Share)+10(取整5) |
| 气泡图 x 轴(价格) | {{CHART9_XMIN}}, {{CHART9_XMAX}} | min(tpPrices)-10 ~ max(tpPrices)+15 |
| 气泡图 y 轴(销量) | {{CHART9_YMAX}} | max(tpSales)×1.2 向上取整 |
| 品牌份额柱 x 轴 | {{CHART4_XMAX}} | max(shares)×1.3 向上取整5 |
陷阱 5:品牌份额百分比表 ≠ 品牌销量表
模板 Section 3 包含两张不同的表:
- 品牌份额百分比表:排名、品牌、W18-W23 份额(%)、趋势 —— 用于展示份额对比
- 品牌销量明细表:品牌、W18-W23 销量(台)、趋势 —— 用于展示绝对销量
两张表都必须更新,不可混淆。
陷阱 6:竞品追踪表在模板中可能出现 2 次
Section 6 的竞品表可能在模板中出现两处(section 内 + section 外),两处都必须替换。
陷阱 7:全部 9 个 Section 都含品类相关文字
Section 1-5 的分析文字、Section 6-7 的竞品/热销产品分析、Section 8 的 4 个洞察卡片,都必须替换为当前品类的内容。遗漏任何一处都会残留模板中的旧引用。
陷阱 8:最终验证必须用 grep 搜索旧数据
生成后用 Python 脚本搜索以下关键词,任一项不为 0 则报告不合格:
- 模板中出现的旧品牌名(如 DREO, LEVOIT, Amazon Basics 等)
- 不在当前周范围内的旧周期标签
- 模板品类名(与当前品类不同的品类名称)
- 跨品类对比:远低于, 远超, 品类之外
- 报告末尾署名为数据来源 Sorftime & SellerSprite + 生成日期
Scan to join WeChat group