Ver código fonte

feat: 补充 shelf-ecommerce-review 技能文件(SKILL.md+2脚本)

dou 1 mês atrás
pai
commit
ea8b8d2c03

+ 94 - 0
skills/shelf-ecommerce-review/SKILL.md

@@ -0,0 +1,94 @@
+---
+name: shelf-ecommerce-review
+description: 货架电商复盘技能(天猫/京东/拼多多)。输入经营数据文件与历史复盘稿件,按三阶段流程(输入分诊 → 程序化处理 → 成稿输出)产出完整复盘报告。用户要求"复盘 / 月度经营复盘 / 货架复盘"时使用。
+---
+
+# 货架电商复盘技能
+
+人工 SOP 的 AI 简化版。核心原则:**数据步骤程序化、判断步骤 AI 化、格式步骤模板化。**
+
+## 与人工流程的对照(省了什么、留了什么)
+
+| 人工步骤 | AI 处理方式 |
+|---|---|
+| 逐平台后台拉数、截图 | 不省:数据必须企业提供(见自检清单),AI 负责自动识别文件结构 |
+| 手动整理 Excel、填公式 | **程序化**:脚本读表,公式直接从历史表格移植重算 |
+| 贴表格截图到文档 | **省略**:直接输出真实数据表 |
+| 逐品线手工对比竞品 | **半程序化**:数据齐则自动生成对比矩阵;不齐降级为定性对比并标注缺口 |
+| 写归因和下一步 | AI 主体工作(判断步骤,人审核) |
+| 管理会汇报稿 | AI 直接产出 |
+
+## 阶段一:输入材料(分诊登记)
+
+只收:docx / xlsx / csv / pdf / html / 图片。长语音、长视频不收——请用户转文字或给会议纪要。
+
+收到文件后按四类登记(文件名、类型、覆盖周期):
+
+| 类型 | 判断标准 | 用途 |
+|---|---|---|
+| A 规则/知识 | SOP、方法论、口径说明 | 决定分析维度与指标 |
+| B 历史成品稿件 | 以往复盘 docx / html | 输出格式模板 |
+| C 数据源 | 平台后台导出 Excel、目标表 | 计算原料 |
+| D 背景补充 | 会议纪要、竞品截图、乱价清单 | 归因上下文 |
+
+登记后先给用户一份《材料清单》确认;缺哪类直接说(见阶段三自检清单)。
+
+## 阶段二:处理(程序化 + 分析)
+
+**优先级:能用脚本算的绝不手数。** 可复用脚本:`process/` 目录(提取 + 审计一体)。
+
+1. **表格消化**:用 python(openpyxl/pandas) 逐 sheet 读取 C 类文件,弄清行列结构、表头、单位、公式。
+   - ⚠️ **read_only=True 的维度缓存会失真**(实测显示 [1行x1列] 但实际有 17985 个单元格)。先用底层 XML 数 `<c>` 标签判断真实数据量,再决定读法;或直接非 read_only 加载。
+   - 行列结构要动态识别(从表头行读月份/指标),不硬编码列号;行层级(渠道→品类树)用标签匹配。
+2. **公式继承**:历史 Excel 里已有的公式(完成率、环比、费比、GP、品类占比、ROI)直接移植到新数据重算,不重新发明。公式形态用 `cell.value.startswith("=")` 扫描收集。
+3. **总量与明细分开**:总量取「全店」行;品类行只算结构占比和环比。两者相减的差额是未列出小品类,显式记入《数据问题清单》,超过 8% 标记"需确认"(实测平台分销差额 19%)。
+   - ⚠️ **渠道命名口径**(企业已确认):源表「平台分销」行 = 电商分销;管理会汇报中的「平台分销」= 社交电商 + 电商分销 合并口径。对外汇报用合并口径,对内看源表明细。已验证:合并后 7-8月 243.8万、8月 155.3万、环比 +68.1%,与成品稿完全闭合。
+4. **加和校验必做**:每张表算完先做 品类合计 vs 全店、各渠道 vs 板块总计 的交叉验证,过了才进分析。
+5. **标准五表自动生成**:
+   - 目标达成表:GSV / 完成率 / GP,分平台分月
+   - 品类结构表:各品类销售额、占比、环比/同比
+   - 流量结构表:手搜 / 品牌词 / 付费 / 内容渠道占比变化
+   - 竞品对比表:核心品线 vs 竞对(访客、排名、付费效率、人群质量分)
+   - 下一步追踪表:上期复盘"下一步"事项的完成情况
+6. **数字三查**(输出《数据问题清单》):
+   - 口径:GSV 还是支付 GMV,是否剔退款
+   - 单位:万元 / 元统一(实测源表单位是"元")
+   - 时间:区间对齐,大促月单独标注
+7. **归因分析**:每个显著变化必须有归因(大促 / 投放调整 / 竞品动作 / 乱价 / 人事变动 / 明星直播等一次性事件);写不出归因的标记"待确认",攒成问题问用户,不硬编。一次性事件(如明星进播)要显式剔除后再评趋势。
+
+## 阶段三:输出(成稿)
+
+**有 B 类历史稿件** → 先读稿提取四样东西:章节骨架、品线写法(现状→归因→下一步)、句式(结论先行、数字+判断混合)、表格样式,然后套用成稿。实测骨架(来源 `管理会/货架7-8月复盘.docx`):
+
+```
+板块增长结论(各渠道增速+增量占比,一句话总结增长引擎)
+├─ 天猫:市场排名 → 店铺整体 → 竞对差距(货品/流量/价格段/人群)→ 流量采买与转化效率(色修→儿童→香氛→修护,每品线:现状数字→差距归因→下一步量化目标)
+├─ 京东:大盘 → 品类概况 → 站内费用 → 分类目分析(色修/修护/儿童/胖管/漱口水)→ CPS/CID
+├─ 拼多多:竞品打法拆解(店铺矩阵/货盘/链接矩阵)→ 我们的动作与效果 → Q4 规划
+└─ 下一步规划(每品线一句:动作 + 量化目标)
+```
+
+**没有历史稿件** → 用同样的内置骨架。硬性要求:每条下一步必须带量化目标和时间(如"CID 日均 5000、ROI 1.3-1.4,1-2 月内")。
+
+交付物 = 复盘正文 + 《工作汇报》(用了哪些数据、算了什么、哪些数字待确认)。
+
+## 启动自检(每次收到复盘任务先做)
+
+**缺文件 → 一次性列出需要企业提供的:**
+
+必需:
+- 各平台后台导出:天猫生意参谋(实时概况/流量/品类/竞品/客群)、京东商智+京准通、拼多多后台
+- 当期目标表(GSV / GP 分解到平台)
+- 费用明细(平台费用、推广花费)→ 算费比和 GP
+
+可选增强:
+- 竞品数据(久谦 / 蝉魔方导出或前台截图)
+- 上期复盘稿(做"下一步"追踪)
+- 特殊事件说明(大促节奏、人事变动、调价)
+
+**缺知识 → 直接问,不猜:**
+- 指标口径(GSV 还是支付 GMV?费比分母是什么?)
+- 输出格式(docx / HTML?给谁看?多长?)
+- 建议深度(能否直接给预算数字?)
+
+**材料齐、问题清 → 明确回复:"材料齐了,我开始干活,请等待。"** 干活期间不打断用户,直到交付。

