
在实际的商业分析、游戏运营和毕业设计选题中评论数据一直是被反复提起但又不好落地的数据源。以“黑悟空评论数据分析系统项目编号 0180”为例这个课题并不是简单写一个爬虫而是要把“评论采集、数据清洗、情感分析、统计聚合、可视化展示”串成一条完整的处理链路。整条链路跑通之后用户可以看到评论量趋势、好评率变化、玩家高频关注点和情感倾向分布进而为游戏口碑跟踪和运营决策提供依据。这篇文章围绕一个可演示、可复现的评论数据分析系统展开重点讲清四个问题系统由哪些模块组成、每条数据从采集到展示经过哪些环节、关键代码和参数怎么设计、演示环境出问题时从哪里查起。整篇文章使用的技术方案适合本科毕业设计、课程实训和小型数据分析项目参考读者可以按顺序把系统搭出来并在答辩时解释清楚每个模块的设计理由。1. 评论数据分析系统的需求拆解与技术选型1.1 毕业设计演示要解决什么问题毕业设计项目的演示效果往往不在功能列表有多长而在数据是否能从原始状态变成有价值的分析结果。很多同学拿到“评论数据分析系统”这个题目后第一反应是“先写爬虫抓评论”但抓下来之后发现数据是 JSON、是英文、是重复的甚至夹杂大量无意义短文本根本没法直接分析。真正的问题不是“缺数据”而是“数据到知识的转换链路不完整”。这个项目的核心目标是把《黑神话悟空》在 Steam 平台上的玩家评论作为分析对象完成以下闭环采集评论原始数据保存到关系型数据库。对评论文本做去重、过滤、长度筛选。统计评论的时间分布、推荐状态占比、评论长度等基础画像。对中文评论做情感打分判断玩家对游戏的整体情绪。使用分词和关键词提取找到玩家讨论的高频主题。通过 Web 页面展示统计指标和图表形成看板。整个系统的亮点不在某一个算法有多深而在每一层都有明确产出。评审老师问“数据从哪里来、结果怎么算出来、图表怎么渲染”时你能从数据库表一路讲到 ECharts 页面这比只贴一个爬虫代码要完整得多。1.2 技术栈选型技术选型的核心原则是“学习成本低、演示效果好、每个组件都能说明白”。本系统建议使用 Python 生态原因有三采集脚本容易写pandas 处理表格数据方便SnowNLP、jieba、wordcloud 这些中文文本处理库的安装和使用都很直接。模块技术选型作用数据采集Python requests调用 Steam 官方评论接口获取评论 JSON数据存储MySQL 8.0保存评论明细和去重标记数据处理pandas numpy清洗、去重、聚合统计情感分析SnowNLP对中文评论计算情感得分分词与关键词jieba jieba.analyse提取评论高频词与主题关键词词云生成wordcloud matplotlib生成词云图片用于看板展示Web 服务Flask提供统计接口和页面渲染前端图表ECharts展示折线图、柱状图、饼图、仪表盘这里需要解释一下为什么选择 MySQL 而不是 SQLite。SQLite 在本地调试时确实省事但毕业设计评阅时老师通常希望看到“数据库设计”和“SQL 语句”MySQL 的多表查询、索引、字符集配置也更容易讲出工程味道。如果演示机器上没有 MySQL 服务可以使用 Docker 运行一个 MySQL 8.0 容器这样环境干净、卸载方便。1.3 数据流与模块划分系统的数据流向按“源数据 - 明细数据 - 特征数据 - 展示数据”四层划分每一层对应独立的代码目录和功能模块。第一层是采集层。采集器请求 Steam 评论接口拿到评论列表后解析出作者、正文、时间、推荐状态、点赞数等字段写入 MySQL 的wukong_comments表。第二层是清洗层。使用 pandas 从数据库读入 DataFrame删除评论字段为空的记录按评论内容的 MD5 值去重过滤过短文本最后把清洗结果写回分析表或者直接在 DataFrame 中继续分析。第三层是分析层。对日期列做按月或按周聚合统计推荐与不推荐的数量计算好评率运行 SnowNLP 对每条评论做情感打分再使用 jieba 抽取 TOP 关键词。第四层是展示层。Flask 提供/api/overview、/api/trend、/api/keywords等 JSON 接口前端页面通过 ECharts 请求这些接口并渲染图表。这样划分之后每一层都能独立测试。采集层跑完先看看数据库里有多少条记录分析层跑完先打印几个统计数字展示层做出来之后整个系统的演示流程就自然成立了。2. 环境准备与项目骨架搭建2.1 环境要求开发机建议使用 Windows 10/11 或 LinuxPython 版本选择 3.9 或 3.10。这里要特别提醒SnowNLP 在更高版本 Python 下通常也能用但为了避免依赖编译问题建议使用 3.10 以下版本。如果原始部署环境只支持 Python 3.11 以上先测试pip install snownlp是否能成功再继续后面的环节。依赖建议版本用途Python3.9 / 3.10主开发语言requests2.31.x调用评论接口pandas2.0.x数据处理PyMySQL1.1.xMySQL 连接Flask3.0.xWeb 服务snownlp0.12.3中文情感分析jieba0.42.1中文分词与关键词wordcloud1.9.x词云生成matplotlib3.7.x词云底图渲染创建虚拟环境并安装依赖的命令如下mkdir wukong-comment-analysis cd wukong-comment-analysis python -m venv venv # Windows venv\Scripts\activate # Linux / macOS source venv/bin/activate pip install requests pandas pymysql flask snownlp jieba wordcloud matplotlib安装完成后用pip list检查版本。如果 wordcloud 安装失败通常是本机缺少 C 编译器可直接下载对应 Python 版本的.whl文件离线安装也可以退回1.8.1版本重试。2.2 初始化数据库MySQL 中需要创建数据库和分析表。这里使用 Docker 启动 MySQL 最省事docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD123456 \ -e MYSQL_DATABASEgame_comment \ mysql:8.0等容器启动后连接数据库执行建表 SQL。评论表的字段设计要覆盖采集接口能提供的全部关键信息同时额外增加review_md5字段用于去重。CREATE DATABASE IF NOT EXISTS game_comment DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; USE game_comment; CREATE TABLE IF NOT EXISTS wukong_comments ( id INT AUTO_INCREMENT PRIMARY KEY, appid INT NOT NULL COMMENT Steam 游戏 ID, author_id VARCHAR(64) NOT NULL COMMENT 评论者 ID, author_name VARCHAR(128) DEFAULT NULL, language VARCHAR(32) DEFAULT NULL COMMENT 评论语言, review_text TEXT NOT NULL COMMENT 评论正文, review_md5 CHAR(32) NOT NULL COMMENT 评论去重标识, timestamp_created DATETIME NOT NULL COMMENT 评论时间, voted_up TINYINT NOT NULL DEFAULT 0 COMMENT 是否推荐, votes_helpful INT DEFAULT 0 COMMENT 有帮助数, votes_funny INT DEFAULT 0 COMMENT 有趣数, weighted_vote_score FLOAT DEFAULT 0 COMMENT 加权评分, sentiment_score FLOAT DEFAULT NULL COMMENT 情感得分, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_review_md5 (review_md5), KEY idx_time (timestamp_created), KEY idx_voted_up (voted_up), KEY idx_sentiment (sentiment_score) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT黑神话悟空评论明细表;关键点是review_md5的唯一索引。评论接口在翻页过程中可能出现重复数据靠这条唯一索引可以保证重复记录直接插入失败配合INSERT IGNORE或ON DUPLICATE KEY UPDATE实现幂等写入。2.3 项目目录与配置目录结构按“采集、清洗、分析、展示、脚本”拆分每个模块职责清晰wukong-comment-analysis/ ├── config.py # 数据库连接配置 ├── scripts/ │ ├── fetch_comments.py # 采集评论 │ └── generate_sample.py # 生成模拟评论数据 ├── analysis/ │ ├── clean_data.py # 清洗与统计 │ ├── sentiment_analysis.py # 情感分析 │ └── keyword_extract.py # 关键词提取与词云 ├── webapp/ │ ├── app.py # Flask 应用 │ ├── static/ # ECharts 和自定义 JS │ └── templates/ │ └── index.html # 看板页面 └── requirements.txt数据库连接配置单独放到config.py避免每个脚本都写一遍连接参数DB_CONFIG { host: 127.0.0.1, port: 3306, user: root, password: 123456, database: game_comment, charset: utf8mb4, }实际项目如果使用远程数据库把host和password改掉即可。生产环境不要把这些参数硬编码到代码里建议读取环境变量但没有项目背景时可以先把配置集中管理。3. 评论采集官方接口、翻页逻辑与入库3.1 接口返回结构Steam 提供的是公开评论接口路径格式为https://store.steampowered.com/appreviews/{appid}?json1《黑神话悟空》的 Steam appid 是1245620。接口返回的 JSON 中包含success、cursor、reviews等字段。其中cursor是下一页的游标标记reviews是评论数组。单个评论对象的关键字段如下字段含义author.steamid评论者 Steam IDauthor.name评论者昵称language评论语言如 schinesereview评论正文timestamp_created评论创建时间戳voted_up是否推荐该游戏votes_helpful被认为有帮助的次数votes_funny被认为有趣的次数weighted_vote_score评论加权投票分数如果请求参数中设置languageschinese接口会优先返回中文评论。但 Steam 评论接口在不同网络环境下的可达性并不稳定如果演示机器无法访问该域名先用本地模拟数据把流程跑通这一步在后面会专门说明。3.2 编写采集器采集器要完成三件事请求接口、解析字段、写入 MySQL。为了降低对官方接口的压力每翻一页后休眠 1 秒。import hashlib import time import pymysql import requests from config import DB_CONFIG APPID 1245620 BASE_URL https://store.steampowered.com/appreviews/{appid} HEADERS { User-Agent: ( Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36 ) } def review_md5(text: str) - str: return hashlib.md5(text.encode(utf-8, errorsignore)).hexdigest() def insert_review(cursor, item: dict) - None: author item.get(author, {}) text item.get(review, ) ts item.get(timestamp_created, 0) created time.strftime(%Y-%m-%d %H:%M:%S, time.localtime(ts)) sql INSERT IGNORE INTO wukong_comments (appid, author_id, author_name, language, review_text, review_md5, timestamp_created, voted_up, votes_helpful, votes_funny, weighted_vote_score) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) cursor.execute(sql, ( APPID, author.get(steamid, ), author.get(name, ), item.get(language, ), text, review_md5(text), created, 1 if item.get(voted_up) else 0, item.get(votes_helpful, 0), item.get(votes_funny, 0), item.get(weighted_vote_score, 0), )) def fetch_comments(max_pages20): conn pymysql.connect(**DB_CONFIG) cursor conn.cursor() start_cursor * for page in range(max_pages): params { json: 1, filter: all, language: schinese, num_per_page: 20, cursor: start_cursor, purchase_type: all, } resp requests.get(BASE_URL.format(appidAPPID), paramsparams, headersHEADERS, timeout10) data resp.json() reviews data.get(reviews, []) or [] for item in reviews: insert_review(cursor, item) conn.commit() print(fpage {page 1}: fetched {len(reviews)} reviews) next_cursor data.get(cursor) if not reviews or next_cursor start_cursor: break start_cursor next_cursor time.sleep(1) cursor.close() conn.close() if __name__ __main__: fetch_comments(max_pages20)运行脚本后在 MySQL 中查看数据量SELECT COUNT(*) FROM game_comment.wukong_comments;如果返回 0先检查请求 URL 是否真实可达、返回 JSON 中success是否为 1。不要急着改代码可以用下面这条命令确认接口内容curl https://store.steampowered.com/appreviews/1245620?json1languageschinesenum_per_page13.3 入库去重策略评论去重是必须处理的细节。原因有两个第一官方接口在翻页时可能存在重复返回第二同一条评论如果多次运行采集脚本不处理会变成脏数据。这里的方案是给评论内容计算 MD5作为数据库唯一键。INSERT IGNORE在遇到重复主键或唯一键时不会报错也不会写入所以重复采集时数据量不会虚增。另一个细节是时间解析。接口返回的timestamp_created是 Unix 时间戳采集时直接转成 MySQL 的DATETIME格式。如果项目后续要按周或按月聚合日期字段必须是数据库可排序的类型不能保留为字符串。4. 评论清洗与基础画像分析4.1 清洗规则采集到原始评论后不能直接进分析层。评论数据常见的问题包括重复文本、过短评论、非中文评论、空作者等。清洗阶段的目标是生成一个干净、可统计的 DataFrame。清洗规则如下检查项清洗策略原因review_md5 重复保留第一条防止重复评论影响统计review_text 为空删除无法参与文本分析评论长度小于 5删除短文本情感判断不准确时间字段为空删除无法参与时间趋势分析超出业务时间范围保留并检查可能是指定时间窗口外的评论清洗代码放在analysis/clean_data.pyimport pandas as pd import pymysql from config import DB_CONFIG def load_data(): conn pymysql.connect(**DB_CONFIG) sql SELECT * FROM wukong_comments df pd.read_sql(sql, conn) conn.close() return df def clean_data(df: pd.DataFrame) - pd.DataFrame: print(f原始数据量: {len(df)}) df df.drop_duplicates(subset[review_md5], keepfirst) print(f去重后数据量: {len(df)}) df df[df[review_text].notna()] df df[df[review_text].str.strip() ! ] df[review_len] df[review_text].apply(len) df df[df[review_len] 5] df[timestamp_created] pd.to_datetime(df[timestamp_created]) df df[df[timestamp_created].notna()] print(f清洗后数据量: {len(df)}) return df if __name__ __main__: raw load_data() cleaned clean_data(raw) print(f清洗后剩余 {len(cleaned)} 条评论)4.2 画像指标基础画像指标不需要太复杂但要能从业务角度讲清楚意义。通常输出四类指标第一类是总体量。评论总数、清洗后评论数、采集覆盖率用来判断样本是否足够。第二类是推荐率。按voted_up分组统计voted_up1表示玩家推荐voted_up0表示不推荐。好评率等于推荐数除以有效评论总数。第三类是时间分布。按天、周、月统计评论量可以观察游戏发售、版本更新等时间点的讨论热度变化。第四类是评论长度分布。评论长度可以粗略反映玩家表达意愿长评论往往带有更具体的体验细节。统计代码def overview_stats(df: pd.DataFrame) - dict: total len(df) recommended int(df[voted_up].sum()) not_recommended total - recommended rate round(recommended / total * 100, 2) if total else 0 return { total: total, recommended: recommended, not_recommended: not_recommended, recommend_rate: rate, } def trend_stats(df: pd.DataFrame) - pd.DataFrame: df[date] df[timestamp_created].dt.strftime(%Y-%m-%d) trend df.groupby(date).agg( total(id, count), recommended(voted_up, sum), ).reset_index() trend[not_recommended] trend[total] - trend[recommended] return trend这段代码输出的overview_stats可以直接给 Flask 接口使用。trend_stats生成折线图所需的日期、总数和推荐数三列。4.3 输出示例清洗和统计完成后可以在控制台看到类似输出原始数据量: 487 去重后数据量: 461 清洗后数据量: 428 清洗后剩余 428 条评论 总体概览: - 评论总数: 428 - 推荐: 366 - 不推荐: 62 - 好评率: 85.51%这里的好评率只是基于评论的统计值不等同于游戏真实好评率因为采集数量有限而且语言过滤后样本并不完整。答辩时一定要说明样本口径可以在页面标题下标注“样本数据仅用于系统演示”。5. 情感分析、关键词提取与领域修正5.1 情感分析的基本思路评论分析系统如果只统计推荐和不推荐说服力不够。很多玩家会写“游戏很好但优化有问题”这样的句子单纯二分类会丢失情绪倾向。所以需要给每条评论计算一个情感得分范围在 0 到 1 之间越接近 1 表示情感越正面越接近 0 表示情感越负面。这里采用 SnowNLP。它的实现原理是基于朴素贝叶斯分类器训练出的中文情感分析模型使用非常方便from snownlp import SnowNLP s SnowNLP(画面非常震撼期待很久了) print(s.sentiments)输出通常大于 0.5说明模型判断为正面情感。但需要注意SnowNLP 的训练语料以电商购物评论为主对游戏领域词汇的覆盖不一定准确。直接用于游戏评论时可能把“打击感不错但难度太高”判成负面。因此本系统在基础情感得分上增加领域修正规则保证演示效果更贴近真实阅读感受。5.2 基于 SnowNLP 的情感打分实现打分函数放在analysis/sentiment_analysis.pyfrom snownlp import SnowNLP POSITIVE_WORDS [惊艳, 震撼, 好玩, 推荐, 神作, 满分, 满意] NEGATIVE_WORDS [卡顿, 闪退, 难受, 失望, 优化差, 退款, 差评, bug] def adjust_score(text: str, base_score: float) - float: score base_score for word in POSITIVE_WORDS: if word in text: score min(1.0, score 0.1) for word in NEGATIVE_WORDS: if word in text: score max(0.0, score - 0.1) return round(score, 4) def score_comment(text: str) - float: base_score SnowNLP(text).sentiments return adjust_score(text, base_score) def add_sentiment_scores(df): df[sentiment_score] df[review_text].apply(score_comment) return df这段代码的解释分两层第一层是基础模型打分SnowNLP 已经给出了 0 到 1 的分数第二层是领域词典修正游戏评论里的特定词能明显影响情绪判断通过关键词加权让分数更接近玩家真实态度。情感得分区间可以直接用于页面上的仪表盘情感得分区间判断倾向示例场景0.0 - 0.4偏负面“优化太差频繁闪退”0.4 - 0.6中性“还行就是难度有点高”0.6 - 0.8偏正面“画面不错战斗系统有特色”0.8 - 1.0正向积极“年度最佳值得购买”5.3 关键词提取与词云关键词提取使用 jieba 自带的关键词接口。需要过滤掉“真的、这个、一个、什么、游戏、还是”这类无信息量的词。这里准备一个自定义停用词集合然后再调用jieba.analyse.extract_tags。import jieba.analyse STOP_WORDS {这个, 一个, 没有, 什么, 就是, 真的, 可以, 还是, 我们, 你们} def extract_keywords(df, top_n20): text_all .join(df[review_text].tolist()) jieba.analyse.set_stop_words_from_offline_text None keywords jieba.analyse.extract_tags( text_all, topKtop_n, withWeightTrue, allowPOS(n, v, vn, a, ad), ) result [{name: k, value: round(w, 4)} for k, w in keywords if k not in STOP_WORDS] return result值得注意的一点如果直接把全部评论拼接成一个超长字符串再提取关键词高频词可能偏向“悟空”“游戏”“黑神话”这类反复出现的词。这其实是业务上的正常结果但看板演示时重点应该是“画面、优化、战斗、剧情、打击感”这些有业务含义的词。因此可以在分析前把review_text中的“悟空”“黑神话”“游戏”“这款”等词加入停用词表让关键词分布更真实。词云生成部分依赖 wordcloud中文字体在 Linux 下经常出问题推荐在代码中显式指定字体路径from wordcloud import WordCloud import matplotlib.pyplot as plt import jieba def generate_wordcloud(text: str, output_path: str): wc WordCloud( font_pathC:/Windows/Fonts/simhei.ttf, # Windows 示例路径 width1200, height600, background_colorwhite, max_words100, ).generate(text) plt.figure(figsize(12, 6)) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.savefig(output_path, dpi150, bbox_inchestight)Linux 服务器如果没有中文字体可以先执行fc-list :langzh查看是否安装了中文字体。没有的话可以把 Windows 下的simhei.ttf上传到项目字体目录再用绝对路径引用。这一步虽然小但很容易在演示现场变成空白方块图。6. 可视化看板Flask 接口与 ECharts 页面6.1 数据接口设计分析结果需要通过 Web 页面呈现。Flask 的作用不是复杂业务而是把数据库中的统计结果转换成前端可以消费的 JSON 接口。这里设计 4 个核心接口接口返回内容对应图表/api/overview评论总数、推荐数、好评率、情感均值顶部指标卡片/api/trend按日期的评论量和推荐量折线图/api/sentiment情感得分区间分布柱状图/api/keywordsTOP 20 关键词及权重横向条形图或词云app.py的核心实现如下from flask import Flask, jsonify, render_template import pandas as pd from analysis.clean_data import load_data, clean_data, overview_stats, trend_stats app Flask(__name__) app.route(/) def index(): return render_template(index.html) app.route(/api/overview) def api_overview(): df clean_data(load_data()) return jsonify(overview_stats(df)) app.route(/api/trend) def api_trend(): df clean_data(load_data()) trend trend_stats(df) data { date: trend[date].tolist(), total: trend[total].tolist(), recommended: trend[recommended].tolist(), } return jsonify(data) if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)接口每次请求都重新加载数据在演示场景下够用但生产环境必须考虑缓存。不要在前端页面刷新时反复执行全量清洗逻辑应该把统计结果提前计算好存入一张聚合表或 Redis 缓存中。6.2 页面配置前端页面采用静态 HTML 加 ECharts 的方式避免引入大型前端构建工具。页面在templates/index.html中加载本地 ECharts 文件再依次请求接口。!DOCTYPE html html langzh-CN head meta charsetUTF-8 title黑悟空评论数据分析看板/title script src/static/js/echarts.min.js/script /head body div idoverview-cards/div div idtrend-chart styleheight: 400px;/div div idsentiment-chart styleheight: 400px;/div div idkeyword-chart styleheight: 400px;/div script src/static/js/dashboard.js/script /body /html在dashboard.js里用fetch拿接口数据后交给 ECharts 渲染。折线图示例fetch(/api/trend) .then(res res.json()) .then(data { const chart echarts.init(document.getElementById(trend-chart)); chart.setOption({ title: { text: 评论量趋势 }, tooltip: { trigger: axis }, xAxis: { type: category, data: data.date }, yAxis: { type: value }, series: [ { name: 评论总数, type: line, data: data.total }, { name: 推荐数, type: line, data: data.recommended } ] }); });这里要注意浏览器访问页面时如果 Flask 运行在0.0.0.0:5000演示环境可以先用浏览器打开http://127.0.0.1:5000。如果是远程服务器要使用服务器 IP 替换127.0.0.1并确保防火墙放行 5000 端口。6.3 演示环境的启动顺序演示时不要直接运行python webapp/app.py应该按固定顺序启动避免现场因为顺序错误导致数据为空。第一步确认 MySQL 容器运行并且wukong_comments表有数据docker ps mysql -h127.0.0.1 -uroot -p123456 -e select count(*) from game_comment.wukong_comments;第二步检查关键 Python 依赖是否齐全pip list | grep -E flask|snownlp|jieba|pandas第三步启动 Flaskcd wukong-comment-analysis python webapp/app.py第四步浏览器验证打开/api/overview确认返回 JSON。打开/api/trend确认时间序列有数据。打开首页确认图表正常渲染。注意演示时最好在本地准备模拟数据。如果现场网络无法访问 Steam 评论接口至少保证系统界面和统计流程可以展示。7. 常见问题、排查链路与答辩准备7.1 高频问题对照表问题现象常见原因检查方式处理建议采集脚本返回 0 条评论网络不可达、语言参数无数据、appid 错误用 curl 请求接口查看 JSON改用本地模拟数据确认接口返回中 reviews 数组长度MySQL 插入中文乱码数据库字符集不是 utf8mb4show variables like character_set_server;创建数据库时指定 utf8mb4连接参数添加 charset评论数很少只有几十条接口默认只返回当前游标前数据采集页数太少查看采集日志每页获取数量调大 max_pages使用 filterall 获取全部类型情感得分几乎全是 0.9修正词加权过大或样本以正面评论为主抽查 10 条评论的 base_score检查自定义词典避免得分溢出wordcloud 生成空白方块系统缺少中文字体fc-list :langzh指定 simhei.ttf 等中文字体路径Flask 页面图表不显示JS 文件路径错误、接口返回非 JSON打开浏览器 F12 查看 Network确认 static 目录和接口路径一致重复运行采集后数据量翻倍唯一键未生效或去重字段写错查看 review_md5 是否唯一确认建表唯一索引 uk_review_md57.2 排查链路顺序遇到系统不工作不要东翻西找按以下顺序排查先确认接口数据是否正常。用 curl 或浏览器直接访问/api/overview如果接口返回报错问题在后端逻辑。再确认数据库数据是否为空。执行SELECT COUNT(*) FROM wukong_comments;如果为空问题是采集或清洗环节。检查清洗代码是否误删了大部分数据。在控制台打印清洗前后的数据量确认过滤条件是否过严。检查 Flask 启动日志。留意ModuleNotFoundError、OperationalError、ConnectionRefusedError第一行异常通常就是根因。最后检查前端控制台。如果接口正常但页面空白优先查看 JS 报错和请求路径。一个非常容易踩的坑是在清洗代码中把timestamp_created列直接覆盖成pd.Timestamp对象然后写回数据库时失败。如果只是展示统计结果不需要把清洗后的 DataFrame 写回数据库如果必须写回需要先把时间列格式化为字符串。7.3 答辩讲解主线答辩时老师通常不会只问“做了哪些功能”更关心设计决策和问题意识。建议按以下主线讲解先讲背景。“黑神话悟空”上线后讨论热度很高玩家评论是口碑分析的重要信息来源但评论量大、文本不规范需要一套自动化系统处理。再讲数据链路。从 Steam 评论接口采集到 MySQL通过 pandas 清洗使用 SnowNLP 打分再通过 jieba 提取关键词最终用 Flask 和 ECharts 展示。接着讲关键技术点。重点解释review_md5的去重逻辑、SnowNLP 情感得分如何修正、时间序列怎么聚合。然后讲实验过程。说明采集了多少条评论、清洗后剩多少、好评率是多少、情感分布长什么样并坦白说明样本限制。最后讲不足与改进。可以提到深度学习情感分类、多平台数据接入、自动定时增量采集等方向。这样回答既有深度又显得诚恳。7.4 可扩展的方向这个系统改成毕业设计论文后仍然有明显的扩展空间。第一个方向是数据源扩展。当前只接了 Steam 评论后续可以接入 TapTap、贴吧等渠道不过要确认平台是否允许采集避免合规风险。多源数据需要先统一字段格式再进入同一套分析流程。第二个方向是增量采集。当前脚本是手动一次性运行生产环境应使用定时任务每日采集新增评论并记录最近一次采集游标避免重复拉全量数据。第三个方向是模型升级。SnowNLP 属于基础模型准确率有限。可以收集一批游戏领域标注数据微调文本分类模型也可以接入大模型做摘要和细粒度情感识别但生产成本会明显增加。第四个方向是报表能力。可以把每日统计结果写入 MySQL 聚合表加入日期筛选、对比分析和 PDF 导出让系统从个人分析工具变成运营报表平台。建议毕业设计阶段先把“数据采集、清洗、情感分析、可视化展示”这条主线做扎实不要同时铺开太多功能。功能太多反而会让系统看起来像功能堆砌缺少核心分析深度。整个项目的核心收获不在于“爬了多少条评论”而在于建立了一个完整的数据分析流程思维。采集、清洗、分析、展示中的任何一环出问题都可能让最终看板失真。把每一步的输入输出都确认清楚这个系统就能稳定复现。后续如果要在真实运营场景中投入使用可以再补充监控、缓存、增量调度和生产级部署当前版本的架构已经为这些扩展预留了清晰位置。