
做数据分析练手项目最怕两件事第一是数据太“假”洗来洗去没有业务感觉第二是流程太散爬虫是爬虫、可视化是可视化最后简历上只能写“用过 Python”。这次我们看的这个项目用 Python MySQL 做了一个泡泡玛特主题的数据可视化分析整体走的是「建库 → 入库 → SQL 分析 → Python 处理 → 可视化出图 → 结论沉淀」的完整链路练完之后是一份能直接写进简历里的数据项目经历。先给这个项目做个定位它不是一个算法项目也不是一个模型部署项目而是一个典型的数据分析全流程项目。技术栈是 Python MySQL pandas pyecharts / Matplotlib 这类常见组合。业务对象是泡泡玛特的盲盒产品数据、门店渠道数据、销售订单数据。核心成果是几张能说明业务问题的可视化图表例如热门 IP 排行、价格带分布、销量趋势、渠道对比。整个过程不依赖高算力设备普通笔记本就能跑重点是让你把 MySQL 建表、SQL 查询、Python 数据清洗、可视化输出串起来。这篇文章会给出完整的项目拆解、数据库表设计、Python 入库脚本、SQL 分析思路和可视化代码同时会把“怎么看数据、怎么找业务结论、怎么写进简历”也讲清楚。如果你正缺一个 Python 数据分析方向的项目经验这篇文章可以直接照做。1. 项目核心能力速览能力项说明项目类型Python MySQL 数据分析可视化练手项目技术栈Python、MySQL、pandas、SQLAlchemy / PyMySQL、pyecharts / Matplotlib业务对象泡泡玛特盲盒产品、IP、价格、渠道、销售订单核心产出数据库表、清洗后的数据集、可视化图表、业务分析结论运行环境Windows / macOS / Linux 均可普通笔记本即可硬件门槛无 GPU 要求8G 内存及以上足够启动方式命令脚本 / Jupyter Notebook / PyCharm 逐步执行接口 API不需要侧重内部数据分析流程批量任务支持批量导入 CSV / Excel 数据入库适合场景数据分析简历项目、毕设、课程设计、Python MySQL 综合练习数据合规注意真实业务数据需授权练习建议使用模拟或已公开脱敏数据这个项目的价值点不是“泡泡玛特”这三个字本身而是它覆盖了数据分析岗面试里最常见的十几道题数据表怎么设计、SQL 怎么取数、重复值和缺失值怎么处理、销售额怎么聚合、Top N 怎么算、时间趋势怎么做、结果怎么用图表表达。2. 适用场景与使用边界2.1 适合谁做Python 基础已经学完但缺一个能串起 pandas MySQL 的完整案例。求职数据分析 / 商业分析 / 运营分析岗位简历缺项目经验。正在准备毕业设计想做一个“数据采集 存储 可视化”的课题。学过 SQL 但没在真实业务表上写过聚合查询。用 Matplotlib 画过图但没做过完整的分析型可视化报告。2.2 能解决什么问题这个项目帮你解决的核心问题是从一堆看起来杂乱的数据中梳理出能支撑业务决策的指标和图表。练完你能掌握这些具体能力设计维度表和事实表理解为什么订单表要单独的 id 而不是直接存 IP 名称。用 SQL 做多表关联查询例如把订单表关联产品表统计某个 IP 的销量。用 pandas 处理 MySQL 查出来的结果补齐缺失值、转换时间格式、计算客单价。用 pyecharts 生成柱状图、折线图、饼图、地图或仪表盘。写出一份可汇报的数据分析结论「谁卖得好、为什么卖得好、下阶段看什么指标」。2.3 使用边界与合规提醒必须强调一点泡泡玛特是真实存在的商业公司其销售数据、内部经营数据、未公开产品数据属于公司资产。做练手项目时建议使用以下数据公开财报中的脱敏数据。自己爬取公开电商页面得到的有限字段并注意遵守目标网站协议。自行模拟构造的示例数据。本文后续代码基于“模拟示例数据”来演示所有数字仅用于跑通流程不代表真实经营情况。项目可以命名为「模拟盲盒零售数据分析」「示例版潮流 IP 商品分析」这样写进简历更稳妥也能避开数据合规问题。3. 环境准备与前置条件这个项目不需要 GPU不用配 CUDA环境要求很亲民。3.1 基础环境清单环境项建议版本说明操作系统Windows 10/11、macOS、Linux任选Python3.9 及以上建议 3.10 或 3.11MySQL5.7 及以上8.0 更佳IDEPyCharm / VS Code / Jupyter任选数据库客户端Navicat / DBeaver / MySQL Workbench可选用于检查数据3.2 Python 依赖库安装建议先建虚拟环境避免和系统 Python 包冲突。下面的命令按常见流程执行即可。python -m venv venv source venv/bin/activate # Windows 下为 venv\Scripts\activate激活虚拟环境后执行安装pip install -U pip pip install pymysql sqlalchemy pandas openpyxl pip install pyecharts matplotlib说明一下每个库的用途pymysqlPython 连接 MySQL 的驱动。sqlalchemy统一的数据库连接引擎pandasread_sql/to_sql经常配合它使用。pandas数据清洗和分析。openpyxl让 pandas 能读写 Excel 文件。pyecharts生成交互式图表。matplotlib生成静态图表适合快速出图。3.3 MySQL 环境检查如果本机还没安装 MySQL先确认几个基础问题MySQL 服务是否已启动。root 用户密码是否知道。端口是否默认 3306。是否允许本机连接。快速测试连接的方式是直接命令行登录mysql -uroot -p能进入 MySQL 交互界面就说明服务正常。如果报Cant connect to local MySQL server through socket /tmp/mysql.sock多数情况是 MySQL 服务没启动先启动服务再重新连接。Linux 下常见命令是systemctl start mysqldmacOS 可以用brew services start mysql。如果平时用 Navicat 之类的客户端比较多提前在客户端里新建一个连接测试一下也行。4. 数据库设计与表结构这个项目的数据库设计是整个分析的地基。模拟一个简化但完整的盲盒零售业务门店维表存放门店信息。产品维表存放产品的 IP 系列、价格、发售日期。订单事实表存放每一笔销售记录关联门店和产品。4.1 创建数据库登录 MySQL 后执行CREATE DATABASE IF NOT EXISTS popmart_sales DEFAULT CHARSET utf8mb4; USE popmart_sales;使用utf8mb4是为了正确存储中文和 emoji 字符盲盒产品名经常包含 IP 名和系列名中文支持必须稳定。4.2 门店信息表 storeCREATE TABLE store ( store_id INT PRIMARY KEY COMMENT 门店ID, store_name VARCHAR(100) COMMENT 门店名称, city VARCHAR(50) COMMENT 城市, channel VARCHAR(20) COMMENT 渠道类型线下门店/电商平台/机器人商店 ) COMMENT 门店维度表;4.3 产品信息表 productCREATE TABLE product ( product_id INT PRIMARY KEY COMMENT 商品ID, product_name VARCHAR(200) COMMENT 商品名称, ip_name VARCHAR(100) COMMENT IP名称如 MOLLY、SKULLPANDA、DIMOO, series_name VARCHAR(100) COMMENT 系列名称, price DECIMAL(10,2) COMMENT 零售价, sale_date DATE COMMENT 发售日期 ) COMMENT 产品维度表;字段ip_name是这次分析里非常重要的维度因为盲盒业务高度依赖 IP。价格字段用DECIMAL(10,2)不要用FLOAT避免金额出现精度问题。4.4 订单事实表 sale_orderCREATE TABLE sale_order ( order_id VARCHAR(50) PRIMARY KEY COMMENT 订单号, store_id INT COMMENT 门店ID, product_id INT COMMENT 商品ID, sale_qty INT COMMENT 销售数量, sale_amount DECIMAL(10,2) COMMENT 销售金额, order_time DATETIME COMMENT 下单时间 ) COMMENT 订单事实表;订单号虽然看起来是一串数字但通常不适合直接用 INT因为可能很长且包含特殊字符所以这里定义为VARCHAR。sale_amount可以冗余存储因为订单金额可能在商品价格基础上受活动影响冗余后查询更方便。4.5 表关系说明sale_order.store_id关联store.store_idsale_order.product_id关联product.product_id这就是最典型的星型模型中间一张订单事实表周边挂维表。后续做多表查询时SQL 的JOIN条件非常直观。4.6 外键要不要加练手项目里外键可加可不加。建议项目初期不加物理外键而是通过在代码中控制数据一致性。原因有两个后期批量导入数据时物理外键会消耗校验时间。数据量大了以后加了外键的表做DELETE/UPDATE会遇到更多约束问题。从数据分析的角度看更常用的是“逻辑外键”也就是字段存在但不在数据库层面强制约束。面试官问到这一点时你可以回答为了提高批量写入和查询效率这里采用逻辑外键设计在应用层保证数据完整性。这个回答比“我不会加外键”专业得多。5. 数据准备与入库这个环节是整个项目里最“真实”的一步。真实业务场景里数据分析师拿到的第一份数据往往不是直接写进 MySQL 的而是 CSV 文件、Excel 表、甚至 PDF 里的表格。所以这个过程应该这样设计准备原始 CSV / Excel 文件。用 pandas 读取并预览。做基础清洗。写入 MySQL。5.1 准备模拟数据文件为了让项目能独立运行可构造三个模拟数据文件store.csv50 行左右字段包括门店 ID、名称、城市、渠道。product.csv100 行左右字段包括商品 ID、名称、IP、系列、价格、发售日期。order_data.csv2000 行左右模拟一段时间内的订单流水。由于没有真实接口文件内容可以按业务规则生成。参考生成逻辑如下# 模拟参考代码只展示生成思路实际文件请自行构造 import pandas as pd import numpy as np np.random.seed(2024) ip_names [MOLLY, SKULLPANDA, DIMOO, LABUBU, HIRONO] series_names [星座系列, 温度系列, 动物王国系列, 西游系列] stores [{store_id: i, city: city, channel: channel} for i, (city, channel) in enumerate(...)]这里要特别说明生成模拟数据时要控制每个 IP 的销量差异、价格带差异不要生成完全均匀的随机数据。否则后面分析时图表没有业务层次感做出来的 Top 5 排名也不具有解释空间。另外在生成order_data.csv时建议加入一些“脏数据”比如空门店 ID。重复订单号。销售数量为 0。时间格式不统一。这也是一个加分设计面试官如果问你“数据清洗怎么做的”你能当场演示出至少三种清洗操作而不是只会说dropna()。5.2 用 pandas 清洗数据读入 CSV 后先看整体情况import pandas as pd orders pd.read_csv(data/order_data.csv, encodingutf-8) print(orders.shape) print(orders.head()) print(orders.info())处理常见问题的参考代码# 1. 删除重复订单号保留第一条 orders orders.drop_duplicates(subset[order_id], keepfirst) # 2. 删除门店 ID 为空的数据 orders orders.dropna(subset[store_id]) # 3. 删除销售数量 0 的数据 orders orders[orders[sale_qty] 0] # 4. 统一时间格式 orders[order_time] pd.to_datetime(orders[order_time])上述每一步都可以单独统计影响行数这样写简历时就能写“清洗 2000 行原始数据去重 12 条去空 8 条有效数据 1980 条”数据意识一下子就出来了。5.3 写入 MySQL写入 MySQL 的代码不需要手动拼接 SQL直接用pandas.to_sql就能完成。from sqlalchemy import create_engine engine create_engine(mysqlpymysql://root:你的密码127.0.0.1:3306/popmart_sales?charsetutf8mb4) store_df.to_sql(store, conengine, if_existsreplace, indexFalse) product_df.to_sql(product, conengine, if_existsreplace, indexFalse) orders.to_sql(sale_order, conengine, if_existsreplace, indexFalse)if_existsreplace表示如果表已存在先删除再重建。练习阶段用这个比较方便。如果已经手工建好表希望保留表结构、只追加数据要改成if_existsappend。这里有个连接细节create_engine的charsetutf8mb4一定要带上否则写入中文时可能出现乱码。如果用 pymysql 原生连接则要写import pymysql conn pymysql.connect( host127.0.0.1, userroot, password你的密码, databasepopmart_sales, charsetutf8mb4, cursorclasspymysql.cursors.DictCursor )写入后建议用 SQL 验证一下行数USE popmart_sales; SELECT COUNT(*) FROM store; SELECT COUNT(*) FROM product; SELECT COUNT(*) FROM sale_order;如果三个表都能查到数据说明入库阶段已经完成。如果报ModuleNotFoundError: No module named pymysql回到 3.2 节把依赖装好如果报连接超时或密码错误优先检查 MySQL 服务状态、密码、端口。5.4 批量导入 Excel 多文件的思路如果需要扩展成批量任务可以用一个目录存放多个 Excel 文件循环读取后写入同一张 MySQL 表方便大量积累数据再统一分析适合以后接更多数据源时快速起步。import os file_dir ./batch_data for file_name in os.listdir(file_dir): if file_name.endswith(.xlsx): file_path os.path.join(file_dir, file_name) temp_df pd.read_excel(file_path) temp_df.to_sql(sale_order, conengine, if_existsappend, indexFalse) print(f{file_name} 导入完成)6. 基于 MySQL Python 的分析维度设计数据库已经就绪接下来进入核心部分用 SQL 做快速聚合再用 Python 做更灵活的分析。下面从数据分析师面试最常遇到的几个角度出发规划 6 类分析思路每类都会给出 SQL 示例和 Python 可视化结果说明。6.1 热门 IP 销售排行盲盒行业最重要的指标之一就是 IP 热度。标准 SQLSELECT p.ip_name, COUNT(o.order_id) AS order_cnt, SUM(o.sale_qty) AS total_qty, SUM(o.sale_amount) AS total_amount FROM sale_order o LEFT JOIN product p ON o.product_id p.product_id GROUP BY p.ip_name ORDER BY total_amount DESC;这个查询解决两个点第一练习了GROUP BY和JOIN第二产出真实业务里最常见的“销售排行表”。用 pandas 执行同样的关联逻辑可以这样写order_df pd.read_sql(SELECT * FROM sale_order, conengine) product_df pd.read_sql(SELECT * FROM product, conengine) merged pd.merge(order_df, product_df, onproduct_id, howleft) ip_rank merged.groupby(ip_name).agg( order_cnt(order_id, count), total_qty(sale_qty, sum), total_amount(sale_amount, sum) ).reset_index().sort_values(total_amount, ascendingFalse) print(ip_rank)这一步可以同时验证 SQL 取数和 pandas 取数结果是否一致如果不一样往往是因为JOIN时存在非规范化字段数据清洗没做彻底。6.2 月度销售趋势很多公司用“同比、环比”看趋势数据库里不一定做了后续处理。最开始的月粒度计算公式是这样的SELECT DATE_FORMAT(order_time, %Y-%m) AS month, COUNT(order_id) AS order_cnt, SUM(IFNULL(sale_amount, 0)) AS total_amount FROM sale_order GROUP BY month ORDER BY month;注意DATE_FORMAT(order_time, %Y-%m)是一种常用取年月方式。此时提取出来是字符串转成日期后图表呈现更自然。Python 里普通写法是merged[order_time] pd.to_datetime(merged[order_time]) merged[month] merged[order_time].dt.strftime(%Y-%m) monthly merged.groupby(month).agg( total_amount(sale_amount, sum), order_cnt(order_id, count) ).reset_index()后续你可以计算环比增长monthly[pct_change] monthly[total_amount].pct_change() * 100环比结果出来以后就可以观察哪个月的增长异常为结论段准备素材。6.3 价格带分布盲盒产品单价有比较明确的阶梯比如 59、69、79、89、99 甚至更高。价格带分布可以直接反映产品结构。SQL 分段聚合可以这么写SELECT CASE WHEN price 60 THEN 0-60 WHEN price 80 THEN 60-80 WHEN price 100 THEN 80-100 ELSE 100以上 END AS price_range, COUNT(*) AS product_cnt, AVG(sale_amount) AS avg_order_amount FROM product p LEFT JOIN sale_order o ON p.product_id o.product_id GROUP BY price_range;用 Python 分箱也常见。更推荐先用 pandas 查看分布再定断点bins [0, 60, 80, 100, 10000] labels [0-60, 60-80, 80-100, 100以上] merged[price_range] pd.cut(merged[price], binsbins, labelslabels, rightFalse) range_stat merged.groupby(price_range).agg( product_cnt(product_id, nunique), total_qty(sale_qty, sum) ).reset_index()6.4 渠道与城市对比企业一般会关心线下门店、电商、机器人商店的贡献差异以及哪些城市销量靠前。SQL 代码SELECT s.channel, COUNT(o.order_id) AS order_cnt FROM store s LEFT JOIN sale_order o ON s.store_id o.store_id GROUP BY s.channel ORDER BY order_cnt DESC;如果表里还包含城市信息城市维度可以这样看SELECT s.city, SUM(o.sale_amount) AS total_amount FROM store s LEFT JOIN sale_order o ON s.store_id o.store_id GROUP BY s.city ORDER BY total_amount DESC LIMIT 10;很多情况下城市维度的结果不一定体现平衡分布不要为了做图而硬画雷达图直接按 Top 10 排序后画柱状图更能尽快体现你的数据对比能力。6.5 客单价与订单金额分布在订单行如果一笔订单是当时多件商品组合分析客单价时需要将订单拆到订单明细行。可以按订单号聚合金额然后得到客单价分布。先用 SQLSELECT order_id, SUM(sale_amount) AS order_amount FROM sale_order GROUP BY order_id ORDER BY order_amount DESC;接着用 pandas 求四分位数和均值order_amount_df merged.groupby(order_id)[sale_amount].sum().reset_index() desc order_amount_df[sale_amount].describe() print(desc)这样可以判断是少部分大额订单贡献了较高营收还是绝大多数订单集中在某个价格区间。6.6 周期内单店产出渠道和城市之外门店产出值得单列。计算每家店平均每个月贡献金额顺便发现异常值SELECT store_id, COUNT(DISTINCT DATE_FORMAT(order_time, %Y-%m)) AS active_months, SUM(sale_amount) AS total_amount, SUM(sale_amount) / COUNT(DISTINCT DATE_FORMAT(order_time, %Y-%m)) AS avg_month_amount FROM sale_order GROUP BY store_id ORDER BY avg_month_amount DESC;某些店如果活跃月份很少但总金额很高可能意味着渠道差异或数据质量问题。这一个发现就可以作为分析报告里的一个小亮点。7. 可视化图表展示分析结果如果只停留在数字层面还看不出项目完整度。下面给出几种目前最容易出效果的可视化思路与参考代码均使用 pyecharts 的交互式图库。图表输出的最终目的不只是“好看”而是让看报告的人一眼得出业务结论。7.1 热门 IP 金额 Top10 柱状图适合Barfrom pyecharts.charts import Bar from pyecharts import options as opts top10 ip_rank.head(10) bar ( Bar() .add_xaxis(top10[ip_name].tolist()) .add_yaxis(销售额, top10[total_amount].round(2).tolist()) .set_global_opts( title_optsopts.TitleOpts(title热门IP销售额Top10), xaxis_optsopts.AxisOpts(axislabel_optsopts.LabelOpts(rotate15)), yaxis_optsopts.AxisOpts(name销售额) ) ) bar.render(output/ip_top10.html)render方法会生成本地 HTML 文件双击就能在浏览器打开。7.2 月度销售趋势折线图适合Line同时展示销售额变化。from pyecharts.charts import Line from pyecharts import options as opts line ( Line() .add_xaxis(monthly[month].tolist()) .add_yaxis(月度销售额, monthly[total_amount].round(2).tolist()) .set_global_opts( title_optsopts.TitleOpts(title月度销售额趋势), tooltip_optsopts.TooltipOpts(triggeraxis) ) ) line.render(output/monthly_trend.html)曲线出现明显波动时结合业务猜测原因比如“新系列发售 / 营销节点”。即便只是模拟数据也需要养成给结论找解释的习惯。7.3 渠道占比饼图适合Piefrom pyecharts.charts import Pie from pyecharts import options as opts channel_data ... pie ( Pie() .add(, channel_data) .set_global_opts(title_optsopts.TitleOpts(title渠道销售结构)) .set_series_opts(label_optsopts.LabelOpts(formatter{b}: {d}%)) ) pie.render(output/channel_pie.html)饼图的适用前提是分类数不多渠道一般只有 35 类比较合适。如果分类超过 8 个不要用饼图用柱状图更清晰。7.4 城市地图如果希望继续扩展还可以用 pyecharts 的地图组件画出不同城市的销量热力。地图数据通常需要城市名称与官方地理数据完全一致否则不显示。模拟数据阶段不必强求除非你手头确实有全国多城市的门店分布。7.5 可视化项目目录结构建议到这里完整的项目目录可以统一为一个结构清晰的仓库方便以后写进简历和提交 GitHub。popmart-analysis/ ├── data/ │ ├── raw/ │ │ ├── store.csv │ │ ├── product.csv │ │ └── order_data.csv │ └── cleaned/ ├── sql/ │ ├── create_table.sql │ └── analysis.sql ├── scripts/ │ ├── 01_clean_data.py │ ├── 02_import_to_mysql.py │ ├── 03_analysis.py │ └── 04_visualization.py ├── output/ │ ├── ip_top10.html │ ├── monthly_trend.html │ └── channel_pie.html └── README.md这种结构在面试的时候很有优势因为面试官只需看 README 和脚本命名就能理解整个数据流。8. 接口与扩展能力如何升级成“可调用”项目有读者会问这个项目是纯分析脚本不是服务能不能做成接口能。练完基础版后可以加一条扩展线用 FastAPI 把分析结果包装成 HTTP 接口这样别人可以通过 URL 直接拿到处理后的 JSON也更有“工程感”。实现思路from fastapi import FastAPI import pandas as pd from sqlalchemy import create_engine app FastAPI() engine create_engine(mysqlpymysql://root:你的密码127.0.0.1:3306/popmart_sales?charsetutf8mb4) app.get(/api/ip_rank) def ip_rank(): df pd.read_sql( SELECT p.ip_name, SUM(o.sale_amount) AS total_amount FROM sale_order o LEFT JOIN product p ON o.product_id p.product_id GROUP BY p.ip_name ORDER BY total_amount DESC , conengine) return df.to_dict(orientrecords)启动服务pip install fastapi uvicorn uvicorn main:app --host 127.0.0.1 --port 8001 --reload启动后访问http://127.0.0.1:8001/api/ip_rank就能看到 JSON 数据。这个扩展的实际意义在于把“数据分析脚本”升级为“可复用的数据查询服务”简历上可以多写一句“实现了基于 FastAPI 的指标查询接口”。但注意如果你还没掌握基础版的分析流程不要为了炫技先把接口写了。接口只是结果展示的通道分析质量才是这个项目的核心。9. 资源占用与运行性能观察这个项目不需要 GPU运行时的资源占用主要来自 MySQL 服务和 Python IDE。9.1 数据量不大时怎么观察性能模拟数据一共几千行本机跑分析基本是秒级完成。那你运行脚本的时候看什么重点看执行的稳定性pandas.read_sql每次查询会不会因为网络中断或连接占用导致报错。连接用完是否关闭如果使用create_engine没有显式dispose时是否会影响后续脚本。大批量写入时MySQL 的max_allowed_packet是否够用。推荐在执行关键函数时打印耗时import time start time.time() # 执行 SQL 查询 print(查询耗时, time.time() - start)这样面试时你能说出“在几千行数据量下SQL 聚合查询耗时约 0.3 秒可视化渲染耗时约几秒”这比空谈“性能不错”有说服力。9.2 如何防范连接泄漏长时间运行 Jupyter Notebook 时频繁执行read_sql可能留下空闲连接。建议写一个统一的连接获取函数并在任务结束后释放。from sqlalchemy.orm import sessionmaker from contextlib import contextmanager Session sessionmaker(bindengine) contextmanager def get_session(): session Session() try: yield session finally: session.close()当然对本项目简单使用engine.dispose()也足够。10. 常见问题与排查方法问题现象可能原因排查方式解决方案安装 pymysql 后 import 仍报错未激活虚拟环境或安装路径不同pip list查看是否包含 pymysql激活正确的虚拟环境后重装连接 MySQL 报密码错误root 密码设置错误用命令行mysql -uroot -p测试重置密码或修改连接串数据库连接出现Unknown database popmart_sales未建库或库名拼写错误SHOW DATABASES;查看重新执行建库 SQL中文乱码连接串或建表字符集不是 utf8mb4查看表字符集建表统一使用 utf8mb4连接串加charsetutf8mb4日期类型报错CSV 中日期格式不统一打印orders[order_time].head()先用pd.to_datetime统一格式to_sql写入报错 Duplicate entry主键重复检查 order_id 是否唯一先清洗去重或换用if_existsreplacepyecharts 生成的 HTML 打开无内容图表数据为空或浏览器安全限制检查数据 DataFrame 大小确保传入的是 list 而不是空数据虚拟环境已存在但 IDE 未识别PyCharm 解释器配置错误查看设置中的 Python Interpreter切换到虚拟环境 python 路径DataGrip/Navicat 连不上本地 MySQL3306 端口被占或用户权限netstat -anofindstr 3306Windows或lsof -i:3306Linux/macOSExcel 文件读取报缺少 openpyxl未安装 openpyxlpip install openpyxl安装后重新运行项目实际运行时还有一个常见问题MySQL 8.0 默认使用 caching_sha2_password 认证方式比较老的 Python 驱动可能不兼容。如果连接时报Authentication plugin caching_sha2_password cannot be loaded处理办法有几种升级驱动pip install -U pymysql或者改用本地开发时常见的密码插件运行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;这个坑概率很高提前了解能省很多时间。11. 最佳实践与使用建议11.1 数据先备份再清洗原始 CSV / Excel 文件不要直接覆盖。整个流程建议分成 raw、cleaned、output 三个目录。清洗后的数据单独保存一份orders_clean.csv以后重新分析时不必每次都跑一遍清洗脚本。orders.to_csv(data/cleaned/orders_clean.csv, indexFalse, encodingutf-8-sig)编码使用utf-8-sig是因为用 Excel 打开 CSV 时不会出现中文乱码这是 Windows 场景下的实际经验。11.2 SQL 脚本保存下来不建议只在 Python 脚本里拼接字符串。把建表和核心分析 SQL 统一放到sql/目录每次修改用版本管理并在文件头注释需求背景。11.3 分析结论要能讲成故事图表是结果不是目的。你要能说出类似这样的话“从 IP 维度看MOLLY 销量最高但环比增速已经放缓。”“从渠道看电商占比超过线下但客单价低于机器人商店。”“从价格带看69 元价格带的产品数量最多说明品牌主攻入门级。”面试官不会只看图表代码真正拉开差距的是你有没有业务解释能力。11.4 合规与授权无论是自己构造模拟数据还是使用网络公开数据都要确保来源合法、用途合规。个人练手项目尽量避免包含完整的真实用户订单、会员信息、未公开商品计划。简历上展示时建议标注“模拟数据 / 脱敏数据”。11.5 从练手到简历项目练完后简历可以这样写项目名称基于 Python MySQL 的盲盒零售数据分析项目描述设计星型模型数据仓库完成门店、产品、订单三张表的建库与数据清洗使用 SQL 完成多维度聚合查询基于 pandas 进行分析并输出可视化报告。技术要点PyMySQL、SQLAlchemy、pandas、pyecharts、MySQL、FastAPI可选。分析成果输出 IP 热度排行、月度销售趋势、渠道结构、价格带分布等 6 类分析图表定位主要增长 IP 和主力价格带。这个写法能让面试官快速判断你掌握了从数据获取到数据展示的完整链路。12. 总结与下一步这个项目的核心价值在于用最常见的 Python MySQL 技术栈完成了一个有业务数据、有多维分析、有可视化输出的完整项目。它没有依赖特殊硬件也没有复杂框架适合作为数据分析方向的第一份落地产物。做完基础版后如果你还想继续扩展可以优先尝试这几个方向接入真实公开数据源需确认授权与合法性把模拟数据换成真实数据。增加更多维度比如用户留存分析、复购周期分析。把 pyecharts 图表升级成 Web 大屏结合 FastAPI 展示结果。把分析流程写成定时任务定期从数据目录拉取数据并更新图表。建议先按文章顺序把建库、洗数、SQL 分析和可视化完整跑通一遍再考虑扩展。跑通一遍之后把项目文档和脚本整理到 GitHub 上简历里的项目经验就扎实了。