+ 118 - 0
skills/shelf-ecommerce-review/提取渠道品类数据.py

@@ -0,0 +1,118 @@
+#!/usr/bin/env python3
+"""
+渠道品类数据提取 + 审计脚本(货架电商复盘技能·阶段二可复用工具)
+
+用法:每期复盘改 INPUT / OUT_JSON / OUT_MD 三个路径即可重跑。
+输入要求:源表格式与「传统电商各平台业绩情况26年9.9.xlsx」一致
+  - 第1行=月份表头,第2行=指标行(GSV/GP/GP率),A列=渠道→品类树
+  - 渠道层下一行是「全店」,品类行按标签匹配
+
+输出:
+  1. JSON:渠道 → 品类 → {月份+指标: 值},含「未列出品类」差额
+  2. Markdown 审计表:加和校验结果(品类合计 vs 全店),差额>8% 标记需确认
+"""
+import openpyxl, json, sys
+
+INPUT   = "/Users/dou/Desktop/BOP/管理会/传统电商各平台业绩情况26年9.9.xlsx"
+SHEET   = "各渠道品类销售数据"
+OUT_JSON = "/Users/dou/Desktop/BOP/7-8月复盘/process/渠道品类数据_4-8月.json"
+OUT_MD  = "/Users/dou/Desktop/BOP/7-8月复盘/process/审计报告.md"
+MONTHS  = ["5月", "6月", "7月", "8月"]          # ← 每期改这里
+THRESHOLD = 8.0                                  # 差额占比告警阈值 %
+
+CHANS = ["天猫", "京东", "猫超", "唯品", "拼多多", "平台分销", "社交电商"]
+# 渠道命名口径(企业已确认):源表「平台分销」行=电商分销;
+# 对外汇报的「平台分销」= 社交电商 + 电商分销 合并。MERGE_GROUPS 生成合并行。
+MERGE_GROUPS = {"平台分销(合并)": ["社交电商", "平台分销"]}
+CATS  = ["色修", "修护", "胖管香氛", "圆管香氛", "儿童", "儿童牙膏", "黑蜂",
+         "其他牙膏", "条装漱口水", "瓶装漱口水", "口喷", "其他品类"]
+
+def main():
+    wb = openpyxl.load_workbook(INPUT, data_only=True)   # 非 read_only:规避维度缓存失真
+    ws = wb[SHEET]
+    rows = list(ws.iter_rows(values_only=True))
+    wb.close()
+
+    # ---- 1. 动态列映射:月份(第1行) × 指标(第2行) → 列号 ----
+    month_col, cur = {}, None
+    for i, v in enumerate(rows[0]):
+        s = str(v) if v is not None else ""
+        if "月" in s or "Q" in s:
+            cur = s
+        m2 = str(rows[1][i]) if i < len(rows[1]) and rows[1][i] is not None else ""
+        if cur and m2 in ("GSV", "GP", "GP率"):
+            month_col[(cur, m2)] = i
+    want = [(m, k) for m in MONTHS for k in ("GSV", "GP")]
+    have = {k: v for k, v in month_col.items() if k in want}
+    missing = [k for k in want if k not in month_col]
+    if missing:
+        print(f"⚠️ 源表缺少这些月份/指标列: {missing}")
+
+    # ---- 2. 行扫描:渠道→全店/品类(标签匹配,不硬编码行号)----
+    result, i, cur_chan = {}, 2, None
+    while i < len(rows):
+        lab = str(rows[i][0]).strip() if rows[i][0] is not None else ""
+        if lab in CHANS:
+            cur_chan, result[cur_chan] = lab, {}
+        elif cur_chan and (lab == "全店" or lab in CATS):
+            rec = {}
+            for k, ci in have.items():
+                v = rows[i][ci] if ci < len(rows[i]) else None
+                if isinstance(v, (int, float)):
+                    rec[f"{k[0]}{k[1]}"] = round(v, 2)
+            if rec:
+                key = "儿童" if lab == "儿童牙膏" else lab   # 口径统一
+                result[cur_chan].setdefault(key, {}).update(rec)
+        i += 1
+
+    # ---- 3.5 合并口径行(如 平台分销(合并)=社交电商+电商分销)----
+    for merged_name, parts in MERGE_GROUPS.items():
+        merged = {}
+        for ch in parts:
+            for cat, rec in result.get(ch, {}).items():
+                for k, v in rec.items():
+                    if k.endswith("差额"):        # 差额不可跨渠道相加,跳过
+                        continue
+                    merged.setdefault(cat, {})[k] = round(merged.get(cat, {}).get(k, 0) + v, 2)
+        if merged:
+            result[merged_name] = merged
+
+    # ---- 4. 审计:品类合计 vs 全店 → 未列出品类差额 ----
+    audit = []
+    for ch, cats in result.items():
+        if "全店" not in cats:
+            audit.append((ch, "缺全店行", None, None)); continue
+        for suffix in ("GSV", "GP"):
+            m = f"{MONTHS[-1]}{suffix}"                     # 审计最后一个月
+            tot = cats["全店"].get(m)
+            s = sum(c.get(m, 0) for k, c in cats.items() if k != "全店")
+            if tot:
+                gap = round(tot - s, 2)
+                cats.setdefault("未列出品类", {})[f"{MONTHS[-1]}{suffix}差额"] = gap
+                pct = abs(gap) / tot * 100
+                audit.append((ch, m, gap, pct))
+
+    with open(OUT_JSON, "w", encoding="utf-8") as f:
+        json.dump(result, f, ensure_ascii=False, indent=1)
+
+    # ---- 4. 输出审计报告 ----
+    lines = ["# 数据提取审计报告", "",
+             f"- 源表:`{INPUT}` → sheet `{SHEET}`",
+             f"- 月份:{'、'.join(MONTHS)}|提取单元格映射 {len(have)} 列", "",
+             "| 渠道 | 指标 | 未列出品类差额(元) | 占比 | 判定 |", "|---|---|---:|---:|---|"]
+    for ch, m, gap, pct in audit:
+        if gap is None:
+            lines.append(f"| {ch} | {m} | - | - | ⚠️ 结构异常 |")
+        else:
+            flag = "⚠️需确认" if pct > THRESHOLD else "OK"
+            lines.append(f"| {ch} | {m} | {gap:,.0f} | {pct:.1f}% | {flag} |")
+    lines += ["", "> 差额 = 全店行 − 已列品类合计,即源表未单列的小品类(如牙刷等)。",
+              "> 总量一律取「全店」行;品类行仅用于结构与环比,不用于推总量。"]
+    with open(OUT_MD, "w", encoding="utf-8") as f:
+        f.write("\n".join(lines))
+
+    print("\n".join(lines[7:]))
+    print(f"\n✅ 数据 → {OUT_JSON}\n✅ 审计 → {OUT_MD}")
+
+if __name__ == "__main__":
+    main()

