用 DuckDB 搭建自动日报系统,每月多赚 5000 元
在数据分析行业,最值钱的不是会写 SQL,而是把重复劳动变成自动化产品。今天拆解一个真实可落地的副业项目:用 DuckDB + Python 搭建自动日报系统,卖给中小企业,每月收订阅费。

项目背景与商业逻辑
很多中小企业每天需要统计销售、流量、转化率等核心指标,但要么老板自己瞎看 Excel,要么雇一个助理手工导出。你的机会在于:帮他们搭一个全自动系统,每天自动产出报表并推送到微信/邮件/Telegram 群。
传统方案 vs DuckDB 方案
传统方案:
- 数据导出到本地 Excel
- 用 Excel 或手动写 VBA 处理
- 耗时数小时,容易出错
- 每次都要人工介入
DuckDB 方案:
- 直接连接数据库,原地计算
- Python 脚本自动调度
- 1-2 秒完成百万行聚合
- 零人工介入,7x24 运行
这个方案的核心优势是原地计算——DuckDB 可以直接连接 MySQL、PostgreSQL、SQLite 等数据源,无需把数据全量搬回本地,百万行聚合在内存中 1-2 秒完成。
系统架构
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ MySQL/PG │────▶│ DuckDB │────▶│ Python │
│ 数据源 │ │ 计算引擎 │ │ 调度 & 推送 │
└─────────────┘ └──────────────┘ └─────────────┘
│
┌───────▼───────┐
│ 邮件/Telegram │
└───────────────┘
核心架构很简单:
- 数据源:MySQL / PostgreSQL / CSV 文件
- 计算引擎:DuckDB(秒级处理百万行数据)
- 调度层:Python schedule 库
- 输出:Markdown + 图片,推送到 Telegram 群或邮箱
第一步:连接数据源,用 DuckDB 做聚合计算
假设你接入了一个电商系统的订单表,数据量约 50 万行。用 DuckDB 做日级别汇总,只需要几行代码:
import duckdb
from datetime import datetime, timedelta
# 直接连接 MySQL,无需导出到本地
con = duckdb.connect('mysql://user:***@host:3306/shop', read_only=True)
# 7日汇总分析
daily_report = con.execute("""
SELECT
DATE(order_time) AS dt,
COUNT(*) AS orders,
SUM(amount) AS revenue,
AVG(amount) AS avg_order_value,
COUNT(DISTINCT user_id) AS active_users
FROM orders
WHERE order_time >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY DATE(order_time)
ORDER BY dt DESC
""").fetchdf()
print(daily_report)
关键技巧:DuckDB 支持原生连接多种数据库,连接字符串格式统一。MySQL 需要安装
duckdb-mysql扩展,PostgreSQL 同理。如果数据量不大,也可以直接读 CSV 文件:duckdb.read_csv('orders.csv')。
执行结果示例:
dt orders revenue avg_order_value active_users
0 2026-08-01 1250 89500.00 71.60 890
1 2026-07-31 1180 82300.00 69.75 845
2 2026-07-30 1320 95600.00 72.42 920
...
第二步:生成可视化图表
有了数据后,用 Matplotlib 生成图表:
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Agg') # 无头模式,服务器友好
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 左图:7日营收趋势
axes[0].plot(daily_report['dt'], daily_report['revenue'],
marker='o', color='#2E86AB', linewidth=2)
axes[0].fill_between(daily_report['dt'], daily_report['revenue'],
alpha=0.2, color='#2E86AB')
axes[0].set_title('7-Day Revenue Trend')
axes[0].set_xlabel('Date')
axes[0].set_ylabel('Revenue (¥)')
axes[0].tick_params(axis='x', rotation=45)
# 右图:订单量 vs 客单价散点图(气泡大小=活跃用户数)
scatter = axes[1].scatter(
daily_report['orders'],
daily_report['avg_order_value'],
s=daily_report['active_users'] * 2,
alpha=0.6,
c=daily_report['revenue'],
cmap='viridis'
)
axes[1].set_title('Orders vs Avg Order Value')
axes[1].set_xlabel('Order Count')
axes[1].set_ylabel('Avg Order Value')
plt.colorbar(scatter, ax=axes[1], label='Revenue')
plt.tight_layout()
plt.savefig('/tmp/daily_report.png', dpi=120, bbox_inches='tight')
第三步:组装日报并推送
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
def format_report(df):
"""将 DataFrame 格式化为可读的日报文本"""
today = df.iloc[0]
yesterday = df.iloc[1] if len(df) > 1 else None
report = f"""📊 今日销售日报 · {today['dt'].strftime('%Y-%m-%d')}
营收:¥{today['revenue']:,.2f}
订单数:{int(today['orders'])} 单
客单价:¥{today['avg_order_value']:.2f}
活跃用户:{int(today['active_users'])} 人
"""
if yesterday is not None:
rev_change = (today['revenue'] - yesterday['revenue']) / yesterday['revenue'] * 100
sign = '📈' if rev_change > 0 else '📉'
report += f"⚡ 环比昨日:{sign} {abs(rev_change):.1f}%"
return report
def send_report(report_text, image_path):
"""发送邮件(可替换为 Telegram Bot API)"""
msg = MIMEMultipart()
msg['Subject'] = f"日报 · {datetime.now().strftime('%m-%d')}"
msg.attach(MIMEText(report_text, 'plain', 'utf-8'))
with open(image_path, 'rb') as f:
from email.mime.image import MIMEImage
img = MIMEImage(f.read())
img.add_header('Content-ID', '<report>')
msg.attach(img)
# smtp 发送逻辑省略,替换为你自己的配置
print(f"Report ready → {image_path}")
print(report_text)
# 执行
report_text = format_report(daily_report)
send_report(report_text, '/tmp/daily_report.png')
替换为 Telegram Bot 推送
如果觉得邮件不够即时,可以改用 Telegram Bot API:
import requests
def send_telegram(chat_id, text, photo_path=None):
bot_token = "YOUR_BOT_TOKEN"
url = f"https://api.telegram.org/bot{bot_token}"
# 发送文本
requests.post(f"{url}/sendMessage", json={
"chat_id": chat_id,
"text": text,
"parse_mode": "HTML"
})
# 发送图片
if photo_path:
with open(photo_path, 'rb') as f:
requests.post(f"{url}/sendPhoto", json={"chat_id": chat_id}, files={"photo": f})
第四步:定时调度 + 多客户隔离
import schedule
import time
def generate_daily_report(client_id):
"""为单个客户生成日报"""
con = duckdb.connect(f'mysql://user:***@host:3306/{client_id}', read_only=True)
# ... 执行查询、生成图表、发送报告 ...
con.close()
# 每天 9:00 自动生成
schedule.every().day.at("09:00").do(generate_daily_report, client_id="client_001")
schedule.every().day.at("09:05").do(generate_daily_report, client_id="client_002")
schedule.every().day.at("09:10").do(generate_daily_report, client_id="client_003")
# 72小时轮询,低负载
while True:
schedule.run_pending()
time.sleep(60)
每个客户一个独立的 DuckDB 连接配置,报表内容按客户 ID 过滤,代码复用率极高。
DuckDB vs 传统方案的对比
| 维度 | 传统 Excel/VBA 方案 | DuckDB + Python 方案 |
|---|---|---|
| 数据处理速度 | 分钟级(大数据量卡死) | 秒级(百万行聚合 1-2s) |
| 数据源支持 | 仅 CSV/Excel | MySQL、PG、SQLite、CSV、Parquet |
| 自动化程度 | 需要人工触发 | 完全自动调度 |
| 维护成本 | 高(公式易错) | 低(代码即文档) |
| 可视化能力 | 基础图表 | 完整的 Matplotlib/Seaborn |
| 部署成本 | 本地电脑 | 云服务器 1核1G 即可 |
| 扩展性 | 差(数据大了就崩) | 好(支持分区、谓词下推) |
商业落地建议
定价策略
| 版本 | 功能 | 月费 |
|---|---|---|
| 基础版 | 单表日报(营收/订单/用户) | 99 元/月 |
| 进阶版 | 多源聚合 + 图表 + 环比分析 | 299 元/月 |
| 企业版 | 实时大屏 + API 接入 + 定制报表 | 999 元/月 |
获客渠道
- 闲鱼/淘宝:挂「定制数据报表」服务,引流到私域
- 技术社区:在 V2EX、即刻发技术笔记,展示效果截图
- 免费试用:给本地小电商免费做一期,要案例和转介绍
- 社群运营:在行业群里分享自动化报表截图,自然获客
成本分析
- 服务器:阿里云/腾讯云 1核1G 约 50 元/月
- 开发时间:首次搭建 2-3 天,后续每个新客户 1-2 小时配置
- 维护时间:每个客户每月 < 30 分钟
- 利润率:基础版毛利约 90%,进阶版约 95%
实际项目中,一个客户从接触到付费平均 3-5 天,维护成本极低(服务器 + DuckDB 本地运行,无第三方依赖)。
进阶方向
- 多数据源融合:用 DuckDB 的
mysql_scanner()和postgres_scanner()同时拉取 ERP 和 CRM 数据,做客户 LTV 分析 - 自动异常检测:用 DuckDB 内置统计函数做阈值告警,营收突降自动通知老板
- 导出 PDF:用 reportlab 把报表转成正式 PDF,增强付费感
- Web 化:用 Streamlit 搭建可视化看板,客户自助查询
- Docker 部署:把整个系统打包成容器,一键部署到客户服务器
完整代码仓库
本项目已开源,包含:
- 多数据源适配(MySQL/PostgreSQL/CSV)
- 日报/周报/月报模板
- Telegram Bot 推送
- Docker 部署配置
- 多客户隔离方案
访问 duckdblab.org 获取完整代码和技术文档。
💡 变现建议总结:这个项目的核心逻辑是「用技术换时间,用时间换收入」。一个客户月费 299 元,10 个客户就是 2990 元/月,而你的维护成本几乎为零。关键是找到有数据但不会用工具的中小企业老板——他们愿意为「省心」付费。
📖 本文的完整版(含 Docker 部署、Telegram Bot 推送、多客户模板)已发布在 duckdblab.org,直接拿去用。
学习更多 DuckDB 实战经验 → duckdblab.org