Django与小程序驱动的用户评论热点挖掘与反馈分析系统 做这类 Django 大屏 小程序的毕设很多同学一开始都以为卡在技术上真正动手了才发现卡在“数据”和“选题包装”上。《django基于用户评论的热点问题挖掘与反馈分析系统》从名字就能看出来它要干的不是简单做个评论列表而是要把一堆原始评论拆成“近期大家都在骂/都在夸什么”的可视化结论。这篇文章就把整个项目从头到尾拆开讲一遍包括模块划分、算法落地、小程序联调、毕设文档和答辩需要准备的细节。适合正在选毕业设计题目、或者已经在做类似系统的同学参考哪怕是刚学 Django 的新手照着文章的思路也能把项目框架搭明白。我有段时间密集帮人看过这类系统源码我也看过不少。说句实在话市面上的成品源码很多只做了一半后端能跑小程序能登录但热点怎么挖出来的、反馈怎么分析的讲不清楚答辩一问就慌。所以这篇文章的重点不是贴一个能运行的源码出来而是讲清楚这套系统的完整链路和每个环节里的实际取舍。1. 这类系统到底在解决什么问题毕设题目看起来很宏大但拆开其实就一句话把用户评论里反复出现的关键信息和情绪倾向自动找出来并且用小程序展示给运营人员看。1.1 用户评论的数据价值与选题动机现在稍微像样一点的产品评论区每天都能产生几百上千条文本。电商平台有商品反馈食堂有菜品吐槽校园里也有对校园服务的意见征集。这些人写的每一句话都带着真实诉求比如“取餐太慢了”“系统又崩了”“价格比上周贵了五块”。但是人工去看这些评论效率太低。一个人一天看几百条已经是极限看完了还不一定能归纳出“最近大家集中反馈的是哪三类问题”。毕设做热点挖掘和反馈分析本质上就是把“人工总结评论”这件事自动化系统定期抓取评论做清洗和分词算权重找突发词再结合情感分析给出结论。从毕设选题的角度来说这个题目有几个天然优势数据来源灵活。可以做爬虫抓公开评论也可以用公开数据集甚至可以自己写一套模拟评论生成器。技术栈覆盖广。Django后端、小程序前端、数据挖掘算法、可视化展示全都能揉进去。可展示性强。答辩现场打开小程序点开一个热词能看到相关评论、情感倾向、趋势变化视觉效果好。边界好控制。算法不需要做到科研级能讲清楚TF-IDF和TextRank区别已经能拿不错的分数。1.2 需求拆解从评论采集到反馈闭环我当时帮同学A做系统规划时直接按“数据链路”把系统切成了五段模块核心功能输出物数据采集抓取评论数据 / 导入已有数据原始评论表数据清洗去重、去噪、分词、去停用词干净语料库热点挖掘关键词提取 时间窗口突发检测热点词表反馈分析情感倾向判断 主题聚类情感分布/主题报告小程序展示热榜、评论流、图表报告用户可操作的界面这个拆法的好处是每一段都可以单独测试。数据采集挂了不影响算法算法抽风不影响展示。很多同学上来就写爬虫爬了两天发现网页结构变了很崩溃。其实可以先用手工整理的评论数据把算法跑通爬虫放后面再补。另外要提醒的是凡是涉及抓取真实平台评论一定要控制频率、遵守网站协议只做公开数据的研究性分析。毕设阶段完全可以采用脱敏后的公开数据集或者构造一批模拟数据重点是把处理链路跑通。2. 技术选型为什么是 Django 而不是 Flask 或 SpringBoot选 Django 不是因为它是“毕设指定框架”而是因为这类系统本身就需要能快速建表、能自动生成管理后台、能优雅写接口。2.1 Django 在毕设项目里的真实优势第一是 ORM。一次定义模型数据库表结构就出来了。评论表、热点词表、情感分析结果表这三个核心表之间还有外键关系比如一条热点词对应多条评论。如果人工写SQL会浪费大量时间Django ORM 只需要定义模型类查询用filter、annotate就能组合出结果特别适合时间紧的毕设。第二是 Django Admin。系统里需要维护用户、管理停用词、手动标记“某条评论属于某热点”这些操作如果都专门做页面工程量不小。用 Admin 后台几行代码就能注册完演示的时候还能展示后台的增删改查能力。第三是生态成熟。配合django-rest-framework写小程序接口身份认证、分页、序列化基本是现成的。再配合simplejwt小程序登录后拿 token后续请求都带 token安全和规范都说得过去。有人会问用 Flask 更轻为什么不用我的看法是Flask 自由度高但自由度也意味着很多组件要自己拼。比如 Flask 里没有内置 ORM默认连数据库配置都要自己整理。毕设周期通常就三四个月Django 的“约定优于配置”能帮你省掉大量重复劳动。2.2 整体架构与数据流向整个系统的前后端是分离的后端Django 提供 REST API处理采集、分析、查询。算法层以 Python 脚本或 Django 管理命令的形式存在读库算完再写回分析结果表。前端小程序充当“展示与轻交互端”不会直接处理算法逻辑。数据库MySQL 存业务数据Redis 可选用来做热词缓存减轻查询压力。数据流是这样的评论先落库由定时任务或者手动任务触发分析分析脚本把热点词、情感结果写回数据库小程序请求对应接口拿到结果后渲染图表。小程序端我建议用原生框架就够了。这个系统最复杂的页面也就是词云、饼图、柱状图和列表原生wx-charts或者echarts小程序版都能搞定。不需要为了一个毕设上 uni-app除非你想顺便展示跨端能力。MySQL 和 SQLite 的选择上个人建议直接用 MySQL。不是说 SQLite 不行而是 MySQL 更贴近真实生产环境且部署在服务器上比较顺手。如果你担心本机没有 MySQL可以通过 Docker 装一个一条命令的事。3. 评论数据的获取与清洗算法之前最脏的一步很多同学把重心放在算法实际上最后拖垮项目的往往是数据。我见过最典型的例子爬下来的评论里有大量“感谢分享”“666666666”这种无效文本不处理就去算词频结果“666”成了热点词答辩现场非常尴尬。3.1 数据来源的三种方式第一种是爬虫采集。优先选择有公开接口或结构稳定的页面在遵守目标站点协议的前提下控制请求频率解析评论字段。要注意大规模爬取存在合规风险毕设项目建议小规模、节流采集并且不做公开传播。第二种是公开数据集。很多教学平台会提供脱敏后的评论数据比如外卖评论、酒店评论、电商评论。字段包括用户ID、评分、评论文本、评论时间。这个方式最省事也最能说明问题。第三种是自己生成模拟数据。如果你希望演示效果完全可控可以先写好一批“带热点”的评论比如在一小段时间窗口内反复出现“配送太慢”然后在算法结果里验证它确实被挖出来了。这样演示时更有说服力造一个已知热点看系统能不能挖出来。我个人最推荐“公开数据 少量自造数据”的组合。公开数据证明系统能处理真实文本自造数据证明系统对突发话题有敏感度。3.2 清洗流程的完整链路评论清洗没有多难但步骤不能省。标准流程是这样的去重同一个人重复提交的、同一句话刷屏的按评论哈希去重。去噪去掉明显与主题无关的文本比如“哈哈哈”“路过”这类低信息评论。去掉特殊字符URL、用户名、手机号、表情符号、HTML标签全部删掉或者转义。统一格式繁体转简体、全角转半角、英文统一小写。分段结构一句话如果太长按标点切成短句方便后续提取关键词。伪代码大概是这样的import re def clean_comment(text: str) - str: # 去除HTML标签 text re.sub(r[^], , text) # 去除URL text re.sub(rhttps?://\S, , text) # 去除用户 text re.sub(r\S, , text) # 去除表情符号简单按非字符处理可结合正则 text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9。、 ], , text) # 繁体转简体可用 opencc 库 return text.strip()表情符号这条很多人会忽略。微信生态下的评论里表情非常多如果不清理分词时会出现一堆难以理解的碎片词。建议在清洗阶段就处理掉。3.3 中文分词与停用词处理清洗完的文本进入分词环节。中文分词最常用的工具是jieba支持三种模式我这里一般用精确模式import jieba text 这个餐厅的桌椅摆放有点乱高峰期特别拥挤 words jieba.lcut(text) print(words) # [这个, 餐厅, 的, 桌椅, 摆放, 有点, 乱, , 高峰期, 特别, 拥挤]分词之后要按停用词表过滤。“的”“了”“是”这些词出现频率极高但对热点分析没有帮助。停用词表网上有现成的也可以自己在 Admin 后台维护一份随时往里加。这个能力在答辩时很容易加分说明你考虑到了可维护性。还有一类词不能丢比如“高峰期”“性价比”“客服态度”。这类词是评论里的关键实体但它们可能被 jieba 切成碎片。解决办法是加载自定义词典把领域词强制识别为整体。比如做外卖领域分析就把“配送超时”“包装破损”加入自定义词典。jieba.load_userdict(extra_dict.txt) # extra_dict.txt 每行: 词语 词频 词性 # 配送超时 5 n # 性价比 5 n清洗和分词做完原始评论表之外应该有一张“分词结果表”或者至少加三个字段words_json、clean_content、is_valid。后期做关键词提取、聚合评论都会方便很多。4. 热点问题挖掘从词频到“突发话题”的算法落地热点挖掘是答辩评委最容易盯上的部分因为它是整个系统的“智能点”。能讲清楚算法原理比跑通代码更值钱。4.1 为什么不能只用词频统计如果直接对所有评论做词频统计得到的结果通常是“的”“了”“好”“不”“很”这类常见词。即使过滤了停用词“不错”“东西”“感觉”这类泛化词也会霸榜因为它们几乎出现在每条评论里。所以需要两个层面的改进用 TF-IDF 或者 TextRank 这种“关键词提取”算法解决“常见词权重过高”的问题。用时间窗口对比解决“到底是长期问题还是最近突发”的问题。一句话理解热点 关键词 × 突发性。今天出现很高频的词如果过去也一直很高频那不叫热点叫常态问题今天暴涨的词才叫热点。4.2 TF-IDF 的实现与局限TF-IDF 的核心思想是一个词在当前评论里出现得多但在所有评论里出现得少那这个词就有区分度更像这篇文章或这条评论的特征词。公式不用死记但要能复述TF词频 词在文档中出现的次数 / 文档总词数IDF逆文档频率 log(总文档数 / 包含该词的文档数 1)TF-IDF TF × IDF在 Django 里实现时可以直接用 sklearn 的TfidfVectorizerfrom sklearn.feature_extraction.text import TfidfVectorizer corpus [ 配送超时 包装破损, 口味不错 就是太咸, 配送太慢 汤洒了 ] vectorizer TfidfVectorizer(token_patternr\S) tfidf vectorizer.fit_transform(corpus) names vectorizer.get_feature_names_out() # 拿到每个词在所有评论里的 tf-idf 权重矩阵 for i in range(len(corpus)): row tfidf.getrow(i).toarray()[0] word_weight dict(zip(names, row)) top_words sorted(word_weight.items(), keylambda x: x[1], reverseTrue)[:5] print(top_words)TF-IDF 适合做“单条评论特征词”的提取但如果想对整个时间窗口内的“热点词”排序还需要把权重再加总。至于没有做任何训练这一点答辩时可以强调无监督方法适用于没有标注数据的情况。不过 TF-IDF 有个缺点它没有考虑词与词之间的顺序关系。“非常好吃”被拆成“非常”和“好吃”如果只取权重可能同时得到两个中低权重词而不是一个高权重的短语。这时候可以引入 TextRank。4.3 用 TextRank 挖掘短语级热点TextRank 的思想和网页排序类似把句子里的词当作节点如果两个词在同一个窗口内共现就认为它们之间存在“连接”。经过多轮迭代被越多重要词连接的词就越重要。jieba.analyse.textrank可以直接用import jieba.analyse text 高峰期等位时间太长服务员态度也不行整体体验很差 keywords jieba.analyse.textrank(text, topK5) # 输出类似 [等位, 高峰期, 服务员, 态度, 体验]TextRank 更擅长抽取长文本的关键词但如果一条评论只有几十个字效果可能没那么明显。所以实际项目里通常把一天内的所有评论文本拼接成一个大文本再跑 TextRank这样能提取出一天内的关键词集合。我记得当时做测试时发现TextRank 对“排队时间长”“上菜速度慢”这种明显带有情绪的短语识别度比 TF-IDF 好因为它保留了词语共现关系。4.4 时间窗口突变检测真正让“热点”浮现的机制关键词算法做了“降噪”但还没解决“突发”。热点问题的定义是某个时间段的词频显著高于历史均值。具体做法是分层把时间切成“当天”和“过去一段时间的基线窗口”两个维度。对每个关键词算一个突发分score (当天的词频 1) / log(历史平均词频 1)如果 score 超过阈值就认为该词在当天形成了热点。实际工程里也可以用标准差的方式类似 Z-Scorescore (当前窗口词频 - 历史均值) / 历史标准差为了不让分母变成 0个人建议用平滑参数。下面是个简化代码思路import math def burst_score(today_count, history_avg): if history_avg 0: return 0.0 return (today_count 1) / math.log(history_avg 2) # 示例 today_counts {配送超时: 80, 口味: 100} history_avg {配送超时: 5, 口味: 90} for word, t_cnt in today_counts.items(): print(word, burst_score(t_cnt, history_avg[word]))计算出来“配送超时”的突发分就远高于“口味”哪怕“口味”出现次数更多系统也能准确判断“配送超时”才是当前热点。这个对比非常适合在答辩现场演示一张表就讲清楚“热点不等于高频”。再往下做还可以对新词挖掘增加一个“凝固度”指标。简单说如果“包装”和“破损”总是黏在一起出现那它们的凝固度就高可以组成新词“包装破损”。这个属于加分项时间不够可以略过。在这个阶段建议保留三张表trend_keyword关键词、日期、频次、突发分、hotspot热点问题、起止时间、相关评论数、hotspot_comment_rel热点和评论的多对多关系。后续小程序展示需要这些关联。5. 反馈分析情感倾向和主题聚类怎么落库热点挖掘解决了“大家在讨论什么”的问题反馈分析要解决“大家是正向反馈还是负向吐槽”的问题。5.1 基于情感词典的情感判别性价比最高毕设阶段不一定要上深度学习模型。用情感词典的方式速度快、可解释性强答辩时逻辑也清晰。先准备一份中文情感词典包含正面词、负面词、程度副词和否定词。然后对每条评论做这样的打分分词后逐个词匹配情感词典。正面词加 1 分负面词减 1 分。如果情感词前存在否定词比如“不满意”情感分数要翻转。如果存在程度副词比如“非常”“特别”分数乘以相应权重。设计一个简单的判断函数def sentiment_score(words): score 0 negate False adverb_weight 1.0 for w in words: if w in negative_words: score -1 * adverb_weight * (-1 if negate else 1) negate False adverb_weight 1.0 elif w in positive_words: score 1 * adverb_weight * (-1 if negate else 1) negate False adverb_weight 1.0 elif w in neg_words: negate not negate elif w in adverb_words: adverb_weight 2.0 else: negate False adverb_weight 1.0 return score最后根据总分映射为“好评/中评/差评”然后按天统计正负面比例。这个方法有缺点无法理解“这餐厅太难吃了服务员态度倒是挺好”这种转折句。但毕设不需要完美你可以在文档里承认该方法的局限并提出可以用 BERT 微调做优化——留一个“未来展望”的切口反而显得你思考深入。5.2 主题聚类把同类型反馈归到一起热点词只是关键词为了生成“反馈分析报告”还要把评论归类到几个核心主题下比如“配送服务”“菜品质量”“价格问题”“环境卫生”。最简单的做法是对清洗后的文本做向量化再用 KMeans 聚类。向量化可以用 TF-IDF 或者 Word2Vec。KMeans 的簇数 K 可以预先设定为 4 到 6 类然后对每个簇提取高频词人工给簇打一个主题标签。from sklearn.cluster import KMeans from sklearn.feature_extraction.text import TfidfVectorizer vectorizer TfidfVectorizer(token_patternr\S, max_features2000) X vectorizer.fit_transform(cleaned_comments) model KMeans(n_clusters5, random_state42) labels model.fit_predict(X)聚类结果的解释性是这类系统的关键。KMeans 完成后还得按簇输出 top 词帮你决定这个簇到底叫“价格敏感”还是“服务态度”。这一步建议做成半自动算法给候选人工确认标签然后在系统里落库。5.3 可视化指标小程序里呈现什么数据才显得专业反馈分析的输出不建议直接丢一堆数字而是做成四个维度指标展示形式说明情感占比饼图当天正面/负面/中性评论占比情感趋势折线图近7天负面情绪评论数量走向主题分布横向柱状图各主题问题对应的评论条数热词排行词云 / 榜单高突发分的词列表我的经验是小程序首页先放“今日热点词”进入详情页再放“情感分布和趋势”最后放“相关评论列表”。这个结构符合人的认知习惯先看结论再看数据再看证据。后台接口返回 JSON 时不要前端拿到列表再自己统计。Django 里可以一次返回统计好的 summarizer 数据{ date: 2025-06-01, sentiment_ratio: {positive: 0.55, negative: 0.3, neutral: 0.15}, trend: [ {date: 2025-05-26, negative: 12}, {date: 2025-05-27, negative: 18} ], hot_keywords: [ {word: 配送超时, burst_score: 8.2, count: 80} ] }这种结构化的接口在答辩演示时最省心小程序不用做二次计算响应也快。6. 小程序端把算法结果变成可交互的产品小程序表面是展示层但它决定了评委的第一印象。在这个项目里小程序要承担热榜查看、反馈报告浏览和评论详情查看三个核心任务。6.1 页面结构与功能对照我建议做四个 tab热点tab顶部是今日热词排行下面是可以横向滑动的突发分趋势图。反馈tab情感占比饼图 主题分布柱状图 近 7 天负面趋势。评论tab按热点词筛选的评论流显示用户头像、昵称脱敏、评论文本、情感标签。我的tab登录注册、历史查看记录、关于系统。热点详情页从热词点击进入后展示该词的频次变化曲线、相关评论列表、情感占比。这一页是整个小程序的“高潮页面”一定要把评论和热点之间的关联做清楚。6.2 Django 接口设计与权限控制接口设计推荐使用 Django REST Framework路由如下接口方法说明/api/auth/token/POST用户登录获取 JWT/api/hotspots/today/GET今日热点词列表/api/hotspots/{id}/detail/GET热点详情与相关评论/api/analysis/summary/GET情感占比与主题分布/api/comments/?keywordxxGET按关键词过滤的评论分页权限方面公开的统计接口可以用AllowAny或者只做简单限流涉及用户浏览记录和收藏的接口必须用 JWT 保护。用 simplejwt 之后Django 里加一个权限类就能搞定from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView class UserHistoryView(APIView): permission_classes [IsAuthenticated]小程序端在请求头里加上Authorization: Bearer token即可。6.3 小程序本地联调一定绕不开的问题第一开发时小程序要求 request 的域名必须备案且配置合法域名。本地调试时最省事的办法是在小程序开发者工具的本地设置里勾选“不校验合法域名”但正式上线前必须配置真实域名。毕设一般不要求上线演示时勾选不校验即可自己心里要清楚这一点。第二本地后端要能被手机访问。建议后端启动时用0.0.0.0:8000然后通过局域网 IP 在小程序里配置baseUrl。注意 Windows 防火墙要放行 8000 端口Android 模拟器里访问本机要用 10.0.2.2 而不是 127.0.0.1。第三接口跨域问题。小程序请求本身没有传统浏览器跨域限制但如果你用开发者工具预览的页面模式调试 H5 版本时则需要在 Django 里配置跨域白名单。7. 毕设完整度文档、演示脚本和答辩话术这部分的权重绝对不亚于代码本身。很多同学代码能跑但答辩不过就是因为不会“叙事”。7.1 交付的四件套做这套系统最终交付通常包括四块内容可运行的源码包Django 后端 小程序前端 数据库初始化 SQL毕业论文文档代码讲解视频或现场讲解稿演示数据我强烈建议在做项目第一天就建立目录结构源码和文档分开放不要最后打包成一个乱糟糟的 zip。7.2 论文目录按“提出问题—构建系统—验证效果”组织论文可以按下面的章节来写绪论背景、国内外研究现状、研究内容相关技术介绍Django、小程序、TF-IDF、TextRank、情感分析需求分析功能性需求、非功能性需求、用例图系统设计总体架构、数据库设计、接口设计、算法流程系统实现核心模块代码与截图系统测试功能测试用例、性能测试、结果分析总结与展望写文档时有个技巧算法章节要多画流程图和数据流图不要只贴代码。评委老师通常先翻图和表格再决定要不要细看内容。7.3 答辩演示脚本一条能讲 10 分钟的故事线演示前先设计一个具体场景。比如“现在是某外卖平台的一天运营结束系统自动抓取了 1000 条今日评论。经过数据清洗剩余有效评论 850 条。系统通过 TF-IDF 和 TextRank 提取关键词结合时间窗口的突发检测发现‘包装破损’今天的突发分达到 8.5远高于历史均值。点进这个热点可以看到 85 条相关评论其中 70% 为负面主要集中在下雨天。因此运营人员应该优先处理包装供应商的问题。”这套话术把技术指标、数据和业务决策串在一起比干巴巴报“我用了 TF-IDF”强得多。答辩常见问题我也列几个为什么要用 Django答快速开发、内置 ORM 和 Admin、适合中小型数据系统。热点是怎么定义的答关键词权重 时间窗口突发分数。情感词典和深度学习哪个更好答情感词典可解释性强、训练成本低但深度学习更准未来可以优化。如果评论量很大系统怎么扩展答可以引入消息队列和分布式爬虫Django 负责 API算法用 Celery 异步任务。8. 排错复盘这个项目最容易踩的五个坑最后一部分说几个这个系统特有的、几乎每做一个都会踩一遍的坑。8.1 中文乱码问题最容易踩的坑发生在 MySQL 建库时没有指定字符集。评论数据一写入就出现一堆问号。建库时一定要写成CREATE DATABASE comment_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;如果是从外部数据文件导入读取 CSV 时也注意编码通常要指定encodingutf-8。有些数据源是 GBK那就得按gbk读再转成 unicode。8.2 时区问题导致热点统计错位Django 默认USE_TZTrue数据库里存的是 UTC 时间。如果你直接用date.today()去按天分组到了晚上更新的时候统计出来的“今天”可能少几个小时。正确的做法是from django.utils import timezone from datetime import timedelta now timezone.localtime() today_start now.replace(hour0, minute0, second0, microsecond0)我调试的时候连续两次发现热点词在 00:00 附近的统计结果与直觉不符最后定位就是时区问题。改完之后一切正常这个小坑在文档里写出来也是加分项。8.3 全量分割导致分词特别慢如果每天抓几千条评论跑一次全量分词还勉强能忍。但如果规模上万直接在视图函数里做算法计算会让小程序接口卡死。解决方案是把分词、热点计算放到 Django 管理命令或者 Celery 异步任务里生成结果后再提供查询接口。python manage.py run_analysis --date2025-06-01清早跑一次分析白天只查表性能和逻辑都会干净很多。8.4 小程序请求后端失败本地调试阶段90% 的 request 失败不是因为代码问题而是“未配置合法域名”和“手机访问不到电脑”。前者在开发者工具里可以临时关闭校验后者要确保手机和电脑在同一局域网并关闭防火墙限制。如果不想用局域网也可以部署到一台云服务器做好 HTTPS 后配置合法域名唯一注意别把密钥暴露在代码里。8.5 把评分字段和分析结果混在一起很多平台自带评分1到5分有人会直接拿评分当情感分析结果这是两码事。评分是用户的整体满意度评论里可能先夸“好吃”再骂“等位太久”这句评论的情绪其实是混合的。不要嫌麻烦单独做一条“情绪极性”分析和评分分开论证才严谨。最后一个实用建议项目里的小程序端和后台 Admin 都记得先准备一份演示账号和数据。不要到答辩现场才临时去爬评论、跑任务。把今日热点词提前算好录入照片和截图演示时照着脚本走整个节奏会非常顺畅。真正让评委信服的不是你在台上敲了多少代码而是你对这套系统从数据采集到热词展示的每一步都说得有理有据。这篇项目的核心价值恰恰就在这个完整链路里。