全部
常见问题
产品动态
精选推荐
功能建议

已处理 待处理 {{opt.name}}
已处理 待处理
分析中 已回复 待规划 {{opt.name}}
分析中 已回复 待规划
商品评论与口碑分析:抓取商品详情评价数据,做情感分析与质量评估

管理 管理 编辑 删除

​

在电商场景里,商品详情页的评论区往往藏着比商品参数更真实的信息。用户会在这里吐槽物流、夸赞做工、抱怨色差,也会用一句话概括“值不值”。把这些评价数据抓下来,做情感分析和质量评估,就能把零散的口碑变成可量化的决策依据。

本文从工程落地角度出发,完整走一遍「抓取 → 清洗 → 情感分析 → 质量评估 → 可视化」的链路,代码以 Python 为主,尽量保证可以直接复制运行。

一、整体思路与技术选型

整个流程可以拆成四个阶段,每个阶段都有明确的输入输出,便于单独调试和替换。


flowchart TD
    A[商品详情页] --> B[评价数据抓取]
    B --> C[数据清洗与去重]
    C --> D[情感分析]
    C --> E[质量维度抽取]
    D --> F[口碑评分聚合]
    E --> F
    F --> G[可视化与结论]
阶段目标常用方案
抓取拿到评价文本、评分、时间、SKUrequests + 接口逆向,或 Playwright 渲染
清洗去重、去广告、过滤无效短评正则 + SimHash
情感分析判断正负面及强度SnowNLP 基线,或微调 BERT
质量评估按维度打分关键词规则 + 情感加权
提示:抓取前务必确认目标站点的 robots.txt 与服务条款,控制请求频率,只采集公开可见的评价内容,不要触碰用户隐私字段。

二、评价数据抓取

2.1 优先找评价接口

大多数电商详情页的评价是异步加载的,翻页时前端会请求一个 JSON 接口。打开浏览器开发者工具的 Network 面板,筛选 XHR,翻一页评价就能看到类似 comment/list?itemId=xxx&page=1 的请求。相比解析 HTML,直接请求接口更稳定。


import time
import random
import requests
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0 Safari/537.36"
),
"Referer": "https://example.com/",
}
def fetch_comments(item_id: str, max_page: int = 20):
"""按页抓取评价,返回原始 JSON 列表。"""
results = []
for page in range(1, max_page + 1):
params = {"itemId": item_id, "page": page, "pageSize": 20}
resp = requests.get(
"https://example.com/api/comment/list",
params=params,
headers=HEADERS,
timeout=10,
)
resp.raise_for_status()
data = resp.json()
comments = data.get("data", {}).get("comments", [])
if not comments:
break
results.extend(comments)
# 随机休眠,避免触发风控
time.sleep(random.uniform(1.0, 2.5))
return results

2.2 需要渲染时用 Playwright

如果评价内容由前端 JS 渲染且没有独立接口,可以用 Playwright 模拟滚动加载。


from playwright.sync_api import sync_playwright
def fetch_by_render(url: str, scroll_times: int = 10):
texts = []
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto(url, wait_until="networkidle")
for _ in range(scroll_times):
page.mouse.wheel(0, 2000)
page.wait_for_timeout(1200)
nodes = page.query_selector_all(".comment-item .content")
texts = [n.inner_text().strip() for n in nodes]
browser.close()
return texts

三、数据清洗与去重

原始评价里混着大量“此用户未填写评价”“系统默认好评”、表情符号和重复刷屏内容,直接送进模型会污染结果。


