毕设常见痛点:为什么“用户行为分析”总被导师打回?
做电商用户行为分析毕设,最容易踩的坑有三类:
- 日志解析混乱:Nginx、埋点、APP 日志格式各唱各的调,时间戳还缺毫秒,清洗脚本写完就“祖传”。
- 实时性差:Pandas 一把梭,10 GB 数据本地跑一夜,第二天早八答辩,电脑还在转菊花。
- 可视化静态:Matplotlib 出 48 张 png,贴进 PPT 全糊成一片,导师问“能下钻吗?”只能尴尬微笑。
一句话:链路太长、工具太散、人力太少。下面给出一条“AI 辅助 + 轻量级架构”的逃生路线,亲测 7 天可交付。
技术选型对比:把“玩具”换成“工具”
| 维度 | 玩具级 | 工具级 | 理由 |
|---|---|---|---|
| 数据框 | Pandas | Polars | 同样 8 GB CSV,Polars 内存降 40%,多核并行秒级 lazy 执行 |
| 可视化 | Matplotlib | Plotly + Streamlit | 前者静态,后者一键st.plotly_chart生成交互,缩放、筛选、下钻全自带 |
| 存储 | SQLite | ClickHouse | 本地 1000 万行 JOIN 查询,SQLite 30 s,CH 0.3 s,列式存储省磁盘 60% |
结论:毕设不是炫技,选“跑得动”的才真香。
AI 如何辅助生成 ETL 与看板:Prompt 三板斧
1. 让 LLM 当“数据字典翻译官”
原始日志长这样:
2024-03-15T08:23:45.123Z|GET /item/123456|user_abc|200|42Prompt 模板:
请把上述管道分隔日志生成 Python 正则解析函数,返回含字段 {ts, method, sku, uid, status, resp_time} 的 NamedTuple,并加类型注解与 docstring。
LLM 秒回:
from typing import NamedTuple import re class LogRow(NamedTuple): ts: str method: str sku: str uid: str status: int resp_time: int LOG_RE = re.compile( r"^(?P<ts>[^|]+)\|(?P<method>[A-Z]+) (?P<sku>[^/]+/item/(?P<sku_id>\w+))\|(?P<uid>[^|]+)\|(?P<status>\d{3})\|(?P<resp_time>\d+)$" ) def parse(line: str) -> LogRow: m = LOG_RE.match(line) if not m: raise ValueError("bad line") return LogRow( ts=m["ts"], method=m["method"], sku=m["sku_id"], uid=m["uid"], status=int(m["status"]), resp_time=int(m["resp_time"]), )复制即用,0 手写正则。
2. 让 LLM 当“SQL 生成器”
需求:计算“过去 7 天每日 UV、PV、平均停留时长”。
Prompt:
用 ClickHouse SQL,表名 user_action,字段 (uid, sku, event_time, event_type, stay_sec)。event_type 含 'pv'/'buy'。输出每日 UV、PV、avg(stay_sec),按天升序。
LLM 回:
SELECT toDate(event_time) AS d, COUNT(DISTINCT uid) AS uv, COUNTIf(event_type = 'pv') AS pv, AVGIf(stay_sec, event_type = 'pv') AS avg_stay FROM user_action WHERE event_time >= now() - INTERVAL 7 DAY GROUP BY d ORDER BY d;贴进 ClickHouse-client,秒出结果,比手写翻文档快 10 倍。
3. 让 LLM 当“Streamlit 组件装配工”
Prompt:
用 Streamlit + Plotly,画每日 UV 折线图,支持范围滑块,y 轴标题“独立访客”,x 轴标题“日期”,图例默认隐藏。
LLM 回:
import streamlit as st import plotly.express as px def draw_uv(df): fig = px.line(df, x='d', y='uv', labels={'d': '日期', 'uv': '独立访客'}) fig.update_layout(showlegend=False) st.plotly_chart(fig, use_container_width=True)直接st.button("刷新")即可重跑,无需前端知识。
性能考量:让笔记本也能跑百万级日志
冷启动延迟
Streamlit 每次刷页面会重载脚本,把@st.cache_data加在“读取 + 轻量聚合”函数上,首次 3 s,后续 0.3 s。内存峰值
Polarsscan_csv(...).filter(...).collect()采用流式分块,8 GB 日志峰值内存 < 2 GB,2018 款 MacBook 无风扇狂飙。查询幂等性
ClickHouse 物化视图 +ReplacingMergeTree保证重复导数不膨胀,毕设导师反复INSERT也不炸表。
生产环境避坑指南:毕设能跑,实习也能跑
时间戳时区
日志里+0000但服务器+0800,ETL 统一toDateTime(ts, 'Asia/Shanghai'),否则凌晨数据全算错一天。用户 ID 匿名化
用 SHA-256 + 盐,避免明文 uid 进仓库,合规又防泄密。避免 N+1 查询
先GROUP BY uid把画像算好写临时表,看板 SQL 直接 SELECT,别再“for uid in uids”循环查 ClickHouse。磁盘写爆
ClickHouse 默认无上限,加<max_table_size_to_drop>100G</>防止日志表把 512 GB 固态撑满。
可复用工程模板:一键克隆即可答辩
仓库结构:
├── data/ # 原始日志 ├── etl/ │ ├── log_parser.py # LLM 生成 │ ├── ch_load.py # 批量写 CH ├── app/ │ ├── dashboard.py # Streamlit 入口 │ ├── plots.py # Plotly 封装 ├── sql/ │ ├── mview.sql # 物化视图 ├── requirements.txt └── README.md # 跑通流程 3 命令README 三行:
pip install -r requirements.txt python -m etl.ch_load --dir data/ streamlit run app/dashboard.py七天节奏:第 1 天搭环境,2-3 天清洗 + 导数,4-5 天 AI 生成图表,6 天写论文,7 天预答辩。
结尾:把毕设当成 MVP,而不是终点
这套轻量级方案不只为了“能过”,它已具备接入真实业务的骨架:ClickHouse 可换分布式集群,Streamlit 可打包成 Docker 镜像,Polars 脚本可丢进 Airflow 定时调度。下一步,你可以思考:
- 把每日全量跑批改成 Kafka + ClickHouse 物化视图,实现“准实时”。
- 引入增量学习:用 River 或 Vowpal Wabbit 在消息流上持续更新“复购概率”模型,让看板从描述过去变成预测未来。
毕业设计不是句号,把 AI 辅助效率沉淀为习惯,才算真正“毕业”。