Python京东评论爬取与情感分析可视化全流程实战
简介这份资源面向具备Python基础、希望上手电商文本挖掘与情感分析的学习者围绕京东商品评论的采集、清洗、情感判断与可视化展开可作为课程大作业或数据分析练手项目。压缩包共20个文件约5.87MB以py脚本、csv数据表、txt文本、jpg/png图表及zbak备份为主脚本负责爬取、模型训练与情感分析csv保存原始评论、处理后数据与结果图片为词云和分类图标另附说明文档与依赖清单结构清晰便于按模块查阅。目前已有76人学习下载。读者可参考完整流程理解从评论抓取、去重清洗到朴素贝叶斯等模型分类再到条形图、饼图等可视化呈现的思路并借助现成数据与脚本复现实验、调整模型或迁移到其他商品评论场景。1. 从一份京东评论数据包说起Python 爬取、情感分析与可视化到底怎么串起来很多人做电商评论分析第一步就卡在“数据从哪来”。这份基于 Python 的京东商品评论爬取与情感分析可视化资源包解决的正是从采集到出图的全链路问题。它包含爬虫脚本jd_comment.py、情感分析脚本sentiment_analysis.py、模型训练脚本train.py以及已经跑出来的jd_comment.csv、processed_comment_data.csv、result.csv三份结果文件还有positive.txt、negative.txt两个情感词典和jd_ciyun.jpg词云图。换句话说这不是一个空壳代码而是一套带样本数据、带中间产物、带可视化结果的完整作业包。适合正在做课程设计、想跑通“爬取—清洗—情感分类—可视化”闭环的 Python 学习者也适合需要快速验证中文评论情感分析流程的开发者。下面我按实际拆包顺序把每一步的参数、坑和验证方法讲清楚。2. 拆包先看文件jd_comment.py 爬虫脚本与数据字段设计2.1 爬虫脚本的核心逻辑与请求参数jd_comment.py是整个流程的入口。京东商品评论接口通常返回 JSON 结构核心字段包括content评论正文、creationTime评论时间、score评分、productColor、productSize等。脚本一般会构造一个带productId、page、sortType的请求循环翻页直到没有新评论或达到设定页数。常见做法是用requests发 GET 请求把User-Agent和Referer写进 headers避免被直接拒绝。下面是我按这个资源包结构还原出的典型请求片段你可以对照自己的jd_comment.py看是否一致import requests import csv import time # 京东评论接口常见参数productId 是商品 IDpage 是页码sortType 控制排序 base_url https://club.jd.com/comment/productPageComments.action params { productId: 100012043978, # 换成你要爬的商品 ID score: 0, # 0 表示全部评分1 差评2 中评3 好评 sortType: 5, # 5 表示按时间排序6 表示按推荐排序 page: 0, pageSize: 10, isShadowSku: 0, fold: 1 } headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://item.jd.com/100012043978.html } all_comments [] for page in range(0, 20): # 先爬 20 页约 200 条够课程设计用 params[page] page resp requests.get(base_url, paramsparams, headersheaders, timeout10) data resp.json() comments data.get(comments, []) if not comments: break for c in comments: all_comments.append({ content: c.get(content, ).replace(\n, ), creationTime: c.get(creationTime, ), score: c.get(score, 0) }) time.sleep(1) # 每次翻页停 1 秒降低请求频率 with open(jd_comment.csv, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[content, creationTime, score]) writer.writeheader() writer.writerows(all_comments)这段代码的逻辑很直白先拼参数再循环翻页每页取comments列表把正文、时间、评分三个字段抽出来存 CSV。参数里score决定你拿的是全部评论还是只拿好评/差评sortType影响你拿到的时间分布。time.sleep(1)是血泪经验不 sleep 连续翻页很容易触发频率限制返回空数据。encodingutf-8-sig是为了 Excel 打开不乱码这个细节在jd_comment.csv里能直接验证——用记事本打开看开头有没有 BOM 字符。2.2 数据字段与后续清洗的衔接爬下来的jd_comment.csv通常只有三列但情感分析需要的是干净文本。processed_comment_data.csv就是清洗后的产物一般会多出clean_content或label列。清洗动作包括去掉 HTML 标签、去掉表情符号、去掉重复评论、过滤掉“此用户未填写评价内容”这类默认好评。你可以用下面这段代码检查清洗前后的差异import pandas as pd import re df pd.read_csv(jd_comment.csv) print(原始条数, len(df)) print(原始样例, df[content].iloc[0][:50]) # 常见清洗去标签、去特殊符号、去空白 def clean_text(text): text re.sub(r.*?, , str(text)) # 去 HTML 标签 text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9。], , text) # 只留中文、英文、数字和常用标点 text text.strip() return text df[clean_content] df[content].apply(clean_text) df df.drop_duplicates(subset[clean_content]) # 按清洗后文本去重 df df[df[clean_content].str.len() 2] # 过滤掉过短评论 print(清洗后条数, len(df)) df.to_csv(processed_comment_data.csv, indexFalse, encodingutf-8-sig)这里的关键参数是正则表达式[^\u4e00-\u9fa5a-zA-Z0-9。]它决定了你保留哪些字符。如果你发现processed_comment_data.csv里评论被削得太狠比如“手机很好用”变成“手机很好用”那说明标点保留没问题如果变成“手机很好用”少了感叹号就把加进白名单。去重和长度过滤是防止模型被“好评”“不错”这种短文本带偏一般保留长度大于 2 的评论。3. 情感分析脚本怎么跑sentiment_analysis.py 与 train.py 的分工3.1 两种情感分析路线词典法 vs 机器学习资源包里同时有positive.txt、negative.txt和train.py说明它支持两条路线。词典法直接拿sentiment_analysis.py对processed_comment_data.csv逐条匹配速度快、无需训练适合课程设计快速出结果。机器学习路线用train.py在online_shopping_10_cats.csv上训练一个分类器再把模型应用到京东评论上准确率更高但需要标注数据。online_shopping_10_cats.csv是公开的中文电商评论数据集包含 10 个类别的评论和情感标签常见做法是用它训练朴素贝叶斯或 SVM。下面是一个词典法情感打分的核心片段import pandas as pd # 加载情感词典每行一个词 with open(positive.txt, r, encodingutf-8) as f: pos_words set(line.strip() for line in f if line.strip()) with open(negative.txt, r, encodingutf-8) as f: neg_words set(line.strip() for line in f if line.strip()) def sentiment_score(text): pos_count sum(1 for w in pos_words if w in text) neg_count sum(1 for w in neg_words if w in text) if pos_count neg_count: return positive elif neg_count pos_count: return negative else: return neutral df pd.read_csv(processed_comment_data.csv) df[sentiment] df[clean_content].apply(sentiment_score) df.to_csv(result.csv, indexFalse, encodingutf-8-sig) print(df[sentiment].value_counts())这段代码的逻辑是“词命中计数”正面词命中多就判正面负面词多就判负面持平判中性。参数上词典文件必须是 UTF-8 编码每行一个词不能有空行。result.csv里会多出sentiment列你可以直接value_counts()看三类比例。如果中性占比超过 60%说明词典覆盖不够需要补充领域词比如“续航”“屏幕”“物流”这些京东评论高频词。3.2 机器学习路线train.py 的训练与保存train.py通常做三件事读online_shopping_10_cats.csv、用jieba分词、用sklearn训练分类器并保存模型。资源包里有个sentiment.marshal.3这是 Python 旧版序列化文件说明模型是用marshal或pickle保存的。常见做法是用TfidfVectorizer加MultinomialNB训练完把模型和向量器一起存下来。下面是一个可复现的训练片段import pandas as pd import jieba from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB import pickle # online_shopping_10_cats.csv 通常有 cat、label、review 三列 data pd.read_csv(online_shopping_10_cats.csv) data data.dropna(subset[review, label]) # 分词去掉单字和空白 def cut(text): return .join([w for w in jieba.cut(str(text)) if len(w) 1]) data[cut_review] data[review].apply(cut) vectorizer TfidfVectorizer(max_features5000) # 最多保留 5000 个特征词 X vectorizer.fit_transform(data[cut_review]) y data[label] model MultinomialNB() model.fit(X, y) with open(sentiment_model.pkl, wb) as f: pickle.dump((vectorizer, model), f) print(模型已保存训练样本数, X.shape[0])参数max_features5000控制特征维度太大容易过拟合太小会丢信息。jieba.cut后过滤单字是为了减少噪声因为“好”“差”这种单字在电商评论里歧义大。训练完用pickle保存(vectorizer, model)元组预测时先transform再predict。如果你拿到的是sentiment.marshal.3可以用marshal.load读但注意 Python 版本兼容性3.8 以上读旧 marshal 文件可能报错建议直接用train.py重新训一个。4. 可视化与结果验证从 result.csv 到 jd_ciyun.jpg4.1 词云图与情感分布图的生成jd_ciyun.jpg是词云图通常用wordcloud库加jieba分词生成。情感分布图可以用matplotlib画饼图或条形图。下面这段代码同时生成词云和情感占比图import pandas as pd import jieba from wordcloud import WordCloud import matplotlib.pyplot as plt df pd.read_csv(result.csv) text .join(df[clean_content].astype(str)) words .join(jieba.cut(text)) # 生成词云font_path 必须指向中文字体否则显示方块 wc WordCloud(font_pathsimhei.ttf, width800, height400, background_colorwhite, max_words100).generate(words) wc.to_file(jd_ciyun.jpg) # 情感分布饼图 counts df[sentiment].value_counts() plt.figure(figsize(6, 6)) plt.pie(counts.values, labelscounts.index, autopct%1.1f%%) plt.title(京东评论情感分布) plt.savefig(sentiment_pie.png) print(counts)关键参数是font_pathWindows 下用simhei.ttfLinux 下换成/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc否则词云全是方框。max_words100控制词云显示词数太多会挤在一起。饼图的autopct显示百分比方便直接写进报告。4.2 结果文件对照与验证方法资源包里有jd_comment.csv、processed_comment_data.csv、result.csv三份文件验证流程是否跑通就看这三份的行数和列数是否合理。下面是一个对照表文件名预期列行数关系验证点jd_comment.csvcontent, creationTime, score原始爬取条数是否有空 contentprocessed_comment_data.csvclean_content, creationTime, score少于等于原始条数去重后是否明显减少result.csvclean_content, sentiment等于清洗后条数三类情感是否都有如果result.csv里只有 positive 和 negative没有 neutral说明词典法把中性都归到了某一类需要检查sentiment_score函数的持平分支。如果processed_comment_data.csv行数比jd_comment.csv少很多比如少了一半那是去重和长度过滤的正常结果但少到只剩几十条就说明清洗太狠要放宽正则白名单。5. 避坑与常见问题爬取、编码、模型加载的翻车现场5.1 爬取返回空数据或 403现象jd_comment.py跑起来comments列表为空或者直接返回 403。原因通常是请求头缺少Referer或User-Agent被识别为脚本也可能是翻页太快触发频率限制。解决补全 headers 里的Referer为商品详情页地址每次翻页time.sleep(1)以上必要时把pageSize降到 10。如果还不行换一个sortType再试有时候接口对排序参数有校验。5.2 CSV 打开乱码现象jd_comment.csv用 Excel 打开中文变乱码。原因写入时用了utf-8而不是utf-8-sigExcel 默认按 GBK 解析。解决所有to_csv和open写入都加encodingutf-8-sig读取时用encodingutf-8即可。这个坑在processed_comment_data.csv和result.csv上同样适用。5.3 词云中文显示方块现象jd_ciyun.jpg里中文全是方框。原因WordCloud默认字体不支持中文。解决下载simhei.ttf放到脚本同目录font_path写相对路径Linux 环境用fc-list :langzh找中文字体路径。如果找不到字体用matplotlib的rcParams[font.sans-serif] [SimHei]也能救急。5.4 sentiment.marshal.3 加载失败现象用marshal.load读sentiment.marshal.3报ValueError: bad marshal data。原因marshal 格式跟 Python 版本强绑定旧版本序列化的文件在新版本可能读不了。解决直接用train.py重新训练一个模型用pickle保存兼容性更好。如果非要读旧文件确认 Python 版本跟生成时一致通常 3.6/3.7 之间兼容性较好。5.5 情感分析结果一边倒现象result.csv里 90% 以上都是 positive。原因京东评论本身好评居多加上词典法对“不错”“很好”这类词过度敏感。解决在processed_comment_data.csv阶段做分层采样或者用train.py的机器学习模型替代词典法。另外检查negative.txt是否包含“差”“慢”“坏”等基础负面词词典不全也会导致负面漏判。6. 进阶技巧用 train.py 模型替换词典法并做交叉验证词典法跑通后最值得做的一步是用train.py训练出的模型替换sentiment_analysis.py里的打分逻辑。具体做法是先加载sentiment_model.pkl对processed_comment_data.csv的clean_content做同样的jieba分词再用vectorizer.transform转成特征矩阵最后model.predict得到预测标签。下面是一个替换示例import pandas as pd import jieba import pickle with open(sentiment_model.pkl, rb) as f: vectorizer, model pickle.load(f) df pd.read_csv(processed_comment_data.csv) def cut(text): return .join([w for w in jieba.cut(str(text)) if len(w) 1]) df[cut_content] df[clean_content].apply(cut) X vectorizer.transform(df[cut_content]) df[sentiment_ml] model.predict(X) # 跟词典法结果对比看差异比例 old pd.read_csv(result.csv) df[sentiment_dict] old[sentiment] diff (df[sentiment_ml] ! df[sentiment_dict]).mean() print(两种方法差异比例, round(diff, 3)) df.to_csv(result_ml.csv, indexFalse, encodingutf-8-sig)这段代码的关键是vectorizer.transform必须用训练时的同一个向量器不能重新fit否则特征空间对不上。diff比例能帮你判断两种方法的一致性一般差异在 15% 到 30% 之间算正常如果超过 50%说明词典法或模型有一方明显跑偏。我一般会再抽 20 条差异样本人工看一眼确认是模型更准还是词典更准。另一个进阶点是做交叉验证。train.py里可以用cross_val_score评估模型稳定性from sklearn.model_selection import cross_val_score scores cross_val_score(model, X, y, cv5, scoringaccuracy) print(5 折交叉验证准确率, scores.mean())cv5表示 5 折scoringaccuracy看准确率。如果交叉验证得分比训练集低很多说明过拟合需要降低max_features或换用LinearSVC。这些验证步骤做完你手里的result_ml.csv才真正有说服力而不是只跑通一个脚本。从那以后我每次拿到这种带train.py和sentiment.marshal.3的资源包都强制先跑一遍交叉验证再替换词典法避免直接拿旧模型套新数据。希望帮到你。本文还有配套的精品资源点击获取