import re
import hashlib
DEFAULT_PATTERNS = [
r"此用户未填写评价",
r"系统默认好评",
r"^\s*$",
]
def clean_text(text: str) -> str:
text = re.sub(r"[\U00010000-\U0010ffff]", "", text)  # 去 emoji
text = re.sub(r"\s+", " ", text).strip()
return text
def is_valid(text: str, min_len: int = 5) -> bool:
if len(text) < min_len:
return False
return not any(re.search(p, text) for p in DEFAULT_PATTERNS)
def simhash(text: str, bits: int = 64) -> int:
"""简化版 SimHash,用于近似去重。"""
tokens = list(text)
v = [0] * bits
for token in tokens:
h = int(hashlib.md5(token.encode("utf-8")).hexdigest(), 16)
for i in range(bits):
v[i] += 1 if (h >> i) & 1 else -1
result = 0
for i in range(bits):
if v[i] > 0:
result |= 1 << i
return result
def dedup(texts, threshold: int = 3):
seen, kept = [], []
for t in texts:
h = simhash(t)
if all(bin(h ^ s).count("1") > threshold for s in seen):
seen.append(h)
kept.append(t)
return kept

四、情感分析

4.1 快速基线:SnowNLP

如果只是做趋势判断,SnowNLP 足够快,适合先跑通链路。


from snownlp import SnowNLP
def sentiment_score(text: str) -> float:
"""返回 0~1 的正面概率。"""
try:
return SnowNLP(text).sentiments
except Exception:
return 0.5
def label(score: float) -> str:
if score >= 0.6:
return "positive"
if score <= 0.4:
return "negative"
return "neutral"

4.2 更准的方案:微调中文 BERT

电商评论有大量口语和反讽,通用模型容易误判。用几千条标注数据微调一个中文预训练模型,效果通常有明显提升。


from transformers import (
    AutoTokenizer,
    AutoModelForSequenceClassification,
    Trainer,
    TrainingArguments,
)
model_name = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=3)
def encode(batch):
return tokenizer(
batch["text"],
truncation=True,
padding="max_length",
max_length=128,
)
dataset 需包含 text 与 label(0/1/2) 两列
train_ds = dataset.map(encode, batched=True)
args = TrainingArguments(output_dir="./out", num_train_epochs=3,
per_device_train_batch_size=16, learning_rate=2e-5)
trainer = Trainer(model=model, args=args, train_dataset=train_ds)
trainer.train()
实践建议:先用规则和 SnowNLP 跑一版,人工抽查 200 条,统计误判类型,再决定是否值得投入标注成本。

五、质量评估:从情感分到维度分

单纯的正负比例不足以说明商品质量。更实用的做法是把评价拆成若干维度,分别统计提及率和情感倾向。

维度关键词示例评估含义
做工做工、质感、毛边、缝隙制造工艺水平
外观色差、颜值、实物、图片与详情页描述一致性
物流发货、快递、包装、破损履约体验
性价比值、划算、贵、智商税价格感知
售后客服、退换、态度服务保障
from collections import defaultdict
DIMENSIONS = {
"做工": ["做工", "质感", "毛边", "缝隙", "开线"],
"外观": ["色差", "颜值", "实物", "图片", "颜色"],
"物流": ["发货", "快递", "包装", "破损", "物流"],
"性价比": ["值", "划算", "贵", "智商税", "价格"],
"售后": ["客服", "退换", "态度", "售后"],
}
def evaluate(comments):
stats = defaultdict(lambda: {"count": 0, "score_sum": 0.0})
for c in comments:
text = c["text"]
score = c["score"]
for dim, words in DIMENSIONS.items():
if any(w in text for w in words):
stats[dim]["count"] += 1
stats[dim]["score_sum"] += score
result = {}
total = len(comments) or 1
for dim, s in stats.items():
result[dim] = {
"提及率": round(s["count"] / total, 3),
"平均情感分": round(s["score_sum"] / s["count"], 3) if s["count"] else 0.0,
}
return result

5.1 综合口碑分

把各维度得分按提及率加权,再结合整体情感分布,得到一个 0~100 的口碑分,便于横向对比不同商品。


def reputation_score(dim_result: dict, overall_positive: float) -> float:
    if not dim_result:
        return round(overall_positive * 100, 1)
    weighted, weight_sum = 0.0, 0.0
    for dim, info in dim_result.items():
        w = info["提及率"]
        weighted += info["平均情感分"] * w
        weight_sum += w
    dim_score = weighted / weight_sum if weight_sum else overall_positive
    # 维度分占 70%,整体正面率占 30%
    return round((dim_score * 0.7 + overall_positive * 0.3) * 100, 1)

