DuckDB 零 ETL 日报系统:5 分钟从 CSV 到 Telegram 推送
每天早上醒来,手机收到一份格式精美的日报——这不是幻想,而是用 DuckDB + Python + Telegram Bot 搭建的系统能做到的事。
传统报表系统的痛点很清晰:需要 ETL 管道、数据库服务器、调度工具(Airflow 或 cron),维护成本高昂。DuckDB 的颠覆性在于:它让报表系统回归极简——一个 CSV 文件,十行代码,就能完成从原始数据到推送通知的全流程。
今天拆解一个可直接落地的副业项目:用 DuckDB 搭建零 ETL 自动化日报系统,帮助中小企业每天自动产出核心指标报告,推送到 Telegram 群或私聊。

一、商业逻辑:你在卖什么?
很多人以为卖的是"数据报表",但真正的价值是**“省时间”**。
一个中小电商团队每天花费 30-60 分钟整理销售数据、制作报表。如果你能帮他们 automate 这个流程,每月收取 299 元订阅费,客户会非常乐意付费——因为他们买的是每天多出来的 1 小时。
定价策略参考:
- 基础版(每日核心指标):299 元/月
- 进阶版(含环比分析 + Top 商品排行):499 元/月
- 企业版(多业务线 + 自定义指标):999 元/月
二、系统架构:三层极简设计
整个系统分三层,没有数据库服务器,没有 Airflow:
┌─────────────────────────────────────────────────────┐
│ 数据层 (Data Layer) │
│ CSV / Excel / JSON 文件 → DuckDB read_csv_auto() │
│ 零 ETL,直接原地读取 │
└────────────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 计算层 (Compute Layer) │
│ Python + DuckDB SQL:聚合、环比、Top-N │
│ 百万行数据 1-2 秒出结果 │
└────────────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 交付层 (Delivery Layer) │
│ Telegram Bot API → 消息格式化 → 定时推送 │
│ 支持:私聊 / 群组 / 频道 │
└─────────────────────────────────────────────────────┘
核心优势: 一台年费 200 元的云服务器(或本地电脑)即可运行,无需任何第三方数据服务。
三、第一步:准备示例数据
先用 Python 生成一份模拟电商日报数据,验证系统逻辑:
import duckdb
import pandas as pd
from datetime import datetime, timedelta
import random
# 生成 30 天的模拟电商数据
dates = [datetime(2026, 8, 1) + timedelta(days=i) for i in range(30)]
products = ["笔记本", "鼠标", "键盘", "显示器", "耳机"]
categories = ["数码配件", "外设", "输入设备", "显示设备", "音频设备"]
data = []
for d in dates:
for p, c in zip(products, categories):
orders = random.randint(10, 200)
revenue = orders * random.uniform(50, 500)
users = random.randint(50, 500)
data.append({
"date": d.strftime("%Y-%m-%d"),
"product": p,
"category": c,
"orders": orders,
"revenue": round(revenue, 2),
"users": users,
})
df = pd.DataFrame(data)
df.to_csv("/tmp/ecommerce_daily.csv", index=False)
print(f"✅ 生成 {len(df)} 条记录")
运行后会在 /tmp/ecommerce_daily.csv 生成 150 条记录(30 天 × 5 个商品),每条包含日期、商品、品类、订单数、营收和活跃用户数。
四、第二步:DuckDB 核心查询(零 ETL)
DuckDB 的杀手锏是**read_csv_auto()**——直接读取 CSV 文件,自动推断列类型,无需任何导入操作:
import duckdb
con = duckdb.connect()
# 1. 核心指标汇总(昨日 vs 前日环比)
yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
day_before = (datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d")
daily_report = con.execute("""
SELECT
'昨日' as period,
SUM(revenue) as total_revenue,
SUM(orders) as total_orders,
SUM(users) as total_users,
ROUND(SUM(revenue)/NULLIF(SUM(orders),0), 2) as avg_order_value
FROM read_csv_auto('/tmp/ecommerce_daily.csv')
WHERE date = ?
""", [yesterday]).fetchdf()
print("📊 核心指标:")
print(daily_report.to_string(index=False))
关键点:
read_csv_auto()自动识别日期格式、数字类型,无需手动指定 schema- 参数化查询(
?占位符)防止 SQL 注入 NULLIF()防止除以零错误
五、第三步:环比计算与 Top-N 排行
日报的价值在于变化趋势,而不仅仅是绝对数值。用 DuckDB 的 CASE WHEN 实现环比计算:
# 2. 环比变化率
growth = con.execute("""
SELECT
SUM(CASE WHEN date = ? THEN revenue END) as rev_yesterday,
SUM(CASE WHEN date = ? THEN revenue END) as rev_day_before,
ROUND(
(SUM(CASE WHEN date = ? THEN revenue END) -
SUM(CASE WHEN date = ? THEN revenue END)) * 100.0 /
NULLIF(SUM(CASE WHEN date = ? THEN revenue END), 0),
2) as revenue_growth_pct
FROM read_csv_auto('/tmp/ecommerce_daily.csv')
""", [yesterday, day_before, yesterday, day_before, day_before]).fetchdf()
# 3. Top 3 商品(按营收)
top_products = con.execute("""
SELECT product,
SUM(revenue) as revenue,
SUM(orders) as orders,
COUNT(DISTINCT date) as active_days
FROM read_csv_auto('/tmp/ecommerce_daily.csv')
GROUP BY product
ORDER BY revenue DESC
LIMIT 3
""").fetchdf()
print("\n📈 环比变化:")
print(growth.to_string(index=False))
print("\n🏆 Top 3 商品:")
print(top_products.to_string(index=False))
性能对比: 同样 100 万行数据,DuckDB SQL 聚合比 pandas 循环快 10-50 倍,且内存占用更低。
六、第四步:Telegram Bot 推送
将报告格式化为美观的 Telegram 消息,通过 Bot API 推送:
import http.client
import json
def send_telegram_message(bot_token, chat_id, message):
"""通过 Telegram Bot API 发送消息"""
conn = http.client.HTTPSConnection("api.telegram.org")
payload = json.dumps({
"chat_id": chat_id,
"text": message,
"parse_mode": "HTML"
})
headers = {'Content-Type': 'application/json'}
conn.request("POST", f"/bot{bot_token}/sendMessage", payload, headers)
res = conn.getresponse()
print(f"Telegram 状态: {res.status} {res.reason}")
conn.close()
return res.status == 200
# 格式化日报消息
msg = f"""📊 <b>电商日报 · {yesterday}</b>
💰 总营收: <b>{daily_report['total_revenue'].values[0]:,.2f} 元</b>
📦 订单数: <b>{daily_report['total_orders'].values[0]}</b> 单
👥 活跃用户: <b>{daily_report['total_users'].values[0]}</b>
🛒 客单价: <b>{daily_report['avg_order_value'].values[0]:.2f} 元</b>
📈 环比昨日: <b>{growth['revenue_growth_pct'].values[0]:+.2f}%</b>
🏆 Top 3 商品:
{chr(10).join([f" {i+1}. {r['product']} — {r['revenue']:,.0f}元"
for i, r in top_products.iterrows()])}
🤖 由 DuckDB 自动化日报系统生成
"""
# 调用发送(替换为真实的 token 和 chat_id)
# send_telegram_message("YOUR_BOT_TOKEN", "YOUR_CHAT_ID", msg)
Telegram Bot 配置步骤:
- 在 Telegram 搜索
@BotFather,发送/newbot创建机器人 - 按提示设置机器人名称,获取
bot_token(格式:123456789:ABCdefGHIjklMNOpqrsTUVwxyz) - 搜索你的机器人,发送任意消息
- 访问
https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates获取chat_id
七、第五步:定时调度
两种部署方式,按需选择:
方式一:系统 crontab(推荐生产环境)
# 每天早上 8 点自动执行
0 8 * * * cd ~/duckdb-daily-report && python3 run_report.py >> /var/log/daily_report.log 2>&1
方式二:Python schedule 库(适合开发测试)
import schedule
import time
def job():
print(f"[{datetime.now()}] 开始执行日报...")
# 运行查询和推送逻辑
send_telegram_message("YOUR_BOT_TOKEN", "YOUR_CHAT_ID", msg)
print("✅ 日报已推送")
schedule.every().day.at("08:00").do(job)
while True:
schedule.run_pending()
time.sleep(60)
八、与传统方案的对比
| 维度 | 传统方案(Excel + VBA) | DuckDB 零 ETL 方案 |
|---|---|---|
| 数据准备 | 手动导出 CSV → 导入数据库 | 直接读取 CSV,零 ETL |
| 计算速度 | 10 万行需要 30 秒+ | 100 万行 1-2 秒 |
| 维护成本 | 需要 Excel 环境、VBA 调试 | 纯 Python + SQL,跨平台 |
| 推送方式 | 人工发送或邮件 | Telegram Bot 自动推送 |
| 部署成本 | 本地电脑 + Excel 授权 | 云服务器 200 元/年 |
| 可扩展性 | 单用户、单文件 | 支持多文件 glob、多数据源 |
核心差异: 传统方案把数据搬来搬去,DuckDB 让数据留在原地被计算。
九、变现路径
这套系统本身就可以成为产品,有三种变现模式:
1. SaaS 订阅服务
让用户上传自己的 CSV 数据,每天自动生成可视化日报推送到 Telegram。
- 定价: 299 元/月/用户
- 目标客户: 中小电商、内容创作者、自媒体
- 获客渠道: 付费频道、技术社区、朋友圈
2. 定制开发服务
帮企业搭建专属日报系统,根据需求定制指标和推送渠道。
- 定价: 500-2000 元/次
- 目标客户: 有 5-50 人的电商团队
- 交付周期: 1-3 天
3. 数据产品订阅
用公开数据源(Kaggle、政府开放数据)生成每日行业报告,在付费频道售卖。
- 定价: 99 元/月
- 目标客户: 投资者、行业分析师
- 差异化: 独家 DuckDB 分析视角
十、进阶技巧
1. 多文件合并读取
当数据分散在多个 CSV 文件中时,DuckDB 支持 glob 模式直接读取:
-- 读取当月所有 CSV 文件,自动合并
SELECT date, SUM(revenue) as daily_revenue
FROM read_csv_auto('/data/sales/2026-08/*.csv')
GROUP BY date
ORDER BY date;
2. 性能优化:并行读取
DuckDB 自动利用多核 CPU 并行读取大文件。可以通过设置强制并行度:
con = duckdb.connect(config={
'max_threads': 4,
'threads_per_query': 4
})
3. 错误处理与告警
在生产环境中,建议添加异常捕获和告警机制:
try:
daily_report = con.execute(...).fetchdf()
send_telegram_message(token, chat_id, msg)
except Exception as e:
error_msg = f"❌ 日报生成失败: {str(e)}"
send_telegram_message(token, chat_id, error_msg)
raise
总结
DuckDB 让报表系统回归本质:数据在哪里,计算就在哪里发生。不需要 ETL 管道,不需要数据库服务器,一个 CSV 文件 + 十行 SQL 就能完成从原始数据到推送通知的全流程。
这套系统的价值不在于技术本身,而在于可复制性——一旦为第一个客户搭建完成,就可以快速复制给更多客户,边际成本趋近于零。
💡 更多 DuckDB 实战技巧 → duckdblab.org