+ 81 - 0
skills/shelf-ecommerce-review/深挖分析.py

@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+"""
+深度分析提取脚本(货架电商复盘技能·阶段二扩展工具)
+四大数据源 → JSON:
+  1. 损益底稿(月度GSV/GP、分渠道费用结构、分品类GP)——26年7月传统电商管理报表-V2
+  2. 天猫单品经济模型(推广占比/营销贡献/180天回购)——天猫数据采集-最新版
+  3. 抖音种草 by月×产品(看后搜成交/花费/ROI)——抖音种草-各产品整体完成进度by月
+  4. 价格带四品牌矩阵(8月生意参谋)——价格段分析
+输出:process/深挖数据.json
+"""
+import openpyxl, json, warnings
+from collections import defaultdict
+warnings.filterwarnings("ignore")
+
+BOP = "/Users/dou/Desktop/BOP"
+OUT = f"{BOP}/7-8月复盘/process/深挖数据.json"
+out = {}
+
+# ── 1. 损益底稿 ──────────────────────────────────────
+wb = openpyxl.load_workbook(f"{BOP}/30天/26年7月传统电商管理报表-虚拟成本-初版-V2.xlsx", read_only=True)
+ws = wb["数据底稿"]
+# 列索引(已校准):1=一级渠道,7=取数品类,12=月份,20=GSV实收,22=平台扣点,26=线上站内费用,27=站外,30=物流,34=成本,37=GP
+# ⚠️ f23 与 f26 数值相同(双标签),只取 f26 避免翻倍
+mon = defaultdict(lambda: {"gsv": 0, "gp": 0})
+chan = defaultdict(lambda: defaultdict(float))
+cat = defaultdict(lambda: defaultdict(float))
+for row in ws.iter_rows(min_row=3, max_col=38, values_only=True):
+    m = str(row[12])[:6]
+    def f(i): return row[i] if isinstance(row[i], (int, float)) else 0
+    mon[m]["gsv"] += f(20); mon[m]["gp"] += f(37)
+    ch = str(row[1]) if row[1] else str(row[0])
+    chan[m][ch] += f(20); chan[f"gp_{m}"][ch] += f(37)
+    cat[m][str(row[7])] += f(20); cat[f"gp_{m}"][str(row[7])] += f(37)
+wb.close()
+out["损益_月度"] = {m: {"GSV": round(v["gsv"], 2), "GP": round(v["gp"], 2)} for m, v in sorted(mon.items()) if v["gsv"]}
+out["损益_7月分渠道"] = {ch: {"GSV": round(v, 2), "GP": round(chan["gp_202607"][ch], 2)}
+                      for ch, v in chan["202607"].items() if abs(v) > 1e4}
+out["损益_7月分品类"] = {c: {"GSV": round(v, 2), "GP": round(cat["gp_202607"][c], 2)}
+                     for c, v in cat["202607"].items() if abs(v) > 1e4}
+
+# ── 2. 天猫单品经济模型(7月) ────────────────────────
+wb = openpyxl.load_workbook(f"{BOP}/30天/天猫数据采集-最新版.xlsx", data_only=True)
+ws = wb["天猫店铺top单品情况(7月)"]
+items = []
+for row in ws.iter_rows(min_row=3, max_row=16, max_col=28, values_only=True):
+    if not row[1]: continue
+    items.append({"类目": row[0] or "", "单品": str(row[1]), "GMV": row[2] or 0,
+                  "推广占比": row[5] or 0, "营销贡献率": row[12] or 0, "回购180": row[13] or 0})
+out["天猫单品经济模型_7月"] = items
+
+# ── 3. 抖音种草 by月×产品 ─────────────────────────────
+wb = openpyxl.load_workbook(f"{BOP}/管理会/抖音种草-各产品整体完成进度by月.xlsx", data_only=True)
+ws = wb["各产品整体完成进度by月"]
+agg = defaultdict(lambda: defaultdict(float))
+cur = None
+for row in ws.iter_rows(min_row=3, values_only=True):
+    if row[0] is not None and str(row[0]).startswith("2026"):
+        cur = str(row[0])[:7]
+    if cur and row[2] and str(row[2]) != "合计":
+        def f(i): return row[i] if isinstance(row[i], (int, float)) else 0
+        k = (cur, str(row[2]))
+        agg[k]["成交"] += f(3); agg[k]["花费"] += f(4); agg[k]["条数"] += f(9)
+wb.close()
+out["抖音种草_月x产品"] = {f"{m}|{p}": {k: round(v, 2) for k, v in a.items()}
+                        for (m, p), a in sorted(agg.items())}
+
+# ── 4. 价格带四品牌(8月生意参谋) ─────────────────────
+wb = openpyxl.load_workbook(f"{BOP}/管理会/价格段分析.xlsx", data_only=True)
+ws = wb["价格段分析"]
+bands = []
+for row in ws.iter_rows(min_row=5, max_row=9, max_col=16, values_only=True):
+    bands.append({"价格带": row[0], "BOP指数": row[4], "参半指数": row[8],
+                  "高露洁指数": row[12], "舒客指数": row[16] if len(row) > 16 else None,
+                  "BOP商品数": row[1]})
+out["价格带_四品牌"] = bands
+wb.close()
+
+with open(OUT, "w", encoding="utf-8") as f:
+    json.dump(out, f, ensure_ascii=False, indent=1)
+print(f"✅ 已写入 {OUT}")
+print(f"   月度损益 {len(out['损益_月度'])}月 | 分渠道 {len(out['损益_7月分渠道'])} | 单品 {len(out['天猫单品经济模型_7月'])} | 种草 {len(out['抖音种草_月x产品'])} | 价格带 {len(out['价格带_四品牌'])}")