ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

京东评论爬取与情感分析可视化:一条数据流水线全解析

京东评论爬取与情感分析可视化:一条数据流水线全解析

简介:这套资源是面向Python爬虫与数据分析学习者的京东商品评论爬取与情感分析可视化研究项目档案,完整覆盖网络数据采集、文本清洗、情感分类和结果可视化流程。压缩包共20个文件,约5.87MB,以Python脚本、CSV数据表、TXT说明文档为主体,辅以JPG/PNG图表与zbak/zip备份文件,便于对照代码与中间结果理解每一步处理逻辑。目前已有77人学习下载。内含情感分析、模型训练与爬虫采集的Python源码文件,以及原始评论、处理后数据和情感分类结果等多份CSV数据集;配合README说明文档可快速还原运行环境并复现实验,直观看到从数据清洗到模型训练再到图表展示的完整链路,对搭建类似评论分析任务有直接参考价值。

1. 京东商品评论爬取与情感分析可视化研究:一条差评背后的数据流水线

逛电商平台时,你是不是也有过这种体验:一件商品下方几千条评论,好评、中评、差评混在一起,中间还夹着几十字的长篇小作文,靠人眼根本看不完。《基于Python的京东商品评论爬取与情感分析可视化研究》解决的就是这个痛点:用Python写一个爬虫把商品评论自动抓下来,经过清洗整理,再用算法判断每条文本的情感倾向,最后画成饼图、柱状图和词云。整个过程不再需要手动读评论,程序像流水线一样,把“抓取→清洗→分析→呈现”全部跑完。为什么值得搞懂它?因为这个项目把爬虫、文本清洗、情感分析和可视化四件事串在了一条链路上,你看明白它,等于拿到了数据分析类项目的通用骨架,以后再遇到类似选题就不会懵。

2. 爬虫是什么:一个自动抄写员怎么把几千条评论搬回来

2.1 爬虫不是“黑入网站”,而是替你按下“保存网页”

普通人打开商品页面,看到的是排好版的图文、价格和评分区;但在浏览器背后,真正发生的是“电脑向服务器发请求,服务器把一整段HTML源码吐回来,浏览器再把它渲染成页面”。爬虫做的事情更简单:不渲染、不看版式,只把源码当作普通文本收下来。打个比方,你从图书馆借书,管理员不允许带原书离开,你就拿笔记本一页页抄——爬虫就是那个不知疲倦的抄写员,它不理解书里写了什么,只知道复制服务器开放出来的内容。项目里的jd_comment.py就是这样的抄写员,它负责发请求、收响应、抽取评论,最后把结果汇总成后面的jd_comment.txt或jd_comment.csv文件。

import requests # 1. 构造请求头,模拟一个普通浏览器访问 headers = {"User-Agent": "Mozilla/5.0"} # 2. 向商品评论区接口发送请求 resp = requests.get("https://example.com/api/comments", headers=headers) # 3. 确认请求成功:状态码200表示服务器正常返回 print(resp.status_code, resp.text[:300])

这段代码里有两个重点。headers里的User-Agent是发给服务器的“访客名片”,默认的Python请求头容易被识别成脚本,加一个浏览器标识能明显降低被拒概率。resp.status_code用于判断请求是否成功,2xx是正常,4xx和5xx都说明哪里出了问题,排查时先看这一行能省不少时间。resp.text是服务器返回的原始文本,打印前300个字符,是为了快速确认返回的是HTML页面还是JSON数据,确认之后才知道下一步该用哪种解析方式。

2.2 评论藏在哪:HTML标签里,还是异步接口的JSON里

刚写完上面的代码,你可能会发现一个问题:返回的文本里根本没有评论。这是因为现在的电商评论区几乎都是异步加载——页面先渲染出框架和标题,评论是浏览器的脚本等页面加载完再去“偷偷”读取的。如果直接看网页源码,只能看到一堆空的div,真正的评论在开发者工具的“网络”面板里,类型是XHR请求。找到那个请求以后,评论通常以JSON格式返回,评论内容、评分、时间被拆成一个个字段,解析起来很省力。json.loads()一行代码就能把JSON字符串变成Python字典,之后按键取值即可。而早期的网页评论是直接嵌在HTML标签里的,反而要用HTML解析器按class或id去抠,写法更绕。

