实战!Python爬京东商品评论:从采集到情感分析+词云可视化,新手30分钟跑通

实战!Python爬京东商品评论:从采集到情感分析+词云可视化,新手30分钟跑通

电商商品评论里藏着黄金数据——用户对产品的真实反馈、痛点需求、满意度评价,不管是做市场调研、产品优化还是竞品分析,都是核心素材。但手动复制评论效率太低,用Python不仅能批量爬取,还能自动做情感分析、生成词云,快速提炼关键信息。

本文以京东商品为例(反爬宽松、结构清晰,新手友好),全程实战「评论爬取→数据清洗→情感分析→词云生成」全流程,用最基础的技术栈(requests+BeautifulSoup+SnowNLP),不用复杂配置,30分钟就能从0到1跑通,还能理解数据处理的核心逻辑。

一、核心流程与技术栈

1. 整体流程(新手必记)

  1. 爬取评论:向电商评论页发送请求,获取用户评论、评分、时间等数据;
  2. 数据清洗:过滤无效评论(空评论、重复评论)、处理特殊字符,让数据更干净;
  3. 情感分析:用中文情感分析库(SnowNLP)给评论打分(0-1分,越接近1越正面);
  4. 词云生成:拆分评论关键词,过滤无意义词汇(如“的”“了”),生成可视化词云;
  5. 结果展示:用图表呈现情感分布、关键词频率,直观看懂用户反馈。

2. 技术栈选型(新手友好,无需复杂配置)

功能库/工具作用说明
网络请求requests模拟浏览器获取评论页HTML数据
页面解析beautifulsoup4从HTML中提取评论、评分、时间等字段
数据处理pandas存储数据、清洗数据、统计分析
中文情感分析snownlp轻量中文情感识别,无需训练,直接调用
中文分词jieba拆分评论为关键词(如“续航给力”→[续航, 给力])
词云生成wordcloud可视化关键词频率,生成美观词云图
图表展示matplotlib绘制情感分布柱状图、评分分布饼图

3. 环境准备(5分钟搞定)

(1)安装Python

已安装的跳过,未安装的去官网下载:https://www.python.org/downloads/(推荐3.8-3.11版本),安装时Windows勾选“Add Python to PATH”,Mac默认自动配置。

验证是否成功:终端输入 python --version(或python3 --version),显示版本号即可。

(2)安装核心库

终端复制粘贴以下命令(国内用户下载慢可先换清华源:pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple):

pip installrequests==2.31.0 beautifulsoup4==4.12.3 pandas==2.2.2 pip installsnownlp==0.12.3 jieba==0.42.1 wordcloud==1.9.3 matplotlib==3.8.4 

二、第一步:爬取京东商品评论(核心实战)

1. 目标分析:京东评论页结构

