ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

淘宝评论情感分析毕设:Selenium爬虫+jieba分词+Word2vec+SVM/LSTM实战

淘宝评论情感分析毕设:Selenium爬虫+jieba分词+Word2vec+SVM/LSTM实战 简介这份资源是面向计算机相关专业学生与从业者的毕业设计项目包聚焦电商淘宝商品评论的情感分析采用Python结合机器学习与深度学习实现完整流程。项目从淘宝评论爬取入手借助Selenium模拟真实登录行为获取数据随后进行文本清理剔除“666”“好好好”等无意义词汇并去除标点再用jieba精确模式分词并构建词典完成词汇向量化与词索引映射最后对比SVM与LSTM两类分类模型的效果。压缩包共43个文件约66.68MB包含14个py源码、7个csv数据集、4个npy与3个pkl模型文件、2个h5权重、2个xls样本以及chromedriver等覆盖爬虫、预处理、训练与绘图模块。该毕设评审分达97分代码经严格调试可运行已有382人学习。读者可据此掌握从数据采集到模型对比的完整链路并直接用于课程设计、大作业或毕业设计参考。1. 淘宝评论情感分析毕设从爬虫到 SVM/LSTM 对比的完整落地路径电商评论里藏着最真实的用户情绪但要把「好评差评」变成可量化的模型输出中间隔着爬虫、清洗、分词、向量化、模型训练五道坎。这份毕业设计资源把整条链路都跑通了Selenium 模拟登录抓淘宝评论jieba 精确模式分词Word2vec 训练词向量最后用 SVM 和 LSTM 做二分类对比评审分 97。它适合计算机相关专业的毕设选手、课程大作业赶工的人以及想搞明白「文本分类到底怎么从零搭起来」的入门者。资源包里带了爬好的评论数据、训练好的模型文件svm_model、model.pkl、lstm_three.h5和 GUI 界面拿到手就能跑不用从零造轮子。2. 环境搭建与数据获取Selenium 爬虫怎么绕开反爬拿到真实评论2.1 依赖安装与目录结构梳理拿到压缩包先别急着跑代码把目录结构看清楚能省很多事。核心目录分四块review_crawler放爬虫脚本review_treatment放数据清洗和分词model放训练好的模型文件GUI放可视化界面。数据文件散在根目录pos.xls、neg.csv、neutral.csv是标注好的正负中三分类原始数据test_set.csv是测试集review.csv是爬虫抓下来的原始评论。安装依赖时最容易翻车的是版本冲突。这个项目用的是 TensorFlow 1.x 时代的 APIlstm_three.h5这种命名风格能看出来如果你本地装的是 TF 2.xtrain_lstm.py大概率跑不起来。常见做法是建一个 Python 3.6/3.7 的虚拟环境按下面这个清单装# 创建虚拟环境Python 版本建议 3.6 或 3.7 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 核心依赖版本尽量对齐 pip install tensorflow1.15.0 pip install gensim3.8.3 pip install jieba0.42.1 pip install scikit-learn0.24.2 pip install selenium3.141.0 pip install xlrd1.2.0 # 读 .xls 文件必须用 1.x2.x 只支持 xlsx pip install pandas numpy matplotlib这里有几个参数值得说清楚。tensorflow1.15.0是 TF 1.x 最后一个稳定版兼容lstm_three.h5的加载方式gensim3.8.3对应 Word2vec 的旧版 API新版gensim 4.x把model.wv的接口改了直接跑会报AttributeErrorxlrd1.2.0是因为pos.xls是老版 Excel 格式xlrd 2.0 之后砍掉了 xls 支持。这几个版本号不是随便写的是血泪经验堆出来的。2.2 Selenium 模拟登录与评论抓取爬虫部分在review_crawler/crawler.py和restaurant_crawler.py里。淘宝的评论接口需要登录态才能拿到完整数据所以项目用 Selenium 驱动 Chrome 模拟真实用户操作。chromedriver文件已经在根目录放好了但你要确认它的版本和本机 Chrome 匹配否则会报SessionNotCreatedException。from selenium import webdriver from selenium.webdriver.common.by import By import time import csv # 启动 Chrome加载已登录的用户配置目录 options webdriver.ChromeOptions() # 指向你本机 Chrome 的用户数据目录这样能复用已登录的淘宝账号 options.add_argument(r--user-data-dirC:\Users\你的用户名\AppData\Local\Google\Chrome\User Data) driver webdriver.Chrome(executable_path./chromedriver, optionsoptions) # 打开目标商品评论页 driver.get(https://item.taobao.com/item.htm?id商品ID) time.sleep(5) # 等页面加载淘宝的异步请求比较多 # 滚动加载评论淘宝评论是懒加载的 for i in range(10): driver.execute_script(window.scrollTo(0, document.body.scrollHeight)) time.sleep(2) # 提取评论文本 comments driver.find_elements(By.CSS_SELECTOR, .tm-rate-content .tm-rate-fulltxt) with open(review.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([comment]) for c in comments: writer.writerow([c.text]) driver.quit()逻辑说明--user-data-dir是关键参数它让 Selenium 复用你手动登录过的 Chrome 配置省去在脚本里处理登录验证码的麻烦。window.scrollTo循环滚动是因为淘宝评论页只渲染可视区域的内容不滚动到底部拿不到全部评论。time.sleep的秒数根据网络情况调整太短会抓到空数据太长效率低。选择器.tm-rate-content .tm-rate-fulltxt是淘宝评论区的 class 名如果页面改版了需要重新抓元素定位。提示爬虫频率别太高单次抓取控制在几十条以内加time.sleep间隔。高频请求会触发滑块验证到时候脚本直接卡死。3. 数据清洗与分词jieba 精确模式怎么把「666」和「好好好」处理干净3.1 评论预处理脚本拆解review_treatment/review_pretreatment.py是清洗主逻辑。原始评论里充斥着「666」「好好好」「哈哈哈」这类无意义重复词还有大量标点符号和表情符号。这些噪声不处理掉词向量会被污染模型学到的全是废话特征。import re import jieba def clean_comment(text): # 去掉无意义重复词 noise_words [666, 好好好, 哈哈哈, 呵呵, 嗯嗯, 啊啊] for w in noise_words: text text.replace(w, ) # 去掉标点符号和特殊字符只保留中文 text re.sub(r[^\u4e00-\u9fa5], , text) return text def cut_words(text): # jieba 精确模式分词 words jieba.cut(text, cut_allFalse) # 过滤停用词和单字 stop_words set([的, 了, 是, 在, 我, 有, 和, 就]) return [w for w in words if w not in stop_words and len(w) 1] # 示例 raw 这个商品真的好好好质量666物流也快 cleaned clean_comment(raw) print(cleaned) # 输出这个商品真的质量物流也快 print(cut_words(cleaned)) # 输出[这个, 商品, 真的, 质量, 物流]逻辑说明clean_comment先做字符串替换去掉噪声词再用正则[^\u4e00-\u9fa5]把所有非中文字符干掉包括标点、数字、英文和 emoji。cut_words用 jieba 的精确模式cut_allFalse这个模式会把「物流也快」切成「物流」「也快」而不是「物」「流」「也」「快」更符合语义。停用词表是硬编码的实际用的时候可以换成更完整的哈工大停用词表。参数上要注意len(w) 1这个过滤条件它把单字词去掉了。单字词在情感分析里信息量太低「好」「差」这种单字虽然带情感但单独出现时歧义太大不如过滤掉让模型聚焦在双字以上的词组上。3.2 Word2vec 词向量训练与词典构造清洗完的文本要转成向量才能喂给模型。项目用 Word2vec 训练词向量核心脚本在model目录下。训练过程分两步先构造词语字典再训练词向量。from gensim.models import Word2vec import pandas as pd import jieba # 读取所有评论构造语料 corpus [] for file in [pos.csv, neg.csv, neutral.csv]: df pd.read_csv(file, encodingutf-8) for text in df[comment]: words jieba.cut(str(text), cut_allFalse) corpus.append(list(words)) # 训练 Word2vec 模型 model Word2vec( sentencescorpus, size100, # 词向量维度100 维在评论数据上够用 window5, # 上下文窗口5 表示看前后各 5 个词 min_count2, # 出现次数少于 2 的词直接丢掉 workers4, # 并行线程数 sg1 # 1 表示 Skip-gram0 表示 CBOW ) model.save(w2v_model.pkl) # 查看某个词的向量 print(model.wv[质量].shape) # 输出 (100,)逻辑说明size100是词向量维度维度越高表达能力越强但训练越慢评论数据量不大时 100 维足够。window5控制上下文范围情感分析里情感词和修饰词的距离通常不超过 5 个词。min_count2过滤低频词避免噪声词进入词表。sg1选 Skip-gram 而不是 CBOW是因为 Skip-gram 对低频词的表征更好评论里很多商品特有的低频词用 Skip-gram 能学到更准的向量。训练完的w2v_model.pkl就是后续 SVM 和 LSTM 的输入基础。SVM 用词向量的平均值作为句子特征LSTM 则直接把词向量序列喂进网络。4. SVM 与 LSTM 模型对比两种分类路线怎么选、怎么跑4.1 SVM 训练脚本与参数调优SVM 部分在svm/train_svm.py。它的思路很直接把每条评论的所有词向量取平均得到一个固定长度的句子向量然后丢给 SVM 做分类。这种做法的优点是快缺点是丢了词序信息。from sklearn.svm import SVC from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report from gensim.models import Word2vec import numpy as np import pandas as pd import jieba # 加载词向量模型 w2v Word2vec.load(w2v_model.pkl) def sentence_vector(text): words jieba.cut(str(text), cut_allFalse) vecs [w2v.wv[w] for w in words if w in w2v.wv] if len(vecs) 0: return np.zeros(100) return np.mean(vecs, axis0) # 构造训练数据 df pd.read_csv(train_cut.csv) X np.array([sentence_vector(t) for t in df[comment]]) y df[label].values X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # 训练 SVM clf SVC(kernelrbf, C1.0, gammascale) clf.fit(X_train, y_train) # 评估 y_pred clf.predict(X_test) print(classification_report(y_test, y_pred))逻辑说明sentence_vector把一条评论里所有词的向量取平均这是最朴素的句子表征方式。SVC的kernelrbf是径向基核适合非线性可分的数据C1.0是惩罚系数越大越容易过拟合越小越容易欠拟合gammascale让 sklearn 自动根据特征方差算 gamma省去手动调参。train_test_split的random_state42固定随机种子保证每次跑出来的划分一样方便复现。SVM 在这个任务上的准确率通常在 85% 左右跑得快几分钟就能出结果。但它的天花板也明显句子向量取平均把词序信息全丢了「质量好」和「好质量」在它眼里是一样的。4.2 LSTM 训练脚本与模型保存LSTM 部分在model/lstm_test.py和train_lstm.py。它保留了词序用词向量序列作为输入通过 LSTM 层捕捉上下文依赖。代价是训练慢需要调的超参多。import tensorflow as tf import numpy as np from gensim.models import Word2vec import jieba # 加载词向量 w2v Word2vec.load(w2v_model.pkl) max_len 50 # 每条评论截断或补齐到 50 个词 def text_to_sequence(text): words jieba.cut(str(text), cut_allFalse) seq [w2v.wv.key_to_index.get(w, 0) for w in words][:max_len] if len(seq) max_len: seq [0] * (max_len - len(seq)) return seq # 构造输入 X np.array([text_to_sequence(t) for t in df[comment]]) y tf.keras.utils.to_categorical(df[label], num_classes2) # 搭建 LSTM 模型 model tf.keras.Sequential([ tf.keras.layers.Embedding(input_dimlen(w2v.wv), output_dim100, weights[w2v.wv.vectors], trainableFalse), tf.keras.layers.LSTM(64, return_sequencesFalse), tf.keras.layers.Dropout(0.5), tf.keras.layers.Dense(2, activationsoftmax) ]) model.compile(losscategorical_crossentropy, optimizeradam, metrics[accuracy]) model.fit(X, y, batch_size32, epochs10, validation_split0.2) model.save(lstm_three.h5)逻辑说明max_len50是序列长度上限超过截断、不足补零。Embedding层直接加载预训练好的 Word2vec 向量trainableFalse表示训练时不更新词向量这样能利用预训练语义且减少参数量。LSTM(64)是 64 个隐藏单元Dropout(0.5)防过拟合Dense(2, softmax)输出二分类概率。batch_size32、epochs10是常见起点数据量大就调大 batch_size收敛慢就加 epochs。LSTM 的准确率通常比 SVM 高 3 到 5 个百分点但训练时间可能是 SVM 的几十倍。如果只是交毕设SVM 够用如果想在答辩时讲出深度LSTM 的调参过程本身就是素材。5. 避坑与排查跑这个项目最容易翻车的五个地方5.1 模型加载报错h5 文件读不进去现象load_model(lstm_three.h5)报ValueError: Unknown layer或OSError: Unable to open file。原因通常是 TensorFlow 版本不匹配TF 2.x 加载 TF 1.x 保存的 h5 文件时自定义层或配置会解析失败。解决确认pip show tensorflow显示的是 1.15.0如果已经是 2.x用tf.compat.v1.keras.models.load_model试试或者直接重新训练一遍模型。5.2 中文乱码pandas 读 csv 全是问号现象pd.read_csv(pos.csv)读出来的中文变成\xe8\xb4\xa8这种编码。原因文件本身是 GBK 编码但 pandas 默认用 utf-8 读。解决加encodinggbk参数或者先用记事本把文件另存为 utf-8 格式。pos.xls用pd.read_excel读同样注意编码。5.3 jieba 分词结果不符合预期现象jieba.cut(物流很快)输出[物流, 很快]没问题但jieba.cut(质量杠杠的)输出[质量, 杠, 杠, 的]。原因jieba 默认词典里没有「杠杠的」这个词。解决用jieba.add_word(杠杠的)手动加词或者加载自定义词典jieba.load_userdict(userdict.txt)。评论里的网络用语多自定义词典是必须的。5.4 Selenium 报 SessionNotCreatedException现象启动 Chrome 时报SessionNotCreatedException: This version of ChromeDriver only supports Chrome version XX。原因chromedriver 版本和本机 Chrome 版本不匹配。解决打开 Chrome 设置看版本号去 chromedriver 官网下载对应版本替换根目录的 chromedriver 文件。版本号前三位要对上比如 Chrome 120.0.6099 对应 chromedriver 120.0.6099。5.5 SVM 训练准确率异常低现象classification_report输出的 accuracy 只有 50% 左右跟随机猜差不多。原因sentence_vector里w2v.wv[w]的 key 对不上大量词不在词表里导致句子向量全是零向量。解决检查 Word2vec 训练时的min_count是不是设太大了把min_count降到 1 重新训练或者在sentence_vector里加个判断如果有效词数为零就跳过这条样本。6. 进阶技巧用 GUI 界面做演示与模型效果验证答辩现场光跑命令行不够直观GUI/main_page.py提供了一个可视化界面输入评论就能看到情感判断结果。这个界面基于 tkinter 写的跑起来很简单cd GUI python main_page.py界面里通常有一个文本框输入评论一个按钮触发预测一个标签显示「正面」或「负面」。背后的逻辑是加载训练好的 SVM 模型和 Word2vec 模型对输入文本做同样的清洗、分词、向量化然后调clf.predict。如果你想在答辩时展示模型对比可以写个小脚本把 SVM 和 LSTM 的预测结果并排输出def compare_models(text): # SVM 预测 vec sentence_vector(text).reshape(1, -1) svm_result clf.predict(vec)[0] # LSTM 预测 seq np.array([text_to_sequence(text)]) lstm_result np.argmax(model.predict(seq), axis1)[0] return {SVM: 正面 if svm_result 1 else 负面, LSTM: 正面 if lstm_result 1 else 负面} print(compare_models(质量很好下次还来))这个对比表在答辩时特别有用评委问「为什么选 LSTM 不选 SVM」的时候你可以直接展示两条模型在同一批测试样本上的准确率差异用数据说话比空谈原理有说服力。验证模型效果还有一个技巧从test_set.csv里随机抽 20 条人工标注情感倾向然后跟模型预测结果对比算一个简单的命中率。这个命中率不用追求多高80% 以上就能说明模型有效。如果低于 70%大概率是数据清洗环节出了问题回头检查停用词表和分词结果。从那以后我每次拿到这种文本分类项目都强制先跑一遍数据抽样检查确认清洗后的文本没有乱码、没有空样本、标签分布均衡再开始训练。这一步花十分钟能省掉后面几小时的排查。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进