import json # 假设text是从评论区接口拿到的JSON字符串 data = json.loads(text) # 标准接口返回里通常有comments这个列表 for item in data["comments"]: print(item["content"]) # 评论正文 print(item["rating"]) # 星级

这里最关键的是字段名。接口返回的JSON长什么样,决定了取content还是取text;所以拿到数据后的第一件事,往往不是写循环,而是print(data.keys())看一下有哪些键。这个习惯在实际项目里很实用,能避免“取了个不存在字段”的低级报错。

2.3 为什么选Python:一门语言把抓取、清洗、建模、画图全包了

如果只是想下载一个网页,大部分编程语言都能做到;但这份资源的完整目标是“采集→清洗→建模→画图”一整条流程。爬完数据马上要清洗,清洗完要分词和建模,建完模还要画图。每一步都换一个工具,光是转换文件格式就够折腾。Python的好处是这些环节全都有成熟库接应:requests负责采集,pandas负责表格清洗,jieba负责分词,scikit-learn提供朴素贝叶斯等模型,matplotlib负责出图。这些库之间共享同一套数据对象,模型训练完可以直接把结果交给画图函数,不用经过任何中间转换。这也是为什么数据分析类的大作业普遍默认用Python——不是因为别的语言做不到,而是因为Python把链路成本压到了最低。

2.4 动态加载和翻页:评论不是一页能抓完的

评论区几乎都是分页加载的,一页只有20条,要抓几千条就得翻几十页。翻页的规律通常藏在请求参数里,比如page=2或page_num=3。代码里只需要维护一个页码变量,每次循环把页码塞进请求,然后解析数据、追加保存。真正值得注意的不是怎么翻页,而是翻页的节奏。如果毫无间隔地连续发请求,服务器会认为你在攻击它,轻则当前IP被临时限制,重则整个会话被封。

for page in range(1, 6): # 每页请求更换page参数,模拟用户浏览 params = {"page": page, "page_size": 20} resp = requests.get(comment_api, headers=headers, params=params) # 处理当前页评论... time.sleep(2) # 暂停2秒,降低访问频率

这段代码的动作很简单,但time.sleep(2)这一行是真正的“经验值”。没有它,代码跑得快,IP死得也快;加上它,抓取慢一点,但能稳定跑完全程。参数page_size是每页条数,很多评论接口支持把它调大,比如调成50或100,能减少翻页次数,但过大的page_size也可能触发反爬,需要自己试。

2.5 踩坑预警:高频率、登录态和验证码

除了翻页,还有两个常见坑位会让爬虫脚本“半路熄火”。第一个是登录态,部分平台的评论区需要登录后才能加载,直接请求接口拿到的可能是空列表。处理方式通常是先手动登录一次,把浏览器Cookie复制出来,塞进请求头里。第二个是验证码,触发频率控制之后可能会弹出滑块或图片验证,简单脚本过不去,只能停下来人工处理。这些在爬虫学习里都属于经典问题,不是玄学,每个做采集的人都会撞上。项目里的脚本面向学习场景,量级小,正常跑没有太大风险,但自己上手扩展时,一定要控制频率、控制范围。

提示:本项目仅用于学习交流,请勿用于商业用途,也不要给目标平台造成访问压力。

3. 数据清洗为什么躲不掉:原始评论数据远比你想的脏

3.1 原始评论不是干净的句子,而是标签、转义符和文本的混合物

从接口里拿到的评论文本,看着像一句话,实际是一锅杂烩。表情符号可能变成了👍这样一串字符,换行变成了\n,HTML标签可能混在句子中间,评分字段里还可能出现半角空格和全角空格同时存在的情况。项目里的jd_comment.txt就是这类原始文本的集合,直接把它喂给统计工具,结果会非常离谱——Word里的字数统计会莫名其妙变多,Excel里做筛选也会被隐藏字符干扰。数据清洗这个环节之所以存在,就是因为现实中的原始数据几乎都不符合分析工具的输入要求。这和你从菜市场买回来的菜不可能直接下锅是一个道理,总得先摘、先洗、先切。

3.2 清洗是一个固定流程:去重、去标签、去符号、再标准化

