
秋招做简历项目最容易出现两个问题一是照着教程把代码跑了一遍但面试官一问链路细节就说不清楚二是只做了一个展示型 Demo没有把数据存储、清洗、分析和结论串起来。这里要拆解的是一个非常典型的 Python MySQL 招聘数据可视化分析项目。它以类似 BOSS 直聘这类招聘平台上的岗位信息为分析对象但重点不放在数据抓取上而是放在从 MySQL 建表、数据导入、数据清洗、统计聚合到可视化输出的完整流程。这个项目适合准备秋招的数据分析、数据开发、后端开发和部分测试开发岗位也是比较容易写进简历、又不显得空洞的项目之一。我最想说的是这类项目能不能打动面试官不在于数据是不是从真实平台拿到的而在于你有没有把“原始数据 - 结构化入库 - 可计算字段 - 业务分析 - 可视化结论”这条链路讲明白。下面按我实际做过的顺序拆一遍包含环境准备、表结构设计、导入方式、分析口径、图表选型、简历写法和排查思路。新手可以直接照着复现有经验的人也可以当成一次项目复盘来看。1. 先搞懂这个项目的定位是“数据分析项目”还是“爬虫项目”1.1 为什么很多人把它做成爬虫展示我看到过不少同类项目题目写的是“BOSS直聘数据分析”但内容里花了 70% 的篇幅在讲如何请求接口、如何解析 JSON、如何处理验证码、如何绕过反爬限制。这其实是走偏了。原因很简单招聘平台的数据页面和接口随时可能调整抓下来的数据字段也没有统一规范。更关键的是这种实现方式不适合直接写进简历也很难在面试现场复现。面试官更想确认的是你拿到一份有缺失、有格式问题的数据后能不能设计出合理的表结构能不能做有效清洗能不能用图表回答业务问题。所以我把项目定位成“数据可视化分析项目”而不是“爬虫项目”。数据获取部分只需要保证来源合法后面才是这个项目的核心价值。1.2 用合法公开数据把重点放在数据处理链路实际操作时可以自己整理一份样例数据也可以使用公开课程里整理好的招聘数据集或者通过平台开放的数据接口获取允许公开使用的数据。这里不建议去写登录抓取、绕过验证码这类实现。一方面有版权和平台规则风险另一方面对简历项目来说没有必要的技术加分还会让面试官对你的合规意识产生疑问。我建议的数据准备方式是这样的先准备 500 到 2000 条岗位数据字段包含职位名称、公司名称、城市、学历要求、经验要求、薪资范围、岗位分类、发布日期。数据源可以是自己人工整理也可以用公开的招聘数据分析类数据集。文件格式统一为 CSV编码使用 UTF-8。如果数据本身不够干净先不要急后面清洗环节正好可以处理。这样产出的项目重点清楚流程完整也方便扩展。1.3 这个项目对秋招简历的实际价值我把这个项目的价值拆成三层第一层基本功。Python 会链接 MySQL能执行 SQL 查询能用 pandas 做数据聚合能画图。这看起来基础但很多人是割裂学的练的时候会项目里不会串。第二层数据意识。薪资字段怎么拆分、空值怎么处理、城市字段怎么统一、分类字段怎么归类这些能回答“脏数据怎么处理”的问题。第三层工程落地。从建表到批量插入到查询优化到输出报告体现的不是“会某个函数”而是“能独立处理一个小型数据任务”。秋招面试里一个 5000 到 10000 字的项目如果能把这三层都讲出来比堆起来三五个只跑通界面的 Demo 更有效。2. 环境准备用最少工具搭起可复现的数据分析环境2.1 需要安装的软件和库先明确环境清单。这个项目不依赖高端显卡也不吃大内存普通笔记本足够跑。我实测时用的是一台 8GB 内存的 Windows 笔记本跑 5000 条数据非常流畅。软件层需要装三样Python 3.8 或更高版本推荐 3.10 左右比较稳定。MySQL 5.7 或 8.0推荐 8.0字符集和排序规则更省心。一个 SQL 图形化工具MySQL Workbench 或 Navicat 都可以用来查看数据和定位问题。Python 库建议安装以下这几个pip install pymysql pandas matplotlib pyecharts openpyxl各个库的作用可以这样理解表格Python 库和职责库名主要用途pymysqlPython 连接 MySQL执行 SQLpandas读取 CSV、数据清洗、分组聚合matplotlib绘制静态图表适合写进报告pyecharts生成交互式 HTML 图表适合展示openpyxlExcel 文件读写辅助输出分析表Windows 系统经常在安装 matplotlib 时遇到字体或依赖问题后面排查部分会专门说。macOS 和 Linux 的安装差别不大Python 虚拟环境建议建一下避免污染系统环境。2.2 MySQL 初始化最容易踩的两个坑MySQL 装好之后先别急着建库。我每次初始化都要确认两件事。第一字符集。强烈建议把数据库默认字符集设置成 utf8mb4而不是 utf8mb3。招聘数据里可能出现公司名、职位名、城市名中带特殊符号比如“·”“”“C”utf8mb3 在部分场景下会报错或乱码。MySQL 8.0 默认已经是 utf8mb45.7 需要确认一下。第二账号权限。本地学习项目不要直接拿 root 到处连。更稳妥的办法是新建一个专用账号只给一个数据库的权限。这样既能避免权限问题也防止误删其他库。登录 MySQL 后可以执行CREATE DATABASE IF NOT EXISTS recruit_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER your_namelocalhost IDENTIFIED BY your_password; GRANT ALL PRIVILEGES ON recruit_db.* TO your_namelocalhost; FLUSH PRIVILEGES;这里的账号、密码和数据库名后面在 Python 连接参数里要保持一致。很多连接报错本质都是这里对不上。2.3 用一段测试代码确认连接没问题建好库之后先用最短代码测试 Python 到 MySQL 的链路。不要一上来就写几百行。import pymysql conn pymysql.connect( hostlocalhost, port3306, useryour_name, passwordyour_password, databaserecruit_db, charsetutf8mb4 ) cursor conn.cursor() cursor.execute(SELECT VERSION()) result cursor.fetchone() print(MySQL version:, result) cursor.close() conn.close()能输出 MySQL 版本号说明环境通了。如果不能连接先看下面的排查顺序MySQL 服务有没有启动。端口是不是 3306改了端口要同步修改 Python 参数。用户名、密码、数据库名是否正确。用户是否被允许从 localhost 连接。这个“先确认连接再写功能”的顺序非常管用。很多初学者写完一大段代码才发现连接参数错了排查难度立刻翻倍。3. 数据准备与 MySQL 表结构设计先建模再动手3.1 招聘数据需要拆出哪些字段项目能不能做下去第一步取决于字段设计。原始 CSV 不管长什么样到了 MySQL 表里都应该尽量结构化。我建议至少包含这些字段表格招聘数据字段设计字段名类型说明idINT 主键自增每条岗位记录唯一编号job_nameVARCHAR(255)职位名称company_nameVARCHAR(255)公司名称cityVARCHAR(100)工作城市salary_minINT月薪下限单位千元例如 15K 记为 15salary_maxINT月薪上限educationVARCHAR(100)学历要求experienceVARCHAR(100)经验要求job_categoryVARCHAR(100)岗位分类例如开发、测试、数据publish_dateDATE发布日期data_sourceVARCHAR(255)数据来源备注方便回溯薪资字段千万不要存成字符串“15-25K”。虽然可读性强但后面做平均薪资、薪资区间分析时非常痛苦。正确做法是解析成 salary_min 和 salary_max 两个整数。这就是数据建模阶段最重要的一个判断。3.2 建表语句与字段类型选择下面是示例建表语句。如果数据量只有几千条不需要设计复杂索引但 id 主键和 publish_date 索引可以先建上。CREATE TABLE IF NOT EXISTS job_info ( id INT AUTO_INCREMENT PRIMARY KEY, job_name VARCHAR(255) NOT NULL, company_name VARCHAR(255), city VARCHAR(100), salary_min INT, salary_max INT, education VARCHAR(100), experience VARCHAR(100), job_category VARCHAR(100), publish_date DATE, data_source VARCHAR(255) ) DEFAULT CHARSETutf8mb4;字段长短怎么定职位名称和公司名称用 255基本够用。如果明确有很长的公司全称可以在导入前检查 max(len())再决定是否扩大到 500。城市字段用 100一般没问题。经验要求、学历要求这类字段取值种类不多100 足够。这个表结构不追求绝对正确但要求能支撑后续分析。如果你在简历里写“负责表结构设计”面试官一定会问为什么选择这些类型。回答的核心逻辑是根据数据内容、查询需求、存储成本三者做取舍。3.3 数据来源怎么解决公开数据集、样例数据和合法接口我先说清楚文章不会提供登录抓取或平台数据批量采集的实现。招聘数据可视化分析的练习场景完全可以用更稳妥的方式解决数据来源。第一种自己整理样例数据。打开一个招聘 App搜索“数据分析师”手工记录 200 条。这个过程很费时间但你会真正理解原始数据长什么样。第二种使用公开数据集。很多学校课程和数据分析练习社区会提供脱敏后的招聘信息 CSV字段通常包含职位、城市、薪资、学历、经验完全够用。第三种平台开放接口。如果数据源本身提供了允许公开调用的 API可以按接口文档合法获取但要在文档允许的范围内使用。这里有一个建议第一次做不要追求数据量越大越好。5000 条可能比 10 万条更适合。数据量小跑起来快排查问题方便。等流程稳定了再往百万级方向扩展。4. 把数据导入 MySQL单条插入只适合验证批量插入才是常态4.1 先用单条 insert 跑通链路数据导入是很容易出问题的一步。最常见的错误是 CSV 里字段顺序和表字段顺序没对齐导致数据串位。我推荐先跑一条 insertimport pymysql conn pymysql.connect( hostlocalhost, port3306, useryour_name, passwordyour_password, databaserecruit_db, charsetutf8mb4 ) try: with conn.cursor() as cursor: sql INSERT INTO job_info (job_name, company_name, city, salary_min, salary_max, education, experience, job_category, publish_date, data_source) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) values ( 数据分析师, 示例科技, 北京, 15, 25, 本科, 3-5年, 数据, 2026-01-10, sample ) cursor.execute(sql, values) conn.commit() except Exception as e: conn.rollback() print(insert error:, e) finally: conn.close()跑通单条插入说明字段顺序、类型、连接参数都没问题。这时再去处理批量数据会轻松很多。4.2 使用 executemany 批量插入数据量超过几百条之后逐条执行 insert 会非常慢。MySQL 和 pymysql 都提供了批量插入机制原因是减少了客户端和服务端之间的往返次数。import csv import pymysql def load_csv_to_mysql(csv_path): conn pymysql.connect( hostlocalhost, port3306, useryour_name, passwordyour_password, databaserecruit_db, charsetutf8mb4 ) rows [] with open(csv_path, moder, encodingutf-8) as f: reader csv.DictReader(f) for line in reader: rows.append(( line[job_name], line[company_name], line[city], int(line[salary_min]), int(line[salary_max]), line[education], line[experience], line[job_category], line[publish_date], public_csv )) sql INSERT INTO job_info (job_name, company_name, city, salary_min, salary_max, education, experience, job_category, publish_date, data_source) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) try: with conn.cursor() as cursor: cursor.executemany(sql, rows) conn.commit() print(imported rows:, len(rows)) except Exception as e: conn.rollback() print(batch insert error:, e) finally: conn.close()这里要注意几个点CSV 里的薪资字段如果带“K”“k”或汉字必须在导入前处理干净。日期格式要符合 MySQL 的 DATE 类型推荐 YYYY-MM-DD。int() 转换失败时程序会中断。先用 pandas 做一遍预处理会更稳。4.3 中文乱码和字符集问题批量导入最容易遇到的问题是中文乱码。这里要先分清楚是哪个环节出的乱码CSV 文件本身编码不是 UTF-8读取时就乱码。数据库表字符集不是 utf8mb4写入后乱码。Python 连接参数少了 charsetutf8mb4读写时乱码。控制台打印乱码但数据库里正常。排查顺序也是从上往下。我实际处理时最多的情况是 CSV 文件是从 Excel 另存出来的默认编码是 GBK直接用 utf-8 读取就会 UnicodeDecodeError 或出现乱码。解决办法是读取时指定编码或者先在 Excel 里另存为 CSV UTF-8。如果 CSV 已经是 GBK 编码可以这样读取with open(csv_path, moder, encodinggbk) as f: ...但更推荐统一转成 UTF-8避免后面在 MySQL 和图表阶段继续踩坑。4.4 导入后先做数据校验导入完成后不要急着画图。先执行几个验证 SQLSELECT COUNT(*) FROM job_info; SELECT * FROM job_info LIMIT 20; SELECT city, COUNT(*) FROM job_info GROUP BY city ORDER BY COUNT(*) DESC LIMIT 10; SELECT city, AVG((salary_min salary_max) / 2) AS avg_salary_k FROM job_info GROUP BY city ORDER BY avg_salary_k DESC LIMIT 10;这三个查询分别验证数据量、原始内容、基础聚合情况。如果 count 对不上、城市字段有缺失、平均薪资明显异常就要先回头处理数据而不是继续可视化。很多问题在数据分析阶段暴露出来但根因往往在导入阶段。所以导入后花 5 分钟做校验是最值得的 5 分钟。5. 数据清洗与统计口径画图前最容易被忽略的一步5.1 薪资字段如何从字符串变成可计算数值假设原始数据里有字段叫 salary值是“15-25K”“20-35K·14薪”“面议”“30-50K/月”。这些字符串都不能直接参与计算。我建议在导入前或导入后用 Python 做统一清洗逻辑如下去掉“·14薪”这类描述。去掉“/月”这类单位。去掉“K”或“k”。如果遇到“15-25K”拆成 salary_min15salary_max25。如果遇到“面议”可以考虑置空后续分析时剔除。如果遇到“30K以上”可以把 salary_min30salary_max30或者根据业务规则赋一个合理值。这是一段示例清洗函数import re def parse_salary(text): if text is None: return None, None if 面议 in text: return None, None # 去掉单位和额外描述 text text.replace(K, ).replace(k, ).replace(·14薪, ).replace(/月, ).strip() # 匹配 min-max 模式 m re.search(r(\d)\s*-\s*(\d), text) if m: return int(m.group(1)), int(m.group(2)) # 匹配 30以上 或 30及以上 模式 m2 re.search(r(\d)\s*以上, text) if m2: v int(m2.group(1)) return v, v # 匹配单个数值 m3 re.search(r(\d), text) if m3: v int(m3.group(1)) return v, v return None, None判断标准就是一句话清洗后的 salary_min 和 salary_max 能不能被 SQL 的 AVG、MAX、MIN 直接计算。如果不能说明清洗还没到位。5.2 SQL 聚合查询城市、学历、经验、岗位分类薪资处理完成后就可以进入统计口径设计。招聘数据最常见的分析维度有四个城市维度哪些城市岗位多平均薪资高。学历维度数据分析、开发、测试等岗位对学历的要求分布。经验维度不同岗位需要多久经验。岗位分类维度市场需要哪些方向的人才。对应 SQL 示例-- 城市平均薪资岗位均值 SELECT city, COUNT(*) AS job_count, ROUND(AVG((salary_min salary_max) / 2), 1) AS avg_salary FROM job_info WHERE salary_min IS NOT NULL AND salary_max IS NOT NULL GROUP BY city ORDER BY avg_salary DESC LIMIT 15;学历分布SELECT education, COUNT(*) AS job_count FROM job_info GROUP BY education ORDER BY job_count DESC;这里要提醒一点“本科及以上”和“本科”在字符串层面是两个值如果直接 group by会出现两个独立类别。是否需要合并取决于业务口径。如果不确定先保留原始值画图前再在 pandas 里做映射。5.3 为什么先用 LIMIT 和 COUNT 验证很多新手一上来就写一个复杂的多表 JOIN 或子查询一旦结果不对根本分不清是数据问题还是 SQL 问题。我更推荐这种方式先 SELECT COUNT(*) 看总行数。先 SELECT * LIMIT 50 看原始字段。再单表 GROUP BY 验证某一维度。最后拼复杂查询。这个顺序能帮你在第一步发现问题。比如城市字段里有“北京”“北京市”“北京·朝阳区”直接 group by 会得到三个城市但业务上可能属于同一城市。这时候要在清洗阶段统一而不是在可视化时想办法“骗过去”。6. 可视化分析用图表讲出三个业务结论6.1 图表选型柱状图、饼图、横向条形图可视化不是简单地“把数据变成图”。先想清楚要回答什么问题再决定图类型。表格分析维度与图表选型分析目标推荐图表原因城市岗位数量和平均薪资柱状图或横向条形图方便对比城市差异学历要求分布饼图或环形图展示占比关系经验要求分布横向条形图类别名称较长横排更易读岗位分类词频词云或横向条形图快速体现人才需求方向薪资区间分布直方图或箱线图反映数据分布和异常值第一次做项目不用把所有图表类型都上一遍。做 4 到 5 张关键图足够了。6.2 matplotlib 示例城市平均薪资 Top 15下面示例使用 pandas 读取 MySQL 查询结果再用 matplotlib 画图。import pandas as pd import pymysql import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] plt.rcParams[axes.unicode_minus] False conn pymysql.connect( hostlocalhost, port3306, useryour_name, passwordyour_password, databaserecruit_db, charsetutf8mb4 ) sql SELECT city, COUNT(*) AS job_count, ROUND(AVG((salary_min salary_max) / 2), 1) AS avg_salary FROM job_info WHERE salary_min IS NOT NULL AND salary_max IS NOT NULL GROUP BY city ORDER BY avg_salary DESC LIMIT 15 df pd.read_sql(sql, conn) conn.close() df df.sort_values(byavg_salary, ascendingFalse) plt.figure(figsize(10, 6)) plt.bar(df[city], df[avg_salary], color#4C72B0) plt.title(招聘岗位平均月薪 Top15 城市单位K) plt.xlabel(城市) plt.ylabel(平均月薪K) plt.xticks(rotation45) plt.tight_layout() plt.savefig(output/city_avg_salary.png, dpi200) plt.show()这里有一个细节第一次画图时很多人发现中文乱码或方块。解决办法是设置中文字体。不同操作系统字体名不一样Windows 常用 SimHei、Microsoft YaHeimacOS 常用 PingFang SC。实在不行可以用plt.rcParams[font.sans-serif]一次多传几个备选字体。先打印df.head()再画图是我常用的习惯。图形是给人看的数据表的数字才最准确。如果图形和表对不上一定是数据或映射出了问题。6.3 pyecharts 示例学历要求分布matplotlib 适合静态报告pyecharts 适合交互式展示。做毕业设计或简历演示时pyecharts 生成的 HTML 页面看起来更完整。from pyecharts.charts import Pie from pyecharts import options as opts import pandas as pd import pymysql conn pymysql.connect( hostlocalhost, port3306, useryour_name, passwordyour_password, databaserecruit_db, charsetutf8mb4 ) sql SELECT education, COUNT(*) AS job_count FROM job_info WHERE education IS NOT NULL GROUP BY education ORDER BY job_count DESC df pd.read_sql(sql, conn) conn.close() data_pair [list(x) for x in zip(df[education], df[job_count])] pie Pie() pie.add( series_name学历要求分布, data_pairdata_pair, radius[40%, 70%] ) pie.set_global_opts(title_optsopts.TitleOpts(title招聘岗位学历要求分布)) pie.set_series_opts(label_optsopts.LabelOpts(formatter{b}: {c} ({d}%))) pie.render(output/education_pie.html)输出一个 HTML 文件后浏览器打开就能看到交互式图表。这个展示效果在面试演示时比静态图片更直观但不要只做图表还要能解释每个占比背后的业务含义。6.4 中文显示、图片保存和最终报告组织项目目录建议这样组织recruit_analysis/ ├── data/ │ └── job_sample.csv ├── sql/ │ └── create_tables.sql ├── src/ │ ├── db_connect.py │ ├── clean_data.py │ └── visualize.py ├── output/ │ ├── city_avg_salary.png │ └── education_pie.html └── README.md图片和 HTML 统一放在 output 目录不要和源码混在一起。README 里写清楚项目背景、表结构、运行步骤和结果结论。很多面试官看简历前会先看 GitHub 或博客一个结构清晰的项目比大段文字更容易留下好印象。图表保存时建议把分辨率调到 150 到 200 DPI避免写进简历或报告后模糊。HTML 图表则要确认打开的浏览器可以正常加载 js 资源。7. 简历写法和面试准备项目经历不能只写工具名7.1 项目经历可以这么写很多人简历上写“使用 Python 和 MySQL 实现招聘数据可视化分析”这是最无效的写法。面试官看完只会得到一个信息这个人装了 Python 和 MySQL。更合理的写法是突出数据和流程数据集处理了约 5000 条招聘数据涵盖 20 城市、6 个岗位方向。存储建模设计 job_info 表结构拆分薪资区间字段通过 pymysql 实现批量入库。数据处理完成薪资字符串解析、城市字段统一、学历映射等清洗工作。分析方法从城市、学历、经验、岗位四个维度统计岗位需求与薪资分布。可视化基于 matplotlib 和 pyecharts 输出静态图表和交互式页面。简历上不要写“独立完成”就完事要加具体动作。比如“独立完成从 CSV 到 MySQL 的批量导入”比“负责数据处理”更可信。7.2 面试官最可能问的几个问题这里面试官大概率会问到几个细节建议提前准备第一个问题薪资字段你为什么要拆成 min 和 max而不是直接存字符串回答思路字符串无法参与数值计算。拆成两个整数后可以用 SQL 的 AVG、MAX、MIN 直接计算也可以用(salary_min salary_max) / 2估算平均薪资。后面画直方图或做薪资区间过滤也更方便。第二个问题城市字段里有“北京”“北京市”“北京·朝阳区”怎么处理回答思路如果只是展示可以把“北京·朝阳区”归到“北京”。但如果要分析区级岗位分布保留原值。项目里要根据业务目标决定统一口径不能一刀切。第三个问题为什么不用 Excel 分析要用 MySQL回答思路Excel 在小数据量下够用但无法体现数据库建模、SQL 聚合、批量数据导入和权限管理这些能力。秋招项目要展示的是工程化思路MySQL 的参与让项目更接近生产环境。第四个问题数据量到百万级你的表结构和查询会不会卡回答思路可以在 publish_date、city 字段上建索引用分页查询替代一次性加载使用窗口函数或临时表减少重复聚合。这个项目如果只是 5000 条很多优化不需要做但面试官想看的是你有没有这个意识。7.3 简历里关于数据量和分析结论的表达简历里的项目经验不是论文摘要要用“动词 结果”的形式。比如清洗 5000 条招聘数据统一薪资、城市、学历等 8 类字段口径。设计 MySQL 表结构使用 pymysql 实现批量入库导入耗时约 3 秒。输出 5 张数据分析图覆盖城市薪资、学历分布、经验要求、岗位需求等维度。如果数据量比较小就不要写“海量数据”。面试官更接受真实的小数据项目虚拟一个“百万级数据”反而容易被追问到漏洞。8. 常见报错与排查链路从现象到原因8.1 连接不上 MySQL先检查服务、端口和账号这个项目最常遇到的报错是连接 MySQL 失败。报错关键词通常是 Cant connect、Access denied、Unknown database。排查顺序按这个来确认 MySQL 服务已启动。Linux 可以用 systemctl status mysqlWindows 可以在服务管理里查看。确认端口。默认 3306如果之前改过端口Python 连接参数要同步。确认用户名和密码。建议先到命令行用同样的账号密码登录一次排除权限问题。确认数据库名。如果连接参数里写错库名会报 Unknown database。确认 Python 进程和 MySQL 是否在同一台机器和同一网络。如果是远程数据库还要检查防火墙、bind-address 等配置。不要一开始就怀疑代码逻辑。连接类报错先用最外层命令验证网络和服务再往里层看参数。8.2 中文乱码和非法字符导入中文时出现乱码或 “Incorrect string value”优先检查三层CSV 文件编码推荐 UTF-8。MySQL 表字符集推荐 utf8mb4。pymysql 连接参数是否带 charsetutf8mb4。如果表已经建好发现字符集不对可以执行ALTER TABLE job_info CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;但如果乱码已经写入改完字符集后仍需要清洗已有数据。所以更好的是在建表时就确认好。另外公司名、职位名里可能包含分词库不认识的字符比如 Emoji 或特殊符号。utf8mb4 能存utf8mb3 可能报错。这也是为什么推荐 8.0 的原因之一。8.3 图表不显示或空白图表没有出现常见原因有三种。第一种环境没有图形界面。在服务器或远程终端里执行 plt.show()不会弹出窗口。解决办法是改成 plt.savefig()把图片保存到文件再打开查看。第二种数据查询结果为空。画图之前先打印 df.head() 或 df.info()。如果为空说明 SQL 条件有问题或者清洗后 salary 字段被置空了聚合结果自然没有数据。第三种中文乱码导致 label 显示为方块。按前面说的配置中文字体即可。如果还不行可以给图表加fontproperties指定一个系统存在的字体文件路径。pyecharts 生成的 HTML 空白最可能是脚本运行时没联网加载 CDN 的 js 文件或者浏览器扩展拦截了本地资源。可以检查 HTML 的 js 引入路径也可以取消浏览器对本地文件的限制。8.4 数据量变大后如何优化如果用 10 万或百万条数据跑这个项目原来的写法会变慢。优化方向有四个SQL 层加索引比如 city、publish_date、job_category。一次性少取数据用 LIMIT 分页或按日期切片。重复查询拆成多个临时表减少 JOIN 的扫描范围。使用 MySQL 的存储过程或定时任务把固定分析流程自动化。这些点即便不在基础版本里实现也建议在文档里作为“后续优化方向”写出来。面试官提问时你能接得住比死记答案更有说服力。9. 最后说点实在的这个项目真正落地时最值得花时间的不是跑通图表代码而是把数据准备、字段清洗、统计口径这三件事做好。很多同学卡在“数据不干净”就放弃或者靠手动改 Excel 强行把数据弄整齐。真实项目中脏数据是常态清洗能力才是核心竞争力。作为秋招准备我建议先把单条流程跑通再用 1000 条左右的数据做完整分析最后再决定要不要扩展更多字段和图表。一口吃不成胖子一个能讲清楚的小项目比一个半懂不懂的大项目要实用得多。最后提醒一句做项目时把每次报错和解决方式记录在 README 里这个方法我用了很久。面试前翻一遍比临时记忆一堆理论答案更有效。