先搞清楚评论数据藏在哪里,这是爬虫的关键:

  1. 打开京东任意商品页(比如:https://item.jd.com/100012345678.html),下拉到“商品评价”,点击“查看全部评价”;
  2. 按F12打开Chrome开发者工具,切换到「Elements」标签,用左上角“箭头图标”点击任意一条评论,右侧会定位到对应的HTML代码;
  3. 关键发现:
    • 每一条评论都包裹在 <div> 标签中;
    • 评论内容:<p>
    • 评分:<div>(通过class中的“star-X”判断,X=1-5);
    • 用户名:<div>
    • 评论时间:<span>
  4. 分页逻辑:评论页的分页参数是page,比如第1页page=1,第2页page=2,URL格式为:https://club.jd.com/comment/productPageComments.action?productId=商品ID&score=0&page=页码&pageSize=10
核心参数说明:
  • productId:商品唯一ID(从商品详情页URL中提取,比如上面链接的100012345678);
  • score:评分筛选(0=全部评论,1=差评,2=中评,3=好评);
  • pageSize:每页评论数(默认10条,可改20条,太多易被反爬)。

2. 爬取代码(带详细注释)

import requests from bs4 import BeautifulSoup import pandas as pd import time import random # ---------------------- 配置参数(新手只需修改这3处)---------------------- PRODUCT_ID ="100012345678"# 商品ID(从京东商品页URL提取) MAX_PAGE =5# 爬取页数(1页10条,5页=50条,新手先测试3-5页) HEADERS ={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/128.0.0.0 Safari/537.36","Referer":f"https://item.jd.com/{PRODUCT_ID}.html",# 模拟从商品页跳转,更像真实用户"Cookie":"你的京东Cookie"# (可选)登录京东后F12复制Cookie,避免爬取受限(不填也能爬少量数据)}# ------------------------------------------------------------------------defcrawl_jd_comments():"""爬取京东商品评论""" all_comments =[]# 存储所有评论数据 base_url ="https://club.jd.com/comment/productPageComments.action"print(f"开始爬取商品ID:{PRODUCT_ID} 的评论,共{MAX_PAGE}页...")for page inrange(1, MAX_PAGE +1):# 构造当前页评论URL params ={"productId": PRODUCT_ID,"score":0,# 0=全部评论,1=差评,2=中评,3=好评"page": page,"pageSize":10,"isShadowSku":0,"rid":0,"fold":1}try:# 发送请求(添加随机延迟,避免高频反爬) time.sleep(random.uniform(0.8,1.5)) response = requests.get( url=base_url, headers=HEADERS, params=params, timeout=10) response.raise_for_status()# 状态码非200抛出异常 response.encoding ="gbk"# 京东评论页编码为GBK,避免中文乱码# 解析HTML(京东评论页是静态HTML,直接用BS4解析) soup = BeautifulSoup(response.text,"lxml") comment_items = soup.find_all("div", class_="comment-item")ifnot comment_items:print(f"第{page}页未找到评论,可能已爬取到最后一页")break# 提取每条评论的核心字段for item in comment_items:# 评论内容(容错:无内容则填“无评论”) comment_con = item.find("p", class_="comment-con") content = comment_con.text.strip()if comment_con else"无评论"# 评分(从class中提取,如"star-5"→5分) star_div = item.find("div", class_="comment-star") score = star_div["class"][1].split("-")[1]if star_div else"0"# 用户名 user = item.find("div", class_="comment-user").text.strip()if item.find("div", class_="comment-user")else"匿名用户"# 评论时间 comment_time = item.find("span", class_="comment-time").text.strip()if item.find("span", class_="comment-time")else"未知时间"# 存入列表 all_comments.append({"用户名": user,"评分": score,"评论内容": content,"评论时间": comment_time })print(f"第{page}页爬取完成,新增{len(comment_items)}条评论,累计{len(all_comments)}条")except Exception as e:print(f"第{page}页爬取失败:{str(e)}")continue# 转换为DataFrame,方便后续处理 df = pd.DataFrame(all_comments)return df # 测试爬取if __name__ =="__main__": comment_df = crawl_jd_comments()# 保存为CSV(可选,方便查看原始数据) comment_df.to_csv("京东商品评论_原始数据.csv", index=False, encoding="utf-8-sig")print(f"\n爬取完成!共获取{len(comment_df)}条评论,原始数据已保存为CSV文件")

3. 关键配置修改(新手必看)

  1. 修改PRODUCT_ID:打开京东商品页,从URL中复制商品ID(比如https://item.jd.com/100012345678.html的ID是100012345678);
  2. 可选:添加Cookie:登录京东后,按F12→「Network」→任意请求→「Headers」→复制Cookie字段,粘贴到HEADERS中,可避免爬取页数受限;
  3. 运行代码:复制代码到编辑器(VS Code/PyCharm),点击运行,终端会输出爬取进度,完成后生成京东商品评论_原始数据.csv

三、第二步:数据清洗(让数据更干净)

爬取的原始数据可能有重复、空评论、特殊字符等“噪音”,需要清洗后再做分析,否则会影响结果准确性:

defclean_comments(df):"""数据清洗:去重、过滤无效评论、处理字段格式"""print("\n开始数据清洗...")# 1. 去重(根据“评论内容+用户名”去重,避免重复爬取) df_clean = df.drop_duplicates(subset=["评论内容","用户名"], keep="first")# 2. 过滤无效评论(空评论、评论长度<2字的无意义评论) df_clean = df_clean[df_clean["评论内容"].str.len()>=2]# 3. 处理评分格式(转换为整数类型) df_clean["评分"]= pd.to_numeric(df_clean["评分"], errors="coerce").fillna(0).astype(int)# 4. 过滤特殊字符(只保留中文、数字、字母,去除表情/符号) df_clean["评论内容"]= df_clean["评论内容"].str.replace(r"[^\u4e00-\u9fa5a-zA-Z0-9\s]","", regex=True)# 5. 重置索引 df_clean = df_clean.reset_index(drop=True)print(f"清洗完成!原始数据{len(df)}条,清洗后{len(df_clean)}条")return df_clean # 调用清洗函数(承接上一步的comment_df) df_clean = clean_comments(comment_df)# 保存清洗后的数据 df_clean.to_csv("京东商品评论_清洗后数据.csv", index=False, encoding="utf-8-sig")print("清洗后的数据已保存为CSV文件")

清洗效果对比

原始数据问题清洗后效果
重复评论、空评论已删除
评分是字符串(如"5")转换为整数(5)
评论含表情、特殊符号(如“👍”)只保留中文、数字、字母
无意义短评论(如“好”)保留(长度≥2字,有参考价值)

四、第三步:情感分析(给评论“打分”)

SnowNLP做中文情感分析,无需复杂训练,直接调用接口即可——它会给每条评论打一个0-1分的情感得分,越接近1表示越正面,越接近0表示越负面。

情感分析代码

from snownlp import SnowNLP defanalyze_sentiment(df):"""情感分析:给每条评论打分,分类正面/中性/负面"""print("\n开始情感分析...")# 定义情感得分计算函数defget_sentiment_score(text): s = SnowNLP(text)returnround(s.sentiments,3)# 保留3位小数# 给每条评论计算情感得分 df["情感得分"]= df["评论内容"].apply(get_sentiment_score)# 根据得分分类(自定义阈值,可调整)defclassify_sentiment(score):if score >=0.7:return"正面"elif score <=0.3:return"负面"else:return"中性" df["情感分类"]= df["情感得分"].apply(classify_sentiment)# 统计情感分布 sentiment_count = df["情感分类"].value_counts()print("\n情感分布统计:")print(sentiment_count)# 统计评分与情感分类的对应关系(验证准确性) score_sentiment = pd.crosstab(df["评分"], df["情感分类"])print("\n评分与情感分类对应关系:")print(score_sentiment)return df # 调用情感分析函数 df_with_sentiment = analyze_sentiment(df_clean)# 保存带情感分析结果的数据 df_with_sentiment.to_csv("京东商品评论_情感分析结果.csv", index=False, encoding="utf-8-sig")print("\n情感分析完成!结果已保存为CSV文件")

结果说明

  • 情感得分:0.98→强烈正面(如“续航超给力,颜值也高”);
  • 情感得分:0.12→强烈负面(如“质量差,用了2天就坏了”);
  • 情感得分:0.5→中性(如“中规中矩,符合预期”);
  • 验证逻辑:5分评论大概率是正面,1分评论大概率是负面,通过pd.crosstab可查看匹配度(一般准确率80%以上,新手足够用)。

五、第四步:词云生成(可视化关键词)

词云能直观展示用户评论中出现频率最高的关键词,比如“续航”“颜值”“质量”等,快速抓住用户关注的核心点。

词云生成代码(解决中文显示问题)

import jieba from wordcloud import WordCloud import matplotlib.pyplot as plt import numpy as np from PIL import Image defgenerate_wordcloud(df):"""生成词云图:分别生成正面、负面评论的词云"""print("\n开始生成词云图...")# ---------------------- 准备工作:定义停用词、字体路径 ----------------------# 停用词:过滤无意义词汇(如“的”“了”“我”,可根据需求添加) stopwords =set(["的","了","是","我","在","有","和","就","都","而","及","与","也","还","很","非常","比较","一下","这个","那个","什么","怎么","没有","可以","但是","因为","所以","如果","虽然","不过","其实"])# 字体路径(关键!解决中文显示乱码问题)# Windows:默认字体路径(无需修改) font_path ="C:/Windows/Fonts/simhei.ttf"# Mac:替换为以下路径(取消注释)# font_path = "/System/Library/Fonts/PingFang.ttc"# Linux:替换为系统中文字体路径(如"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc")# ------------------------------------------------------------------------# 1. 提取正面/负面评论的所有内容 positive_comments =" ".join(df[df["情感分类"]=="正面"]["评论内容"].tolist()) negative_comments =" ".join(df[df["情感分类"]=="负面"]["评论内容"].tolist())# 2. 中文分词(将句子拆分为关键词)defcut_words(text): words = jieba.lcut(text)# 精确分词# 过滤停用词和长度<2的词 filtered_words =[word for word in words if word notin stopwords andlen(word)>=2]return" ".join(filtered_words) positive_words = cut_words(positive_comments) negative_words = cut_words(negative_comments)# 3. 定义词云样式(可自定义颜色、形状)defcreate_wordcloud(words, title, save_path):# 可选:自定义词云形状(如圆形、心形,需要提前准备图片)# mask = np.array(Image.open("circle.png")) # 替换为图片路径 mask =None# 无形状(默认矩形) wc = WordCloud( font_path=font_path,# 中文字体 width=800, height=600,# 图片大小 background_color="white",# 背景色 max_words=200,# 最多显示关键词数 mask=mask,# 自定义形状(可选) colormap="viridis"# 颜色映射(可修改为"plasma"、"coolwarm"等)).generate(words)# 显示词云图 plt.figure(figsize=(10,6)) plt.imshow(wc, interpolation="bilinear") plt.axis("off")# 隐藏坐标轴 plt.title(title, fontsize=16, fontproperties=font_path) plt.tight_layout()# 保存词云图 wc.to_file(save_path)print(f"{title}词云已保存为:{save_path}")# 生成正面、负面评论词云 create_wordcloud(positive_words,"正面评论关键词词云","正面评论词云.png") create_wordcloud(negative_words,"负面评论关键词词云","负面评论词云.png")# 调用词云生成函数 generate_wordcloud(df_with_sentiment)

关键说明

  1. 字体路径:必须指定中文字体,否则词云会显示方块乱码,Windows/Mac/Linux的字体路径已标注,按需修改;
  2. 停用词:可根据实际评论添加更多无意义词汇(如“京东”“商品”“购买”等与评价无关的词);
  3. 自定义形状:准备一张白色背景的图片(如圆形、心形),替换mask参数的图片路径,即可生成对应形状的词云。

六、第五步:结果可视化(直观展示分析结论)

matplotlib绘制情感分布柱状图和评分分布饼图,让分析结果更直观:

defvisualize_results(df):"""结果可视化:情感分布柱状图、评分分布饼图"""print("\n开始生成可视化图表...")# 字体设置(解决中文显示问题) plt.rcParams['font.sans-serif']=['SimHei']# Windows:黑体# plt.rcParams['font.sans-serif'] = ['PingFang SC'] # Mac:苹方 plt.rcParams['axes.unicode_minus']=False# 解决负号显示问题# 1. 情感分布柱状图 plt.figure(figsize=(10,5)) sentiment_count = df["情感分类"].value_counts() bars = plt.bar(sentiment_count.index, sentiment_count.values, color=["#2E8B57","#FFD700","#DC143C"])# 在柱子上添加数值标签for bar in bars: height = bar.get_height() plt.text(bar.get_x()+ bar.get_width()/2., height +0.5,f"{int(height)}条", ha="center", va="bottom", fontsize=12) plt.title("商品评论情感分布", fontsize=16) plt.xlabel("情感分类", fontsize=12) plt.ylabel("评论数量", fontsize=12) plt.grid(axis="y", alpha=0.3) plt.savefig("情感分布柱状图.png", dpi=300, bbox_inches="tight")print("情感分布柱状图已保存")# 2. 评分分布饼图 plt.figure(figsize=(8,8)) score_count = df["评分"].value_counts().sort_index() colors =["#DC143C","#FF6347","#FFD700","#9ACD32","#2E8B57"] wedges, texts, autotexts = plt.pie( score_count.values, labels=[f"{score}分"for score in score_count.index], colors=colors, autopct="%1.1f%%",# 显示百分比(保留1位小数) startangle=90)# 美化文本for autotext in autotexts: autotext.set_color("white") autotext.set_fontsize(12) plt.title("商品评论评分分布", fontsize=16) plt.savefig("评分分布饼图.png", dpi=300, bbox_inches="tight")print("评分分布饼图已保存")# 调用可视化函数 visualize_results(df_with_sentiment)

七、最终成果展示

运行完所有代码后,你会得到以下文件:

  1. 数据文件:京东商品评论_原始数据.csv京东商品评论_清洗后数据.csv京东商品评论_情感分析结果.csv
  2. 可视化文件:正面评论词云.png负面评论词云.png情感分布柱状图.png评分分布饼图.png

示例成果:

  • 正面词云:高频词“续航给力”“颜值高”“手感好”→用户满意点;
  • 负面词云:高频词“发热”“续航短”“客服差”→产品待优化点;
  • 情感分布:正面85%、中性10%、负面5%→整体用户满意度高;
  • 评分分布:5分占78%、4分占15%→产品口碑较好。

八、新手避坑指南(我踩过的坑,你别再踩)

1. 爬取评论时中文乱码

  • 问题:终端/CSV文件中评论显示问号;
  • 解决方案:京东评论页编码是GBK,在response.encoding = "gbk",保存CSV时用encoding="utf-8-sig"

2. 词云显示方块乱码

  • 问题:词云只有形状,没有中文关键词(全是方块);
  • 解决方案:确保font_path指向正确的中文字体文件,Windows/Mac/Linux的路径已在代码中标注。

3. 情感分析结果不准

  • 问题:5分评论被判定为“中性”;
  • 解决方案:调整情感分类阈值(如将正面阈值从0.7降到0.6),或过滤无意义短评论(如“好”“不错”)。

4. 爬取页数受限

  • 问题:爬2-3页后就爬不到数据;
  • 解决方案:登录京东后复制Cookie到HEADERS中,或延长延迟时间(如time.sleep(random.uniform(1.5, 2.5)))。

5. 分词效果差(关键词拆分错误)

  • 问题:“续航给力”被拆分为“续航”“给力”(正确),“颜值高”被拆分为“颜值”“高”(正确);若拆分错误(如“性价比”拆分为“性”“价比”);
  • 解决方案:给jieba添加自定义词典,比如jieba.add_word("性价比"),提前定义专业词汇。

九、合规与伦理说明

  1. 本文爬虫仅用于个人学习、数据分析,不得用于商业用途或批量爬取京东数据,避免给平台服务器造成压力;
  2. 爬取的数据仅包含公开的用户评论,不得泄露用户隐私(如用户名、手机号等);
  3. 遵守《网络安全法》和京东用户协议,若平台明确禁止爬虫,需立即停止爬取行为。

十、进阶方向(爬完这一步,下一步学什么?)

  1. 爬取更多数据:扩展代码爬取多商品评论,做竞品对比分析;
  2. 情感分析升级:用更精准的模型(如BERT、LSTM)替换SnowNLP,提升情感识别准确率;
  3. 实时监控评论:添加定时任务(如Celery),每天自动爬取最新评论,监控产品口碑变化;
  4. 多维度分析:提取评论中的“价格敏感”“功能需求”等维度,做更细致的用户画像;
  5. 生成分析报告:用Python自动生成Word/Excel分析报告,包含数据表格、可视化图表和结论建议。

通过本文实战,你不仅学会了爬虫,还掌握了数据清洗、情感分析、可视化的完整流程——这套逻辑适用于任何电商平台(淘宝、天猫、拼多多),只要修改页面解析的CSS选择器和URL参数,就能快速适配新需求。现在就去试试爬取你关注的商品评论,看看用户到底在吐槽什么、好评什么吧!

Read more

告别“选择困难症”:我是如何用 AI Ping 实现大模型自由,还能省下 50% 成本的?

告别“选择困难症”:我是如何用 AI Ping 实现大模型自由,还能省下 50% 成本的?

告别“选择困难症”:我是如何用 AI Ping 实现大模型自由,还能省下 50% 成本的? * 写在最前面 * 场景一:从“写脚本卡壳”到“批量生成” * 场景二:开发路上的“万能插头” * 使用感受 * 一点小建议与期待 * 写在最后 🌈你好呀!我是 是Yu欸🚀 感谢你的陪伴与支持~ 欢迎添加文末好友🌌 在所有感兴趣的领域扩展知识,不定期掉落福利资讯(*^▽^*) 写在最前面 版权声明:本文为原创,遵循 CC 4.0 BY-SA 协议。转载请注明出处。 在这个大模型“百花齐放”甚至“百模大战”的时代,作为一名既要写代码开发,又要频繁输出技术内容(写博文、做视频)的开发者,我每天最大的烦恼就是: “今天这个任务,

By Ne0inhk
Ubuntu 虚拟机安装 OpenClaw

Ubuntu 虚拟机安装 OpenClaw

最近特别火的一个事是OpenClaw,个人AI助手工具,周末空闲,咱也对新技术尝尝鲜。 一、环境与前置准备 1.1虚拟机配置要求 配置项最低要求推荐配置CPU2 vCPU2-4 vCPU内存4 GB RAM8 GB RAM存储20 GB SSD40 GB+ SSD系统Ubuntu 22.04 LTSUbuntu 22.04/24.04 LTS网络公网访问(可选)稳定的外网连接 1.2 系统初始化和更新 更新系统软件包 sudo apt update && sudo apt upgrade -y 安装必要有工具 sudo apt install -y curl ca-certificates git

By Ne0inhk
Flutter 三方库 code_coverage 的鸿蒙化适配指南 - 掌握终端级覆盖率实时报告技术、助力鸿蒙应用构建敏捷且严密的测试反馈闭环

Flutter 三方库 code_coverage 的鸿蒙化适配指南 - 掌握终端级覆盖率实时报告技术、助力鸿蒙应用构建敏捷且严密的测试反馈闭环

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 code_coverage 的鸿蒙化适配指南 - 掌握终端级覆盖率实时报告技术、助力鸿蒙应用构建敏捷且严密的测试反馈闭环 前言 在 OpenHarmony 鸿蒙应用全场景流转与分布式特性日益复杂的背景下,测试代码的“有效性”比“数量”更为关键。虽然 flutter test --coverage 能够生成 LCOV 基础报告,但在追求敏捷开发的今天,开发者更需要一种能直接在终端(Terminal)快速扫描、精准点出“哪一行还没测”的轻量化反馈机制。code_coverage 作为一个专注于本地开发体验的覆盖率统计增强工具,旨在通过极简的命令行输出,瞬间揭示代码库的“透明度”。本文将详述其在鸿蒙端性能审计中的实战方法。 一、原原理分析 / 概念介绍 1.1 基础原理 code_

By Ne0inhk
[linux仓库]调试Segmentation fault的利器:手把手教你开启和使用Core Dump[进程信号·叁]

[linux仓库]调试Segmentation fault的利器:手把手教你开启和使用Core Dump[进程信号·叁]

🌟 各位看官好,我是! 🌍 Linux == Linux is not Unix ! 🚀 今天来学习Linux的core dump标志,理解core 和 term的区别。 👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享更多人哦! 目录 core dump 标志  Core vs Term 思考 总结 core dump 标志  在上一章节中,我们提到Core 和 Term 默认都是终止进程,只有在一些情况会出现区别: 信号有的是可以追踪的,有的是可以不被追踪的core dump表示不需要被追踪了 还记得这张图吗?当时我们在讲如果进程出现异常了,低7位表示退出信号,但是还有一位在那时并没有讲,而今天终于可以揭露这层面纱了. 先提出一个问题:如果我的进程出现异常了,我想不想知道是什么原因导致异常的?(像9号、2号这种信号就不需要,因为这是用户自己想退出的,因此默认行为是Term) 那肯定是想知道的,如

By Ne0inhk