问题:多平台卖家的数据噩梦
开淘宝店的,往往也开了拼多多和京东。每天打开三个后台 → 分别导出 CSV → 粘贴进 Excel → 手动做对比 → 整理成老板要看的样子。这个过程每天至少 1 小时,月底汇总更是噩梦。
这是电商运营最真实的痛点。不算那些百万级大卖家——他们有 BI 团队。真正痛苦的是月销 10-200 万的腰部卖家,几百个 SKU,三四个平台,数据全在 CSV 里。
他们面临的三个核心问题:
- 数据分散 — 每个平台有自己的导出格式,字段名不一样(淘宝叫"实收金额",拼多多叫"商家实收"),没法直接对比
- 手工聚合慢 — Excel 手动合并,VLOOKUP 到处飞,容易出错
- 没有看板 — 想看一眼各平台实时占比?没有。想看 Top SKU 排名?得手工算半小时
以前怎么?用 Python + Pandas 写脚本——但 Pandas 加载三个月几十万行订单数据,8GB 内存笔记本直接卡死。或者上 BI 工具——Tableau 每人 $70/月,小卖家不舍得。
DuckDB 的方案:一个 .py 文件,零安装数据库,10 行 SQL 搞定全部。
DuckDB 解法:UNION ALL 跨平台聚合
DuckDB 最核心的优势在这里展现得淋漓尽致——它能直接读 CSV,自动推断 schema,然后用 SQL 做跨平台数据清洗和聚合。
三个平台 CSV 的 schema 不一样?没关系,用 UNION ALL BY NAME 自动按列名对齐:
SELECT '淘宝' AS platform, order_id, amount, sku, province, order_date
FROM read_csv_auto('taobao_orders.csv')
UNION ALL BY NAME
SELECT '拼多多' AS platform, order_id, amount, sku, province, order_date
FROM read_csv_auto('pdd_orders.csv')
UNION ALL BY NAME
SELECT '京东' AS platform, order_id, amount, sku, province, order_date
FROM read_csv_auto('jd_orders.csv')
以前这个操作:Pandas 读三个 CSV → 手动统一列名(3-5 行)→ concat()(1 行)→ 类型转换(3-5 行)。数据量到了 50 万行,Pandas 内存占用 2-3GB。
DuckDB 的这个操作:1 行 SQL,零拷贝,零内存浪费。DuckDB 的列式引擎只扫描你需要的列,read_csv_auto 自动处理 schema 差异。
完整代码:从 CSV 到 6 维度看板
下面这个脚本是完整的可交付方案。它会:
- 自动生成三个平台的模拟订单数据(你也可以换成真实 CSV 文件)
- 用 DuckDB 做 6 个维度的跨平台分析
- 输出两个交付物:6-Sheet Excel 报表 + 交互式 HTML 看板
前置条件
pip install duckdb pandas openpyxl plotly numpy
DuckDB 版本要求 1.5+(UNION ALL BY NAME 语法从 v0.10.0 开始支持)。
完整脚本
#!/usr/bin/env python3
"""
DuckDB 电商多平台运营看板
输出:6-Sheet Excel 报表 + Plotly 交互式 HTML 看板
"""
import duckdb
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import random
# ============ 第1步:生成模拟数据(实际使用时替换为真实 CSV 路径)============
print("🔄 生成模拟订单数据...")
def gen_orders(platform, stores, n_days=90):
"""为某个平台生成 n_days 天的订单"""
skus = [f"{platform[:2]}-{chr(65+i)}-{random.randint(100,999)}"
for i in range(random.randint(15, 25))]
categories = {
'服装': ['男装', '女装', '童装'],
'数码': ['手机', '配件', '耳机'],
'家居': ['厨具', '家纺', '收纳']
}
province_pool = ['广东', '浙江', '江苏', '上海', '北京', '四川', '湖北',
'山东', '福建', '河南']
start_date = datetime.now() - timedelta(days=n_days)
rows = []
for store in stores:
for day_offset in range(n_days):
n_orders = random.randint(5, 30)
date = start_date + timedelta(days=day_offset)
for _ in range(n_orders):
cat = random.choice(list(categories.keys()))
sub_cat = random.choice(categories[cat])
sku = random.choice(skus)
qty = random.randint(1, 5)
price = random.choice([29.9, 49.9, 79.9, 99, 129, 199, 299, 499])
rows.append({
'order_id': f"{platform[:2]}{date.strftime('%y%m%d')}{random.randint(10000,99999)}",
'order_date': date.strftime('%Y-%m-%d'),
'store': store,
'sku': sku,
'category': cat,
'sub_category': sub_cat,
'quantity': qty,
'amount': round(qty * price, 2),
'province': random.choice(province_pool),
'platform': platform
})
return pd.DataFrame(rows)
# 生成数据
taobao_df = gen_orders('淘宝', ['旗舰店', '专营店', '工厂店'])
pdd_df = gen_orders('拼多多', ['官方旗舰店', '品牌店'])
jd_df = gen_orders('京东', ['自营旗舰店', '第三方专营店'])
# 保存为 CSV(模拟从平台导出的情景)
taobao_df.to_csv('taobao_orders.csv', index=False)
pdd_df.to_csv('pdd_orders.csv', index=False)
jd_df.to_csv('jd_orders.csv', index=False)
print(f" ✅ 淘宝: {len(taobao_df)} 条订单")
print(f" ✅ 拼多多: {len(pdd_df)} 条订单")
print(f" ✅ 京东: {len(jd_df)} 条订单")
# ============ 第2步:用 DuckDB 做跨平台聚合分析 ============
print("\n🔄 运行 DuckDB 跨平台分析...")
con = duckdb.connect()
# 2a. KPI 总览
kpi_overview = con.execute("""
WITH unified AS (
SELECT * FROM read_csv_auto('taobao_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('pdd_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('jd_orders.csv')
)
SELECT
platform,
COUNT(*) AS 订单数,
ROUND(SUM(amount), 0) AS 总销售额,
ROUND(AVG(amount), 2) AS 客单价,
ROUND(SUM(quantity), 0) AS 总销量,
ROUND(SUM(amount) / NULLIF(SUM(quantity), 0), 2) AS 件单价,
COUNT(DISTINCT sku) AS SKU数,
ROUND(SUM(CASE WHEN province IN ('广东','浙江','江苏') THEN amount ELSE 0 END)
/ SUM(amount) * 100, 1) AS 核心省份占比_pct
FROM unified
GROUP BY platform
ORDER BY 总销售额 DESC
""").fetchdf()
print("\n📊 各平台 KPI:")
print(kpi_overview.to_string(index=False))
# 2b. 每日销售额趋势
daily_trend = con.execute("""
WITH unified AS (
SELECT * FROM read_csv_auto('taobao_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('pdd_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('jd_orders.csv')
)
SELECT order_date, platform, ROUND(SUM(amount), 0) AS sales
FROM unified
GROUP BY order_date, platform
ORDER BY order_date, platform
""").fetchdf()
# 2c. SKU 销售排名
sku_rank = con.execute("""
WITH unified AS (
SELECT * FROM read_csv_auto('taobao_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('pdd_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('jd_orders.csv')
)
SELECT
sku, category, sub_category,
ROUND(SUM(amount), 0) AS 总销售额,
SUM(quantity) AS 总销量,
ROUND(AVG(amount / quantity), 2) AS 均价,
COUNT(DISTINCT platform) AS 覆盖平台数
FROM unified
GROUP BY sku, category, sub_category
ORDER BY 总销售额 DESC
LIMIT 20
""").fetchdf()
# 2d. 品类分析
cat_analysis = con.execute("""
WITH unified AS (
SELECT * FROM read_csv_auto('taobao_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('pdd_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('jd_orders.csv')
)
SELECT
category, platform,
ROUND(SUM(amount), 0) AS 销售额,
COUNT(*) AS 订单数,
ROUND(SUM(amount) / SUM(SUM(amount)) OVER (PARTITION BY category) * 100, 1) AS 平台占比_pct
FROM unified
GROUP BY category, platform
ORDER BY category, 销售额 DESC
""").fetchdf()
# 2e. 各平台热销 Top 3
top3_per_platform = con.execute("""
WITH unified AS (
SELECT * FROM read_csv_auto('taobao_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('pdd_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('jd_orders.csv')
),
sku_sales AS (
SELECT platform, sku, category,
ROUND(SUM(amount), 0) AS sales,
ROW_NUMBER() OVER (PARTITION BY platform ORDER BY SUM(amount) DESC) AS rank
FROM unified
GROUP BY platform, sku, category
)
SELECT platform, sku, category, sales
FROM sku_sales
WHERE rank <= 3
ORDER BY platform, rank
""").fetchdf()
# 2f. 整体销售趋势(跨平台合计)
overall_trend = con.execute("""
WITH unified AS (
SELECT * FROM read_csv_auto('taobao_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('pdd_orders.csv')
UNION ALL BY NAME
SELECT * FROM read_csv_auto('jd_orders.csv')
)
SELECT order_date, ROUND(SUM(amount), 0) AS total_sales
FROM unified
GROUP BY order_date
ORDER BY order_date
""").fetchdf()
con.close()
print(" ✅ DuckDB 分析完成")
# ============ 第3步:输出为 Excel 报表(6个 Sheet)============
print("\n🔄 生成 Excel 报表...")
with pd.ExcelWriter('电商多平台运营报表.xlsx', engine='openpyxl') as writer:
kpi_overview.to_excel(writer, sheet_name='KPI总览', index=False)
overall_trend.to_excel(writer, sheet_name='每日销售趋势', index=False)
sku_rank.to_excel(writer, sheet_name='SKU销售排名', index=False)
cat_analysis.to_excel(writer, sheet_name='品类分析', index=False)
top3_per_platform.to_excel(writer, sheet_name='各平台热销Top3', index=False)
daily_trend.to_excel(writer, sheet_name='每日分平台趋势', index=False)
print(" ✅ 电商多平台运营报表.xlsx 已生成")
# ============ 第4步:输出 Plotly 交互式 HTML 看板 ============
print("\n🔄 生成交互式 HTML 看板...")
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# 看板标题
html = """
<html><head><meta charset="utf-8">
<title>电商多平台运营看板</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; margin: 20px; background: #f5f5f5; }
h1 { color: #2c3e50; text-align: center; }
.container { max-width: 1400px; margin: 0 auto; }
.card { background: white; padding: 20px; margin: 15px 0; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.card h2 { color: #34495e; margin-top: 0; }
.kpi-row { display: flex; gap: 15px; flex-wrap: wrap; }
.kpi-card { flex: 1; min-width: 150px; background: #f8f9fa; padding: 15px; border-radius: 8px; text-align: center; }
.kpi-value { font-size: 24px; font-weight: bold; color: #2c3e50; }
.kpi-label { font-size: 13px; color: #7f8c8d; }
</style></head><body>
<div class="container">
<h1>🦆 电商多平台运营看板</h1>
<p style="text-align:center;color:#7f8c8d;">数据周期:过去90天 | 平台:淘宝 / 拼多多 / 京东</p>
"""
# KPI 卡片
kpi_card_html = '<div class="card"><h2>📊 总体 KPI</h2><div class="kpi-row">'
for _, row in kpi_overview.head(3).iterrows():
kpi_card_html += f"""
<div class="kpi-card">
<div class="kpi-label">{row['platform']}</div>
<div class="kpi-value">¥{row['总销售额']:,.0f}</div>
<div style="font-size:12px;color:#95a5a6;">{row['订单数']} 单 | 客单价 ¥{row['客单价']}</div>
</div>"""
kpi_card_html += '</div></div>'
html += kpi_card_html
# 图1:总销售趋势
fig1 = px.line(overall_trend, x='order_date', y='total_sales',
title='📈 总销售趋势(跨平台合计)',
labels={'order_date': '日期', 'total_sales': '销售额 (¥)'})
fig1.update_layout(template='plotly_white', height=400)
html += f'<div class="card">{fig1.to_html(full_html=False, include_plotlyjs="cdn")}</div>'
# 图2:每日各平台趋势
fig2 = px.line(daily_trend, x='order_date', y='sales', color='platform',
title='📊 各平台每日销售额对比',
labels={'order_date': '日期', 'sales': '销售额 (¥)', 'platform': '平台'})
fig2.update_layout(template='plotly_white', height=400)
html += f'<div class="card">{fig2.to_html(full_html=False, include_plotlyjs="cdn")}</div>'
# 图3:品类分析 - 气泡图
fig3 = px.sunburst(cat_analysis, path=['category', 'platform'], values='销售额',
title='🎯 品类 - 平台 销售额分布',
color='销售额', color_continuous_scale='blues')
fig3.update_layout(height=500)
html += f'<div class="card">{fig3.to_html(full_html=False, include_plotlyjs="cdn")}</div>'
# 图4:SKU Top 20
fig4 = px.bar(sku_rank.head(20), x='总销售额', y='sku', color='category',
orientation='h',
title='🏆 SKU 销售额 Top 20',
labels={'总销售额': '销售额 (¥)', 'sku': 'SKU', 'category': '品类'},
text='总销售额')
fig4.update_layout(template='plotly_white', height=600, yaxis={'categoryorder':'total ascending'})
html += f'<div class="card">{fig4.to_html(full_html=False, include_plotlyjs="cdn")}</div>'
html += """
<div class="card" style="text-align:center;color:#7f8c8d;">
<p>🦆 由 DuckDB 驱动 · 本看板为静态 HTML,数据截至生成时刻</p>
</div></div></body></html>"""
with open('电商多平台运营看板.html', 'w', encoding='utf-8') as f:
f.write(html)
print(" ✅ 电商多平台运营看板.html 已生成")
print("\n" + "="*50)
print("🎉 交付完成!")
print(" 📁 电商多平台运营报表.xlsx (6个Sheet)")
print(" 📁 电商多平台运营看板.html (Plotly 交互式看板)")
print("="*50)
运行方法
python day16_shop_dashboard.py
脚本运行后,你会在当前目录看到两个文件:
| 文件 | 说明 |
|---|---|
电商多平台运营报表.xlsx | 6 个 Sheet 的 Excel 报表(KPI总览/每日趋势/SKU排名/品类分析/热销Top3/分平台趋势) |
电商多平台运营看板.html | Plotly 交互式 HTML 看板,在浏览器中打开即可 |
替换真实数据
把脚本中生成模拟数据的部分替换为读取真实 CSV:
# 替换这段:
taobao_df = gen_orders('淘宝', ...)
# 改为:
taobao_df = pd.read_csv('后台导出的淘宝订单.csv')
pdd_df = pd.read_csv('后台导出的拼多多订单.csv')
jd_df = pd.read_csv('后台导出的京东订单.csv')
脚本会自动适配 CSV 中的列名,UNION ALL BY NAME 会根据列名自动匹配。
与传统方案对比
| 方案 | 代码量 | 内存占用 (50万行) | 学习成本 | 成本 |
|---|---|---|---|---|
| Excel 手动合并 | 全靠手点 | N/A | 低 | 免费但费时 |
| Python + Pandas | 50-80 行 | 2-3 GB | 中 | 免费 |
| DuckDB 方案 | ~20 行 SQL | <200 MB | 低(会 SQL 就行) | 免费 |
| Tableau / Power BI | 零代码(但贵) | N/A | 中高 | $70/月/人 |
| 自研数据中台 | 上万行 | N/A | 极高 | 十几万起 |
变现方案
目标客户
月销 10-200 万的腰部电商卖家,同时经营 2-3 个平台,对数据敏感但不会编程。
报价区间
| 服务模式 | 报价 | 说明 |
|---|---|---|
| 一次性交付脚本+看板 | ¥2,000-3,000 | 适配客户的数据格式,交付后不再修改 |
| 月度维护+数据更新 | ¥500-1,000/月 | 每月更新看板,新增分析维度 |
| 定制开发(含更多维度) | ¥5,000-8,000 | 包含库存预警、利润分析、广告ROI等 |
交付清单
- 客户提供:各平台 CSV 导出(至少 3 个月的订单数据)
- 你交付:适配后的 Python 脚本 + Excel 报表 + HTML 看板
- 验收标准:各平台销售额总和与客户后台对得上
获客渠道
- 闲鱼 — 搜索"电商数据看板"“淘宝数据分析”,看谁在求这个
- 小红书 — 发笔记标题如"3 个平台的订单怎么合并?一个脚本搞定"
- 电商卖家群/朋友圈 — 直接展示看板截图
扩展思路
- 叠加更多的数据源 — 加上广告投放数据(直通车/多多搜索/京东快车),做 ROI 分析,报价可以翻倍
- 库存联动 — 对接进销存数据,做缺货预警,这个功能价值极高
- 做成 SaaS — 多个客户上传 CSV → DuckDB 后台处理 → 每个客户一个看板链接。年费 ¥999/客户
- 行业定制版 — 专门做某个品类(如服装/食品/电子),针对性更强的分析维度

为什么用 DuckDB 做这个项目
这个项目的本质需求是:把散落在多个 CSV 里的数据,快速聚合、分析、可视化。DuckDB 是最适合这个场景的工具:
- 零依赖:不需要装数据库,一个 pip install 搞定
- 自动推断:
read_csv_auto自动适配不同平台的 CSV 格式 - 列式引擎:只读需要的列,内存占用是 Pandas 的 1/10
- SQL 标准:会 SQL 就能做数据分析,不需要学 Pandas
- 输出灵活:可以输出到 Pandas DataFrame(转 Excel),也可以直接用 SQL 做聚合
一句话总结:一个 DuckDB Python 脚本 = 一条完整的数据分析服务产品线。