清洗不是“碰运气式”地删几行,而是一套有顺序的固定操作。先去重,把重复评论删掉,否则同一句话会被当成好几条记录,统计权重被无端放大;再去掉HTML标签,因为标签是页面结构的代码,不是用户表达;接着用正则去掉特殊符号,只保留中文、字母和数字,这一步能把表情和乱码一并清走;最后做标准化,比如繁体转简体、全角转半角、压缩多余空白。项目里的processed_comment_data.csv就是这套流程跑完后的干净数据,后续的分词、情感分析和画图都以它为准。很多初学者跳过了这一步直接建模,等到结果出不来再回头补,往往要返工大半天。

import re def clean_text(text: str) -> str: text = re.sub(r"<[^>]+>", "", text) # 1. 去掉HTML标签 text = re.sub(r"\\[nrt]", "", text) # 2. 去掉换行和制表符转义 text = re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9]", "", text) # 3. 只留中文、字母、数字 return text.strip() # 4. 去掉首尾空白

clean_text这个函数就是清洗核心。第1条正则把<和>之间的内容全部删掉,适用于去除HTML标签;第2条处理的是文本里的转义字符;第3条最关键,把所有不是中文、字母和数字的字符直接移除,表情符号和emoji在这一步被清掉。参数方面,如果你希望保留标点以便做句子切分,可以把第3条正则需要对应调整,比如把标点也加入白名单。清洗的结果直接影响后面分词的准确度和词云的判断——脏字符越少,后续产出越干净。

3.3 清洗前后对照表:一行数据经历了什么

我们可以把清洗前后的文本放在一起对比,感受一下变化量。

清洗前处理动作清洗后
<span>这手机手感不错👍</span>\n去标签、去转义、去符号这手机手感不错
好用\n好用\n好用去重好用
屏幕清晰。【自营】去掉无信息尾部(可选)屏幕清晰

第一行是最典型的情况,HTML标签、转义符、表情混在一起,正则处理完只剩一句干净的评语。第二行是数据采集时常见的重复,不先去重,词频统计会把“好用”放大三倍。第三行里【自营】是平台附加信息,与用户情感无关,要不要去掉取决于分析目标;如果只关心用户体验表达,保留它会让词云和特征向量里多出一个无意义词。清洗策略没有绝对标准,但原则是明确的:只保留和分析目标相关的文本内容。

3.4 不洗会怎么样:词云里飘满“的”“了”“很”

这是文本分析里最容易翻车的一幕:辛辛苦苦跑完代码,生成的词云图上全是“的”“了”“很”“我”这类信息量为零的词,看起来像分词工具出了问题,实际是原始文本没洗干净。HTML残留会让分词器产生畸形词块,表情和特殊符号会让词频统计失真,重复文本会让某些词被成倍放大。数据清洗这一步做得扎不扎实,直接决定情感分析模型学到的是评价内容,还是一堆噪声。项目里的train.py训练之前,必须先确认processed_comment_data.csv里的文本是干净的,这个顺序不要反过来。磨刀不误砍柴工,在这条流水线里,清洗就是那把刀。

4. 情感分析的易混概念:机器怎么判断“还行”算中性

4.1 情感分析不是读心术,而是给文本贴分类标签

当人看到“这手机手感不错”这句话,会自然地认为这是正面评价;看到“用了一周就开始卡”会判断这是负面反馈。情感分析的目标,是让计算机也能独立完成这种判断。但需要说清楚的是,计算机并不理解“手感”是什么,也不理解“卡”带来的烦躁感,它只是把一个句子映射到预先定义好的类别上——正面、中性或负面。更规范的说法叫“意见挖掘”,因为它挖掘的是文本表达出来的倾向,而不是用户内心的真实情绪。项目里的sentiment_analysis.py做的就是这件事:读入一条评论文本,输出一个情感标签;输入输出都很简单,复杂的部分全在读取之前已经处理完毕。

4.2 机器怎么学会分类:从带标签语料中计算概率

机器不认识“不错”是褒义的,它需要先看大量例子。项目里的online_shopping_10_cats.csv就是这样一份带标签的电商评论语料,每一行都包括一条评论文本和它的情感分类。train.py在训练时大致做四件事:先用jieba把评论切分成词,然后把句子转换成模型能计算的向量特征,再把数据按比例切分成训练集和验证集,最后用朴素贝叶斯从训练集中统计词与情感标签的关系。