六、结果可视化

用 matplotlib 画一张维度雷达图,再配一张情感分布柱状图,基本能一眼看出问题集中在哪。


import matplotlib.pyplot as plt
import numpy as np
def plot_radar(dim_result: dict):
    dims = list(dim_result.keys())
    values = [dim_result[d]["平均情感分"] for d in dims]
    angles = np.linspace(0, 2 * np.pi, len(dims), endpoint=False).tolist()
    values += values[:1]
    angles += angles[:1]
    fig, ax = plt.subplots(figsize=(6, 6), subplot_kw={"polar": True})
    ax.plot(angles, values, linewidth=2)
    ax.fill(angles, values, alpha=0.25)
    ax.set_xticks(angles[:-1])
    ax.set_xticklabels(dims)
    ax.set_ylim(0, 1)
    plt.title("各维度情感得分")
    plt.tight_layout()
    plt.savefig("radar.png", dpi=150)

七、工程化注意事项

  • 增量抓取:按评价时间戳做增量,避免每次全量重跑。
  • 限流与重试:对 429/503 做指数退避,单域名并发控制在个位数。
  • 数据落库:评价文本、评分、时间、SKU 分开存,方便后续按维度聚合。
  • 模型版本管理:情感模型更新后,历史结果要能复现,建议记录模型版本号。
  • 合规:只采集公开评价,不存储用户昵称、头像等可识别信息。

八、总结

商品评论分析的价值不在于“抓了多少条”,而在于能否把非结构化文本转成可比较的指标。抓取阶段优先找接口,清洗阶段重点去重和过滤默认好评,情感分析先用轻量方案跑通再考虑微调模型,质量评估则要落到具体维度上,才能给选品、运营和售后提供真正可用的结论。

从工程角度看,这条链路的关键是可替换、可复现:每个阶段都保持清晰的输入输出,抓取层换站点、情感层换模型、评估层换维度权重,都不需要改动其他环节。建议先用小批量数据跑通全流程,验证指标合理后再逐步扩大采集规模,同时把模型版本、清洗规则和评分公式一并记录下来,方便后续对比和回溯。如有任何疑问,欢迎留言探讨!​


{{voteData.voteSum}} 人已参与
支持
反对
请登录后查看

+v 2467742810 最后编辑于2026-11-06 16:20:16

快捷回复
{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}
回复({{post_count}}) {{!is_user ? '我的回复' :'全部回复'}}
排序 默认正序 回复倒序 点赞倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理员 企业

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推荐': '推荐'}}
{{item.is_suggest == 1? '取消推荐': '推荐'}} 【已收集】
{{item.floor}}# 沙发 板凳 地板 {{item.floor}}# 【已收集】
{{item.user_info.title || '暂无简介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打赏
已打赏¥{{item.reward_price}}
{{item.like_count}}
分享
{{item.showReply ? '取消回复' : '回复'}}
删除
{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回复 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打赏
已打赏¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回复' : '回复'}}
删除
{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}
收起 展开更多
查看更多
打赏
已打赏¥{{reward_price}}
33
{{like_count}}
{{collect_count}}
添加回复 ({{post_count}})

相关推荐

{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}
问题:
问题自动获取的帖子内容,不准确时需要手动修改. [获取答案]
答案:
提交
bug 需求 取 消 确 定
打赏金额
当前余额:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
请输入 0.1-{{reward_max_price}} 范围内的数值
打赏成功
¥{{price}}
完成 确认打赏

微信登录/注册

{{ wechatLoginError }}
切换手机号登录

{{ bind_phone ? '绑定手机' : '手机登录'}}

{{codeText}}
切换微信登录/注册
暂不绑定
CRMEB客服
CRMEB咨询热线 400-8888-794

扫码领取产品资料

功能清单
思维导图
安装教程
CRMEB开源商城下载 源码下载 CRMEB帮助文档 帮助文档
返回顶部 返回顶部
CRMEB客服