
简介一份基于Python的电商评论数据情感分析项目源码面向计算机、自动化等专业的高校学生适用于课程设计、期末大作业或毕业设计。项目覆盖评论数据采集、清洗、情感打分、关键词分析与可视化展示内置Streamlit图形界面可对不同品牌或时段的热水器等产品评论进行对比并处理评分与内容不吻合等问题。压缩包共1380个文件核心包含478个py源码、237个csv评论数据集、178个txt说明文档还有HTML可视化页面、ipynb分析笔记及依赖库文件整体约53.95MB。目前已有1697人学习项目经过严格调试评审分达95分附有需求文档、接口文档、流程图和较规范的注释便于直接运行和二次开发。在此基础上还可引入LDA主题建模、词云、BERT情感分类或深度学习模型做算法优化是课程大作业与毕设的有力参考。1. 电商评论情感分析这个课程大作业为什么值得你顺手拿走做课程设计最怕什么不是不会写代码而是题目太大、数据太脏、交上去老师一问就露馅。这份基于 Python 的电商产品评论数据情感分析资源恰好把这三件事都替你趟了一遍。它不是一个空壳 Demo而是带真实爬取数据、完整 Streamlit 可视化界面、项目说明文档的整套大作业数据文件里连美的热水器 2019、2020 两年的评论都分好了好差评比例、时间跨度、文本长度都是可以直接写进报告里的素材。适合三类人一是计算机/自动化专业要做期末课程设计或课设答辩的学生二是想快速把情感分析流程跑通、看效果再改业务场景的从业者三是想学评论数据挖掘但不想从零爬虫写起的入门者。你拿到的不是一段孤零零的算法代码而是从数据清洗、情感打分到 Web 界面展示的一整条链路。代价只有一个你得花半小时把虚拟环境激活、跑起来然后对着可视化界面一句一句琢磨那些评论背后的真实槽点。2. 拿到压缩包后先别急着跑先把环境与文件结构摸清2.1 解压后的文件清单哪些是数据哪些是环境哪些是代码解压这个 zip 之后你第一眼会看到一堆后缀各异的文件。不少同学上来就找main.py结果发现根本没有这是因为项目的启动入口是 Streamlit 脚本而不是传统的命令行脚本。我用表格把这堆文件按用途拆开方便你心里有数。文件 / 目录类型用途spider_comments.csv数据爬虫抓取的原始评论字段未做清洗spider_comments_34000.csv数据约 3.4 万条评论的样本集适合做整体分布观察spider_meidi_comments2019.csv数据某品牌热水器 2019 年全部评论spider_meidi_comments2020.csv数据同品牌 2020 年评论可与 2019 做对比分析美的Midea_正面.csv数据正面评论筛选结果情感分析后的产物activate/activate.bat/deactivate.bat环境脚本Python 虚拟环境激活脚本Windows 用 batLinux/mac 用无后缀文件pyvenv.cfg/sysconfig.cfg环境配置虚拟环境配置文件用来定位 Python 解释器与依赖路径Comment_analysis/代码目录Streamlit 可视化脚本及辅助模块注意activate和activate.bat是两套不同平台的脚本如果你在 Windows 的 PowerShell 里执行了activate大概率会报错因为 PowerShell 默认禁止执行无签名的 .ps1 脚本。我一般直接用cmd或者Git Bash来激活环境省掉授权这层麻烦。2.2 虚拟环境激活Windows 与 Linux 的差异处理这是整个项目里第一个坑也是新手最容易翻车的地方。常见的做法是直接在项目根目录打开终端执行下面的命令# Windows cmd 下激活虚拟环境 .\\activate.bat # Linux / macOS 下激活虚拟环境 source activate激活成功后终端提示符前面会多一个(venv)前缀。如果执行后提示找不到解释器或者 import 模块时报错先检查pyvenv.cfg里的home路径是不是指向你机器上存在的 Python 安装目录。因为虚拟环境里的路径是创建时写死的换机器以后经常出现路径失效的问题解决方式有两种要么改pyvenv.cfg里的home指向你本机 Python要么干脆删掉虚拟环境目录用python -m venv 新的环境目录重新建一个。激活环境以后先验证核心依赖是否齐全。这个项目主要依赖streamlit、snownlp、pandas、pyecharts这几个包。如果你发现缺包执行以下命令补装pip install streamlit snownlp pandas pyecharts依赖版本我这里不展开说因为 Python 3.8 到 3.11 之间这些库的兼容性基本没问题。但有一点要注意snownlp是老牌的国产情感分析库它依赖的pymongo版本如果超过 4.x某些环境下会出现启动警告不影响主流程忽略即可。2.3 数据文件的编码陷阱读 CSV 之前先做这一步这批 CSV 文件是爬虫程序抓下来的编码十有八九是 UTF-8但里面可能混着 BOM 头。直接pandas.read_csv()读出来第一列列名会带着一个看不见的\ufeff后续所有按列名操作的代码都会炸。我的习惯是无论什么 CSV先按下面的方式读绕开编码坑import pandas as pd # 先探测编码避免 UTF-8 解码失败导致乱码 df pd.read_csv(spider_comments_34000.csv, encodingutf-8-sig) print(df.head()) print(df.columns.tolist())utf-8-sig会自动剥离开头的 BOM 标记列名就干净了。如果你读出来的评论内容仍然是乱码把 encoding 换成gbk或gb18030再试一次因为很多爬虫框架默认输出 GBK 编码的中文评论这也是常见坑之一。这一步确认列名、确认评论字段名是后面一切分析的前提。3. 把评论变成分数情感分析核心链路与参数选择3.1 SnowNLP 的评分逻辑为什么它的情感分数不等于电商评分项目的情感分析基于 SnowNLP它是一部以商品评论语料训练出来的朴素贝叶斯分类器对输入的每条文本输出一个 0 到 1 之间的情感倾向值越接近 1 表示越正面越接近 0 表示越负面。需要注意这个分数和电商平台的星级评分是两套体系——平台评分是用户主观打的 1 到 5 星SnowNLP 分数是模型根据文本措辞推出来的概率值。一个用户给 2 星但评论写“物流慢得离谱”情感分数自然很低但一个用户给 3 星且评论只写“一般吧”SnowNLP 很可能给出 0.5 上下的中性分。所以做分析时要把这两个维度同时纳入不能只看一个。我在处理这个项目时会把score字段电商评分和情感分数分别作为两个独立特征然后交叉比对找出那些“高星但低情感”或“低星但高情感”的异常评论这些通常是刷单或者用户体验强烈反转的代表性案例。3.2 数据预处理去重、空值、短文本过滤真实爬下来的评论没有一行是干净的空值、重复、表情符号、广告词混在其中。如果直接喂给 SnowNLP出现频率高的低质文本会污染整体情感分布。我一般按下面的顺序清洗顺序不能乱import pandas as pd df pd.read_csv(spider_comments_34000.csv, encodingutf-8-sig) # 1. 删除完全重复的评论同用户同内容 df df.drop_duplicates(subset[评论内容], keepfirst) # 2. 删除评论内容为空的行 df df.dropna(subset[评论内容]) # 3. 过滤掉过短的文本小于4个字符的通常是“好评”“一般”这类无效文本 df df[df[评论内容].str.len() 4] # 4. 删除纯标点/纯表情的噪声评论 df df[df[评论内容].str.contains([\\u4e00-\\u9fa5], regexTrue)] print(f清洗后剩余评论数: {len(df)})这里每一步都有讲究。drop_duplicates的subset参数指定按评论内容去重因为同一条评论可能被同一个用户在多个商品 SKU 下重复提交str.len() 4这个阈值是我多次跑数据后定的低于 4 个字符的评论在 SnowNLP 里几乎不产生有效区分度最后一步保留含汉字的行是为了干掉表情包和纯数字评价。清洗干净以后再看情感分布结果才不会偏移。3.3 情感打分函数与批量处理清洗完就可以批量计算情感分数了。这里要注意SnowNLP单条文本的处理速度还行但 3.4 万条评论一条条硬跑也会等上一两分钟属于正常现象。为了后续方便复用我把打分逻辑封装成函数from snownlp import SnowNLP def get_sentiment_score(text): 输入评论文本返回情感分数0~1之间 if not isinstance(text, str) or len(text.strip()) 0: return 0.5 # 空文本按中性处理 try: s SnowNLP(text) return s.sentiments except Exception: return 0.5 # 异常情况默认中性避免中断批量处理 # 批量计算 df[sentiment_score] df[评论内容].apply(get_sentiment_score) print(df[[评论内容, sentiment_score]].head())情感分数回调到 0.5 这个中性默认值是有意为之的因为实际生产场景里个别坏文本导致程序中断的代价远大于把这个样本置为中性。apply是 pandas 的逐行应用函数运行效率虽然不如向量化操作但胜在灵活适合套用这种无法向量化的第三方库调用。如果你嫌慢可以用multiprocessing做多进程分块计算当然课程设计阶段不推荐因为多进程的调试成本比省下的十几秒高得多。3.4 分数分桶把连续分数转成可解释的结论一条评论给一个 0.63 或者 0.84说实话没人看得懂。为了让报告里能写“正面评论占比xx%”我会把连续分数分成三个桶负面0~0.4、中性0.4~0.6、正面0.6~1.0。不过分桶阈值这东西多少有点玄学不同数据集的最佳切分点不一样我更建议先用直方图画出来看分布形态再决定阈值。import numpy as np def sentiment_bucket(score): if score 0.4: return 负面 elif score 0.6: return 中性 else: return 正面 df[sentiment_label] df[sentiment_score].apply(sentiment_bucket) print(df[sentiment_label].value_counts())分桶的价值是把模型输出的连续值变成业务可读的结论也方便后续做饼图和柱状图。这个 0.4/0.6 的切分不是固定标准如果你发现负面样本占比异常低可以把下界上调到 0.45 重新试。这也是这个项目适合做课程设计的原因——你可以在报告里大大方方写一句“本文采用 0.4 与 0.6 作为情感分界阈值该阈值根据样本分布调整”这比硬套别人论文里的 0.5 切分点要立得住。4. 用 Streamlit 把分析结果搬上网页运行命令与界面拆解4.1 启动入口的命令细节这个项目最有辨识度的就是最后的结果展示不是控制台打印而是完整的 Web 可视化页面。启动方式在项目说明里写得很明确streamlit run ./Comment_analysis/Streamlit/streamlitEXP.py注意路径是相对路径你必须在项目根目录下执行这条命令否则 Streamlit 会报找不到文件。启动成功后终端会显示Local URL: http://localhost:8501浏览器会自动打开这个地址。如果没自动打开手动复制地址访问即可。如果你是在服务器上跑想远程访问要加--server.address 0.0.0.0参数课程设计一般不需要。4.2 页面模块拆解从评论总览到单条明细streamlitEXP.py这个脚本我是拆开看的它包含以下几个功能区数据总览区展示评论总数、好评/差评占比、平均评分用st.metric组件显示核心指标情感分布区用柱状图或饼图展示正面/中性/负面评论的占比图表用的 pyecharts 生成 HTML 再嵌入页面时间趋势区按月份聚合评论数量和平均情感分数呈现同一商品在不同时间段的口碑变化关键词透视区输入一个关键词比如“漏水”筛选出所有含该词的评论并展示这批评论的情感分布单条评论明细表可搜索、可分页的评论数据表每一行都有原始评分和情感分数。如果你打开界面发现图表不显示常见原因是 pyecharts 生成的 HTML 文件未能正确嵌入到 Streamlit 的组件中此时streamlit.components.v1.html的height参数设置过小会导致图表只露出一条线。我一般会把高度调到 500 以上。4.3 页面布局与交互参数的手动调整这份代码里有些可调参数是写死在脚本里的但你可以打开脚本直接改。比较值得动的有三个# streamlitEXP.py 中常见的可调参数示例 SENTIMENT_THRESHOLD_NEG 0.4 # 负面评论阈值 SENTIMENT_THRESHOLD_POS 0.6 # 正面评论阈值 TOP_N_KEYWORDS 20 # 关键词 TOP N 展示数量调整TOP_N_KEYWORDS时要注意这个参数影响的是关键词统计表的行数数值过大时表格会变得冗长反而不利于汇报演示。阈值参数则和前面第 3 章的sentiment_bucket函数是关联的两处要同步修改否则会出现页面上的占比分布和代码逻辑不一致的情况。这个同步问题在课程答辩时经常被老师追问提前改好一处并在注释里说明即可。5. 避坑指南课程大作业里最折磨人的 5 个细节5.1 CSV 读进来列名是乱码或带前缀现象df.columns打印的结果里第一列显示为\ufeff评论内容后面所有按名字索引的操作报 KeyError。原因文件保存时带了 UTF-8 BOM 头pandas 默认编码utf-8不会自动去掉 BOM。解决读取时用encodingutf-8-sig或者在读进来后执行df.columns [col.lstrip(\ufeff) for col in df.columns]。5.2 虚拟环境激活后 pip 安装的包仍然找不到现象source activate后终端显示进入了环境但执行python -c import snownlp仍然报 ModuleNotFoundError。原因可能是终端还在旧 shell 的 PATH 缓存中或者 pyvenv.cfg 里面的home指向了不存在的 Python 路径。解决先deactivate再重新激活不行就打开pyvenv.cfg检查home路径是否真实存在如果不对直接新建虚拟环境重新安装依赖。5.3 Streamlit 页面图表空白但没有报错现象页面上的表格和数据能显示柱状图区域空白浏览器控制台也没有明显报错。原因pyecharts 默认渲染为独立 HTMLStreamlit 内嵌时如果高度参数太低图表会被压缩成一条线甚至不可见。解决找到调用components.html的位置把height调整为 500~800如果是用st.plotly_chart或其他方式检查渲染引擎是否安装完整。5.4 评分与文本情感严重不吻合导致报告结论矛盾现象某条评论给了 5 星但 SnowNLP 算出的情感分数只有 0.2单独抽出来看文本其实是“好评但客服态度太差”。原因用户评分针对的是整体购物体验情感分析针对的是文本措辞两者语义维度不同出现矛盾是正常的不代表代码跑错了。解决在报告中把这种矛盾作为“特征工程亮点”来写单独设一个交叉表展示异常样本并说明这部分数据可以用于识别真实口碑与评分的偏差。5.5 评论里夹杂大量系统自动回复现象分词统计时“此链接不存在”“该商品已下架”这类非用户生成内容占据 TOP 关键词。原因爬虫抓取时把页面里系统提示也抓了进来这类文本不属于真实用户评论。解决在预处理阶段加过滤规则匹配包含“下架”“不存在”“链接”等字样的文本并剔除。我一般维护一个黑名单词表逐条扩充效果比正则一次写到位更可靠。6. 进阶玩法把这份大作业的档次再往上拉一截如果你时间充裕想让答辩老师眼前一亮可以在这个项目基础上做三件事多模型对比、分品牌口碑拆解、主题模型深挖。先说多模型对比。原始项目默认用 SnowNLP但 SnowNLP 训练的语料偏电商通用对特定品类如热水器的领域词不一定敏感。你可以把结果与基于情感词典的方法做对比——使用jieba分词后配合大连理工大学情感词汇本体库做词汇匹配打分最后计算两种方法的分类一致性用混淆矩阵展示。这部分代码量不大但写进报告里就是“多种方法对比分析”的加分项。import jieba import pandas as pd # 简易情感词典打分示例正向词加分、负向词减分最后归一化 pos_words {好: 1.0, 快: 0.8, 满意: 1.0, 漂亮: 0.9} neg_words {差: 1.0, 慢: 0.8, 漏水: 1.0, 垃圾: 1.0} def lexicon_score(text): words jieba.lcut(text) raw sum(pos_words.get(w, 0) for w in words) - sum(neg_words.get(w, 0) for w in words) return max(0.0, min(1.0, 0.5 raw / 10)) df[lexicon_score] df[评论内容].apply(lexicon_score)这段代码属于能跑的简易版关键词表和权重需要根据你的数据扩充但足以展示“第二种方法的实现思路”。我再强调一次jieba分词结果受词典影响极大如果你发现“漏水”被切成“漏”和“水”你的负向情感词就匹配不上了。解决办法是把领域词加入jieba.add_word(漏水, freq100)。然后是分品牌口碑拆解这个项目里正好有 2019、2020 两年的评论数据你可以按年份分组计算平均情感分数用折线图展示口碑变化趋势。如果两年数据有同一个品牌的不同型号还可以进一步按型号聚合。写进报告里的结论会很扎实比如“2020 年该品牌热水器正面评论占比从 62% 提升到 74%与产品升级周期吻合”。最后是主题模型深挖。SnowNLP 只输出情感分数不告诉你大家在夸什么、骂什么。配合LDA主题模型能从负面评论里抽出几个隐藏主题——比如“安装费贵”“加热慢”“售后服务差”。这个在项目说明里也提到了pyLDAvis可视化你可以用网页交互式查看主题词分布。课程设计做到这一层就已经超出了“调用一下情感分析库”的范畴老师基本没有理由不给高分。从那次课设以后我每次拿到一份新的评论数据集都会先把评分和情感分数的交叉表跑一遍再决定要不要上主题模型——这不是流程仪式感而是数据库里真的有太多“5 星好评但文本抱怨”的灰色样本。希望这份拆解能帮你在同样的路上少踩几个坑把这份资源真正变成自己的东西而不是解压完就丢进回收站。本文还有配套的精品资源点击获取