朴素贝叶斯的直觉特别适合初学者理解。你可以把“好评”和“差评”想象成两个大口袋,口袋里装着从训练语料里统计出来的词;“不错”“清晰”这类词在好评口袋里出现得多,“卡”“退货”在差评口袋里出现得多。新评论进来时,先拆成词,再分别看这些词在哪个口袋里更常见,最后综合所有词的判断,给整句评论投一票。它运算量小,几千条数据就能得到可用结果,而且每个判断都能反推出“是哪些词把它推向这个类别”,解释起来不费劲。

from sklearn.naive_bayes import MultinomialNB # 用清洗后的评论特征X和标签y训练分类器 model = MultinomialNB() model.fit(X_train, y_train) # 预测新评论的情感倾向,0为负面、1为中性、2为正面 y_pred = model.predict(X_test)

这里建议至少看懂两点。第一,MultinomialNB适合输入是离散特征(比如词频统计结果)的分类任务,正好匹配“分词→向量化”之后的评论数据;第二,fit接收的是已经转换好的数值特征X_train,不是原始字符串,所以如果直接拿pandas里的评论列喂进去,一定会报错。X_train是怎么来的,是理解这份代码的关键。

4.3 这里有几个初学者最容易搞混的点

下面这五个点是初学者最容易搞混的地方,逐个说清楚。

第一,情感分析不等于关键词匹配。有人觉得“准备一个好评词库、一个差评词库就能判断”,但碰到“屏幕不差”就露馅了——词库里有“差”这个负面词,整句话却明显是正面。关键词只是特征的一部分,真正的分类器会用整句词的组合来做判断。

第二,平台星级不等于文本情感。用户打三星写“还行,能用”,星级是中评,文本也接近中性;但有人直接把星级当成训练标签,模型就会学错方向。标注数据时,正确做法是让真人去看文本内容打标签,而不是抄平台的评分。

第三,分词不等于情感分析。jieba分词只是把句子切碎,就像把菜切好不等于菜做好了。分词是前置步骤,情感分析要等在分词、去停用词、向量化之后才开始。

第四,准确率不是越高越好。模型在训练集上拿到99%,不一定说明它强,更可能是它把训练样本背了下来,换一批没见过的新评论就崩溃,这是过拟合。判断模型好坏要看验证集上的表现,而不是训练集分数。

第五,负面词不一定代表负面情绪。“这款手机不发热”里有“热”,而它恰恰是卖点;“两天才充一次电”里的“才”让句子变成夸奖。这类否定和程度结构,只能靠模型在完整句子上学习,单看一个词必然误判。

4.4 为什么这个项目选朴素贝叶斯而不是深度学习

既然提到情感分析,很多人第一反应是用深度学习甚至大模型。但这份项目的数据量只有几千条评论,在这个规模下,深度学习训练不稳定,非常容易过拟合,跑出来可能还不如朴素贝叶斯。朴素贝叶斯的最大优点是“少样本也能干活”,收敛快、可解释、跑起来不挑机器。项目里sentiment.marshal.3就是训练完成后保存下来的模型文件,marshal是Python自带的一种序列化格式,通俗说就是“把训练好的模型打包成一个文件”,下次直接加载就能用,不用重新训练一遍。这种“先训练→保存→再加载预测”的套路,在真实项目里几乎是标准动作。

5. 可视化和文件串联:从CSV到图表,最后交付了什么

5.1 饼图、柱状图、折线图、词云:什么时候用哪张图

情感分析的结果如果只躺在CSV表格里,看报告的人很难快速抓住重点。可视化的作用,是把分析结论翻译成图形语言,让人不需要懂技术就能看懂结果。饼图和环形图适合展示整体构成——正面、中性、负面各占多少百分比,扫一眼就知道口碑是多是少;柱状图适合对比数量差异,比如不同商品的差评数、不同时间段的差评数;折线图适合展示情绪随着时间的变化,比如某次版本更新之后差评是变多了还是变少了;词云则把高频关键词按出现次数放大字号,让人一眼看出用户最在意的是“续航”“拍照”还是“售后”。这些不同图形回答的是不同问题,选错图会让结论大打折扣。

5.2 以jd开头的一组文件是怎么串联起来的

这个项目的文件不是散落的零件,它们串成一条完整的数据流水线:

文件名在流水线里的作用
jd_comment.py采集脚本,负责抓取评论并输出原始文本
jd_comment.txt / jd_comment.csv采集结果,原始评论的两种存储形式
processed_comment_data.csv清洗后的数据集,供模型训练和分析使用
train.py训练情感分类模型,并保存模型文件
sentiment_analysis.py加载模型,对评论做情感判断并输出结果
result.csv最终分析结果,含情感标签和统计数据
fig.png / jd_ciyun.jpg可视化输出,供报告直接使用

顺着这张表走一遍,整个流程就是:jd_comment.py采集到原始评论,清洗后进入processed_comment_data.csv;train.py在这个干净数据上训练模型,把训练好的分类器保存下来;sentiment_analysis.py加载模型,对每一条评论做情感判断,结果汇总到result.csv;最后用统计图fig.png和词云图jd_ciyun.jpg把结论可视化。每一步的输出都是下一步的输入,环环相扣,这正是它适合当作学习范本的原因——你看到的不只是“一段爬虫代码”,而是一条能跑通全流程的链条。

5.3 文本辅助文件是干什么的:positive.txt、negative.txt和词云之间的关系

除了核心脚本,包里还有几个容易被忽略的文本文件,它们也在承担职责。positive.txt和negative.txt是正面与负面情感词库,分别存放了常见的褒义表达和贬义表达;这类词库经常被用来做最简单的规则判断——一句评论如果命中了多个正面词,就初步偏向正面。它和模型训练可以互为参照:模型结果和词库判断对不上时,往往能帮你发现训练数据里的标注问题。jd_ciyun.jpg是词云图,是基于清洗后评论文本的分词结果生成的。requirements.txt则是依赖清单,记录了这个项目运行所需的所有Python库名称和版本范围,在新环境里执行pip install -r requirements.txt就能一键装齐。另外,那些带.zbak后缀的文件是备份,比如train.py.zbak、requirements.txt.zbak,相当于代码的“后悔药”,改坏了原文件可以随时换回来。jdicon.jpg是界面图标,主要用在报告示意,不影响分析流程。

5.4 可视化是最后一步,但它决定分析能不能被看懂

项目里最常被人直接拿进报告的不是CSV,而是fig.png和jd_ciyun.jpg。这说明一个现实:数据分析项目做到最后,沟通效率往往比计算精度更能决定成果的评价。饼图和词云把“正面评价占多少”“大家最常讨论什么词”压缩成一眼就能吸收的信息,这比逐行看表格高效太多。也正因此,这类选题才会频繁出现在数据分析的大作业里——链路完整、结果可视化、交出来的图表本身就是最好的说明。你在自己动手复现的时候,可以试着换一套商品评论来跑,你会发现只要清洗和训练两个环节没有偷懒,出图只是几分钟的事。

6. 什么时候适合用这套流程:三个边界判断避免白干

6.1 适合用它的场景

如果你正在准备数据分析方向的课程大作业,需要找一个能完整跑通的案例,这份资源就是为这种场景准备的。文件里包含爬虫脚本、清洗后的数据集、训练脚本和输出图表,下载下来对着流程跑一遍,就能看到从评论到图表的全过程。如果你想快速了解某个商品的用户口碑方向,并不打算搭建正式系统,也可以用这套思路做一次小规模调研,把result.csv和两张图作为结论支撑。

6.2 不适合用它的场景

有几类情况不要硬搬。第一,商用或大规模采集,超出学习脚本的能力范围,也容易触碰法律红线。第二,数据源换成社交媒体内容,比如微博评论朋友圈留言,这些文本口语化、短句多,在电商语料上训练出来的模型效果会明显下降。第三,数据量非常大,比如几十万条评论,虽然朴素贝叶斯本身跑得动,但清洗和可视化环节会暴露出性能瓶颈,这个项目里提供的基础脚本达不到生产要求。

6.3 我的边界判断方法

我拿到类似代码时,会先问自己三个问题:数据是不是只用于学习?采集量是不是控制在合理范围?分析结果会不会被拿去商业化?三个答案都符合预期,才继续动手。有一次我跑完模型,词云图上全是“的”“了”“很”,当时以为代码写错了,排查半天才发现清洗步骤被我省掉了,脏文本直接喂进了模型。从那以后,我每次做文本分析都强制把“清洗”当成独立一步走完,不再跳过——希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

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