1. 项目概述与核心价值
京东作为国内头部电商平台,每天产生数百万条商品评论数据。这些数据蕴含着消费者真实反馈、产品优缺点和市场趋势等宝贵信息。通过Python技术栈对这些评论数据进行采集、清洗、分析和可视化呈现,可以帮助我们:
- 发现热销商品的用户关注焦点(如手机品类中的"拍照效果"、"续航能力"等高频关键词)
- 识别产品改进方向(通过负面评论的情感分析)
- 监测市场趋势(不同时间段评论热词的变化)
- 辅助选品决策(对比竞品的用户评价维度)
这个项目完整覆盖了从数据获取到最终可视化的全流程,特别适合想要学习电商数据分析实战的Python开发者。下面我将分享具体实现方案中几个关键环节的技术细节和避坑经验。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据采集方案设计
2.1 京东评论接口分析
京东商品评论数据主要通过其开放接口获取。经过实测分析,主要涉及以下接口:
python复制# 获取评论总数接口
'https://club.jd.com/comment/productCommentSummaries.action?referenceIds={商品ID}'
# 分页获取评论详情接口
'https://club.jd.com/comment/productPageComments.action?productId={商品ID}&score=0&sortType=5&page={页码}&pageSize=10'
重要提示:请求时需要添加合法的headers信息,特别是User-Agent和Referer字段,否则会返回403错误。建议使用真实浏览器访问后复制完整的headers信息。
2.2 反爬应对策略
京东对爬虫有较严格的防护措施,需要特别注意:
- 请求频率控制:实测建议单次采集间隔不低于3秒,可使用
time.sleep(random.uniform(3,5))增加随机性 - IP代理池:建议使用付费代理服务,免费代理的可用性较差
- Cookie更新:连续采集2小时后需要更换Cookie
- 异常处理:对HTTP 403/503等状态码要有重试机制
python复制# 典型请求示例
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...',
'Referer': 'https://item.jd.com/100038187793.html'
}
def get_comments(product_id, page):
url = f'https://club.jd.com/comment/productPageComments.action?productId={product_id}&page={page}'
try:
resp = requests.get(url, headers=headers, timeout=10)
if resp.status_code == 200:
return resp.json()
else:
print(f'请求异常:{resp.status_code}')
return None
except Exception as e:
print(f'请求失败:{str(e)}')
return None
3. 数据清洗与预处理
3.1 原始数据结构解析
京东返回的评论数据是嵌套的JSON格式,主要包含以下字段:
json复制{
"comments": [
{
"content": "手机拍照效果很好,但电池续航一般",
"creationTime": "2023-07-15 10:20:33",
"score": 4,
"usefulVoteCount": 12,
"userLevelName": "金牌会员",
"productColor": "黑色",
"productSize": "8GB+256GB"
}
]
}
3.2 关键清洗步骤
- HTML标签去除:评论内容中可能包含
<br>等HTML标签 - 特殊字符处理:表情符号、特殊空白字符等
- 无效评论过滤:如"此用户未填写评价内容"等默认评论
- 属性标准化:将"很好"、"不错"等描述转化为统一标准
python复制import re
import jieba
def clean_content(text):
# 去除HTML标签
text = re.sub(r'<[^>]+>', '', text)
# 去除特殊字符
text = re.sub(r'[\u200b-\u200f\u202a-\u202e]', '', text)
# 去除连续空格
text = re.sub(r'\s+', ' ', text).strip()
return text
def preprocess_data(comment):
# 情感分数映射
score_map = {1: '差评', 2: '中评', 3-5: '好评'}
return {
'content': clean_content(comment['content']),
'sentiment': score_map.get(comment['score'], '未知'),
'date': comment['creationTime'].split()[0],
'useful': comment['usefulVoteCount'],
'user_level': comment['userLevelName'],
'product_spec': f"{comment.get('productColor','')}/{comment.get('productSize','')}"
}
4. 数据分析核心方法
4.1 评论情感分析
使用SnowNLP库进行情感值计算(0-1之间,越接近1表示越积极):
python复制from snownlp import SnowNLP
def analyze_sentiment(text):
try:
return SnowNLP(text).sentiments
except:
return 0.5 # 默认中性
# 应用示例
df['sentiment_score'] = df['content'].apply(analyze_sentiment)
df['sentiment_label'] = pd.cut(df['sentiment_score'],
bins=[0,0.3,0.7,1],
labels=['负面','中性','正面'])
4.2 关键词提取与词云生成
使用jieba进行分词和关键词提取:
python复制from wordcloud import WordCloud
import matplotlib.pyplot as plt
# 合并所有评论内容
all_text = ' '.join(df['content'].tolist())
# 加载停用词表
stopwords = set(line.strip() for line in open('stopwords.txt', encoding='utf-8'))
# 生成词云
wordcloud = WordCloud(
font_path='simhei.ttf',
background_color='white',
max_words=100,
stopwords=stopwords,
width=800,
height=600
).generate(all_text)
plt.figure(figsize=(12,8))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()
4.3 时间趋势分析
python复制# 按日统计评论量和平均情感分
daily_stats = df.groupby('date').agg({
'content': 'count',
'sentiment_score': 'mean'
}).rename(columns={'content': 'comment_count'})
# 绘制双轴图
fig, ax1 = plt.subplots(figsize=(12,6))
color = 'tab:red'
ax1.set_xlabel('日期')
ax1.set_ylabel('评论量', color=color)
ax1.plot(daily_stats.index, daily_stats['comment_count'], color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx()
color = 'tab:blue'
ax2.set_ylabel('情感分', color=color)
ax2.plot(daily_stats.index, daily_stats['sentiment_score'], color=color)
ax2.tick_params(axis='y', labelcolor=color)
plt.title('评论量与情感分时间趋势')
plt.show()
5. 可视化方案实现
5.1 使用Pyecharts构建交互式图表
安装依赖:
bash复制pip install pyecharts
5.1.1 情感分布饼图
python复制from pyecharts import options as opts
from pyecharts.charts import Pie
sentiment_dist = df['sentiment_label'].value_counts()
pie = (
Pie()
.add("", [list(z) for z in zip(sentiment_dist.index, sentiment_dist.values)])
.set_global_opts(title_opts=opts.TitleOpts(title="评论情感分布"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c} ({d}%)"))
)
pie.render("sentiment_pie.html")
5.1.2 用户等级-情感分布热力图
python复制from pyecharts.charts import HeatMap
cross_tab = pd.crosstab(df['user_level'], df['sentiment_label'])
heatmap = (
HeatMap()
.add_xaxis(cross_tab.columns.tolist())
.add_yaxis(
"",
cross_tab.index.tolist(),
cross_tab.values.tolist(),
label_opts=opts.LabelOpts(is_show=False),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="用户等级-情感分布"),
visualmap_opts=opts.VisualMapOpts(max_=cross_tab.values.max()),
)
)
heatmap.render("heatmap.html")
5.2 使用Plotly实现动态可视化
python复制import plotly.express as px
# 产品规格-情感分布箱线图
fig = px.box(df, x='product_spec', y='sentiment_score',
title='不同规格产品情感分分布')
fig.show()
# 评论时间分布热力图
df['hour'] = pd.to_datetime(df['creationTime']).dt.hour
hourly_counts = df.groupby(['date', 'hour']).size().reset_index(name='counts')
fig = px.density_heatmap(hourly_counts, x='hour', y='date', z='counts',
title='评论时间分布热力图')
fig.show()
6. 项目优化与扩展方向
6.1 性能优化建议
-
数据采集阶段:
- 使用异步请求(aiohttp)提升采集效率
- 实现断点续采功能
- 将采集到的数据实时存入MongoDB
-
数据分析阶段:
- 对大型数据集使用Dask替代Pandas
- 将情感分析模型替换为更精确的BERT模型
- 使用Redis缓存中间结果
6.2 分析维度扩展
-
竞品对比分析:
- 采集同类商品评论数据
- 对比各品牌的情感分、关键词分布等指标
-
用户画像构建:
- 结合用户等级、购买时间等维度
- 识别高价值用户群体特征
-
异常检测:
- 识别可能的刷评行为(如短时间内大量相似评论)
- 检测水军评论特征
6.3 部署与应用
-
自动化报表系统:
- 使用Airflow设置定时任务
- 自动生成日报/周报并发送邮件
-
交互式看板:
- 使用Dash/Streamlit构建Web看板
- 支持筛选不同时间范围、商品类别等维度
python复制# Streamlit示例
import streamlit as st
st.title('京东评论分析看板')
date_range = st.date_input("选择日期范围", [])
if date_range:
filtered_df = df[(df['date'] >= str(date_range[0])) &
(df['date'] <= str(date_range[1]))]
st.write(f"共{len(filtered_df)}条评论")
st.plotly_chart(px.pie(filtered_df, names='sentiment_label',
title='情感分布'))
7. 常见问题与解决方案
7.1 数据采集相关问题
Q1:请求频繁被封IP怎么办?
- 解决方案:使用代理IP轮换,建议使用付费代理服务如芝麻代理,配合以下设置:
python复制proxies = { 'http': 'http://username:password@proxy_ip:port', 'https': 'http://username:password@proxy_ip:port' } resp = requests.get(url, headers=headers, proxies=proxies, timeout=10)
Q2:获取的评论数据不全?
- 可能原因:京东默认只返回前100页评论
- 解决方案:通过多维度采集(按好评/中评/差评分别采集)
7.2 数据分析相关问题
Q1:情感分析准确度不高?
- 改进方案:
- 使用领域词典增强SnowNLP:
python复制from snownlp import sentiment sentiment.load('mobile_review.txt') # 自定义手机领域词典- 改用预训练模型:
python复制from transformers import pipeline classifier = pipeline('sentiment-analysis', model='uer/roberta-base-finetuned-jd-binary-chinese')
Q2:关键词提取出现大量无意义词?
- 改进方案:
- 扩充停用词表(包含"京东"、"快递"等电商场景常见词)
- 使用TF-IDF算法提取关键词:
python复制from sklearn.feature_extraction.text import TfidfVectorizer tfidf = TfidfVectorizer(max_features=50, stop_words=stopwords) tfidf_matrix = tfidf.fit_transform(df['content'])
7.3 可视化相关问题
Q1:Pyecharts图表显示不正常?
- 检查步骤:
- 确保render()方法指定了完整路径
- 浏览器控制台查看是否有JS加载错误
- 尝试升级Pyecharts版本
Q2:Plotly图表在Jupyter中不显示?
- 解决方案:
python复制import plotly.io as pio pio.renderers.default = 'notebook' # 或'jupyterlab'
8. 实战经验分享
8.1 数据采集中的坑
-
Cookie有效期问题:京东Cookie通常2-3小时失效,建议:
- 监控采集成功率,低于90%时自动更新Cookie
- 准备多个账号的Cookie轮换使用
-
商品ID获取技巧:直接从商品详情页URL中提取:
code复制https://item.jd.com/100038187793.html → 商品ID为100038187793
8.2 分析效率提升技巧
-
使用向量化操作:避免对DataFrame逐行操作
python复制# 不推荐 df['sentiment'] = df['content'].apply(lambda x: SnowNLP(x).sentiments) # 推荐 texts = df['content'].tolist() sentiments = [SnowNLP(text).sentiments for text in texts] df['sentiment'] = sentiments -
并行计算加速:
python复制from multiprocessing import Pool def process_text(text): return SnowNLP(text).sentiments with Pool(4) as p: df['sentiment'] = p.map(process_text, df['content'])
8.3 可视化设计心得
-
颜色选择原则:
- 情感分析:负面用红色系,中性用黄色系,正面用绿色系
- 时间趋势:使用渐变色表示强度变化
-
交互设计技巧:
- 在Pyecharts中添加数据缩放功能:
python复制.set_global_opts( datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")] )- 在Plotly中添加悬停信息:
python复制fig.update_traces(hovertemplate="日期: %{x}<br>数量: %{y}")
9. 完整项目结构建议
code复制jd_comment_analysis/
├── data/ # 数据存储
│ ├── raw/ # 原始JSON数据
│ └── processed/ # 清洗后的CSV数据
├── docs/ # 文档
├── notebooks/ # Jupyter笔记本
│ ├── 1_data_collection.ipynb
│ ├── 2_data_cleaning.ipynb
│ └── 3_analysis_visualization.ipynb
├── src/
│ ├── crawler/ # 爬虫代码
│ │ ├── jd_crawler.py
│ │ └── proxy_pool.py
│ ├── analysis/ # 分析代码
│ │ ├── sentiment.py
│ │ └── keywords.py
│ └── visualization/ # 可视化代码
│ ├── pyecharts/
│ └── plotly/
├── config.py # 配置文件
└── requirements.txt # 依赖列表
10. 环境配置与依赖管理
推荐使用conda创建独立环境:
bash复制conda create -n jd_analysis python=3.8
conda activate jd_analysis
# 安装核心依赖
pip install requests pandas jieba snownlp pyecharts plotly
# 开发工具
pip install jupyterlab matplotlib
对于大型数据集分析,建议额外安装:
bash复制pip install dask[dataframe] scikit-learn
11. 法律与伦理注意事项
-
数据使用规范:
- 仅将数据用于个人学习与研究
- 不存储用户敏感信息(如用户名、联系方式等)
- 不将原始数据公开传播
-
采集频率控制:
- 单商品采集间隔不低于3秒
- 每日采集量控制在合理范围(建议不超过1万条/天)
-
反爬规避界限:
- 不使用自动化工具注册账号
- 不绕过网站的正常访问限制
在实际项目中,建议先查阅京东的robots.txt文件,了解其允许的爬取范围。对于商业用途的数据需求,应当通过官方API渠道获取授权。
