止观
AI前沿观察

[F2]7万条买家评论扒出12个真需求:AI选品流水线

2026-09-25 · 电商 AI 实战 · 全文约 5600 字 · 阅读时间 14 分钟

先说一个我上周撞的墙。我想抓某东一条爆款商品的评论区,直接请求它的公开评论接口,返回的是一个很少见的状态码:444,响应体就一行字——The Request Forbidden。换浏览器 UA、加 Referer、降频,全是 444。换搜索引擎快照页,200 是 200,回来一个只有 209 字节的反爬验证壳。最后动用云爬虫服务,拿回来一句更干脆的:TARGET_BLOCKED_BY_RULE,目标 URL 被安全策略拦了。

评论区是选品人眼里最富的矿:买家愿意花三分钟写“哪里不满意”,等于免费给你做了一轮用户访谈。但矿门口都有保安。

这篇文章讲怎么绕开保安之后把活干完——从一份公开的真实电商评论数据集(7 万条,带 1-5 星评分)出发,走一遍我实际跑通的四级流水线:清洗 → 统计聚类 → 差评提升度 → LLM 需求归纳,最后模型真的给我吐出了 12 张“需求卡片”,每张带 lift 数据和逐字引用的差评原文。所有代码我都跑过,所有数字都是本机实测。

※ ※ ※

📋 先看全貌:四级流水线

层干什么7 万条数据上的实测结果
L1 清洗规则去水评:短句/默认好评/刷屏/返现广告淘汰 151 条(0.22%)
L1.5 分域图书类话术和实物类话术不是一套语言图书 ~1.2 万条单拆,实物 5.8 万条
L2 聚类jieba 分词 + LDA 主题模型,不预设标签让评论自己抱团10 个主题,最大堆 8729 篇
L3 提升度词在差评里的出现率 ÷ 全量出现率(lift)第一名:不值(lift=4.53)
L4 归纳把 L3 词表+原文证据喂给大模型,输出结构化需求卡片12 张卡,全带逐字引用

一句话:你不需要预先知道要找什么需求,统计层负责把“跟差评强相关的词”筛出来,大模型只负责把词翻译成人话。

四级流水线

※ ※ ※

🧱 第一级:清洗,以及一个反直觉的实测结论

拿到数据第一件事不是上模型,是把“没有信息量的评论”扔掉。刷单返现、“好评”两个字交差、啊啊啊啊刷屏,这些会污染后面所有统计。我的规则层不到 30 行:

def junk_reason(t):
    t = t.strip()
    if len(t) < 6: return "too_short"
    if re.fullmatch(r"(好+|不错+|可以|还行|很好|挺好的|一般|满意|喜欢|赞|顶|默认好评|"
                    r"好评)+[!!~。\.]*", t): return "default_praise"
    if len(set(t)) / max(len(t), 1) < 0.25: return "repeat_flood"   # 啊啊啊啊水贴
    if re.search(r"加微信|微信号|返利|返现|好评有礼|刮刮卡|抽奖|代购|点击链接|QQ群", t):
        return "ad_or_farming"                                       # 刷单/返现
    if len(t) > 2000: return "too_long"
    return None

五条规则,实测淘汰情况长这样:

原始: 70000 | 各规则剔除: {'repeat_flood': 104, 'default_praise': 20,
'ad_or_farming': 15, 'too_short': 11, 'too_long': 1}
清洗后: 69849 (淘汰 0.22%)

反直觉的地方在这:这批数据只有 0.22% 是明显的水评。 我原本以为规则会砍掉百分之几,结果平均评论长度 43 字,绝大多数人是真的写了字。但这不代表评论区干净——真正的水不是“不写”,是写了但没信息:“质量很好,物流很快,下次还来”,每个字都对,对你选品零贡献。这种评论规则层砍不动,得靠下一级用统计把它稀释掉。

还有一个必须做的动作:分域。这批数据里图书类评论约占六分之一,而图书用户的评价语言(“装帧”“译者”“正版”)跟实物商品(“做工”“续航”“按键”)完全是两套词表,混在一起做主题模型,模型会花一半容量去学“这是一本书”。用一条正则把它们拆开:

book_pat = re.compile(r"这本书|这套书|童书|绘本|读物|教材|教辅|出版社|考研|年级|正版|精装|装帧|丛书")
df["is_book"] = df["text"].str.contains(book_pat, regex=True)
# 图书 ~1.16 万条单拆 | 实物商品 ~5.8 万条

一句话:清洗层解决“假数据”,分域解决“串台数据”,都别指望模型替你兜底。

※ ※ ※

🔍 第二级:让评论自己抱团(LDA),但别迷信它

需求挖掘最容易掉进的坑:先拍一组标签(“性价比”“质量”“外观”),再去数每个标签出现几次。这是拿着手电筒找钥匙——你只会找到你预设要找的东西。

所以我用无监督主题模型 LDA:不告诉它有任何标签,让它根据词的共现关系自己把 5.8 万条实物评论聚成 10 堆。核心就三行:

vec = CountVectorizer(max_features=6000, min_df=15)   # 词表上限 6000,生僻词进不来
X = vec.fit_transform(corpus)                          # corpus = jieba 分词后的空格连接
lda = LatentDirichletAllocation(n_components=10, random_state=42,
                                max_iter=20, learning_method="online")
topics = lda.fit_transform(X)

跑完打印每个主题的顶层词,实测输出(截 6 个):

主题0 (7102篇): 还是 就是 不过 但是 没有 手机 味道 总体 ...
主题2 (7437篇): 质量 包装 很快 一般 速度 效果 纸张 内容 ...
主题4 (8729篇): 喜欢 值得 好书 推荐 印刷 一本 内容 收藏 ...
主题5 (4198篇): 性价比 已经 还行 容易 耳机 速度 ...
主题6 (4396篇): 方便 舒服 颜色 做工 外观 实惠 音质 ...
主题8 (5787篇): 问题 时间 好用 建议 大家 ...

看到问题了吗?主题词表里一半是“还是、不过、就是”这种语法词。LDA 没有骗人——这些词确实高度共现,它们标记的是转折句式簇(“东西还行,但是……”),而不是商品属性簇。换句话说:LDA 找到了“差评的句式”,但没找到“差评的原因”。 我保留了它做粗分堆和人工抽查(比如快速把“耳机音质不满”聚到主题 6),但真正的痛点定位,靠的是第三级。

一句话:主题模型适合探路,不适合出报告;能把话说清楚的是下一个指标。

※ ※ ※

📊 第三级:lift 提升度——本条流水线的灵魂

如果只允许我留一个统计概念进这篇文章,就是它。

lift(提升度)= 某个词在差评里的出现率 ÷ 这个词在全部评论里的出现率。 lift=2 的意思是:写了这个词的评论,出现在差评里的概率是普通评论的两倍。它回答的不是“什么词最常见”,而是“什么词最能区分差评和好评”——这俩问题的答案差别大到离谱。

完整实现不到 20 行:

df["neg"] = df["rating"] <= 3          # ≤3 星视为差评
N, NEG = len(df), df["neg"].sum()      # 全量 58250,差评 11201(19.2%)

def phrases(t):
    ws = [w for w in jieba.lcut(t) if len(w) >= 2 and not w.isdigit()]
    return set(ws) | {a + b for a, b in zip(ws, ws[1:])}  # 单词 + 相邻二字组合

all_c, neg_c = Counter(), Counter()
for _, r in df.iterrows():
    all_c.update(r["ph"])
    if r["neg"]: neg_c.update(r["ph"])

for p, cnt in all_c.items():
    if cnt < 120: continue             # 样本太小,系数不稳定
    lift = (neg_c[p] / NEG) / (cnt / N)

纯词频排行榜第一名是什么?“质量”——全量 5931 次、差评内 1138 次,lift 恰好 1.00:写了“质量”俩字的评论,是差评的概率和普通评论一模一样。更扎心的是“喜欢”(lift 0.40)、“好用”(0.39)、“速度”(0.66),这些高频词全是好评富集词。真正有区分度的是另一张榜(我把“没有/不是/一般”这类纯语法词剔掉后):

痛点词全量出现差评内出现lift
不值1471284.53
很差 / 太差192 / 165157 / 1354.25
退货3032434.17
垃圾2672144.17
盗版3902993.99
怀疑2021503.86
一般般3762693.72
根本2872043.70
失望8305643.53

三个信息密度极高的发现,都是词频排行永远给不出来的:

  1. “不值”的 lift 比“垃圾”还高。 骂垃圾是情绪,喊不值是账算明白了——后者对选品的杀伤力更大:它意味着同价位有替代品。
  2. “退货”lift=4.17。 写这两个字的人不是抱怨,是已经在行动。评论里的“退货”应该做退货率的前置预警指标。
  3. 语法词的 lift 陷阱。 “一般”lift=2.96、“失望”3.53,这些情绪词区分度很高但没有产品含义。第一遍我天真地把 lift 榜直接贴给了运营同事,换来一句“所以呢?”——统计层的终点是“哪些词跟差评有关”,不是“差评为什么”。 后者需要第四级。
词频 vs lift

※ ※ ※

🤖 第四级:LLM 归纳——把 lift 榜翻译成需求卡片

现在轮到语言模型出场,但注意顺序:证据先由统计层固化,模型只做归纳和翻译。这个顺序反过来(让模型直接读 7 万条评论“总结用户需求”)就是烧钱许愿。

喂给模型的 prompt 模板(脱敏后原样):

你在帮一个电商选品团队读评论。以下是 {N} 条真实商品评论的统计层输出。

一、差评强相关词表(lift=该词在差评中的出现率÷全量出现率,>1.6 即显著):
{phrase  total  neg  lift 表,取 TOP30}

二、这些词所在的差评原文片段(每条截 90 字):
{每个词抽 2 条真实差评,带词标签}

任务:把它们归纳成不超过 12 条"真需求"。要求:
1. 每条需求给:name(≤8字的人话标签)、evidence(支撑词的lift数据)、
   quote(一条最能代表该需求的原文摘录,逐字引用)、
   insight(一句话:这条需求指向什么产品机会或卖点)。
2. 只从数据出发,不许编造词表里没有的证据。
3. 输出严格 JSON:{"needs":[{"name":"","evidence":"","quote":"","insight":""}]}

关键设计三个:给模型划定证据边界(“不许编造词表里没有的证据”)、强制逐字引用(quote 字段让每条结论可回溯到原文)、限制数量上限(12 条,逼它合并同类项而不是堆砌)。一次调用、几分钱,实测输出:

{
 "needs": [
  {"name": "规格真实一致",
   "evidence": "完全(lift=2.07), 正常(lift=1.61)",
   "quote": "根本没有16G 现在的东西也太假了,说是16G,但连12G的3D电影都装不下",
   "insight": "虚标参数引发强烈不信任,需在详情页展示实测数据或第三方认证,杜绝货不对板"},
  {"name": "配件完整齐全",
   "evidence": "打开(lift=2.16), 几个(lift=1.63)",
   "quote": "东西很快到了,但是打开失望发现没有网线,一根网线没几个钱,但是出去买很费神!",
   "insight": "缺失基础配件虽成本低但极大增加用户隐形成本,承诺'全套标配'可消除购买顾虑"},
  {"name": "售后响应高效",
   "evidence": "要求(lift=1.60), 一个月(lift=2.40)",
   "quote": "手机4分,售后-4分,综合0,打不了0分给一分",
   "insight": "产品小瑕疵可容忍,但售后流程繁琐会彻底摧毁口碑"},
  ...共 12 张卡片
 ]
}

“手机 4 分,售后 -4 分,综合 0”这种句子,你自己蹲在电脑前想破头也不会写成需求,但买家替你写好了。这就是评论区值钱的原因。

一句话:统计层负责“是什么”,大模型负责“意味着什么”,两边的账各归各。

※ ※ ※

🔁 交叉验证:这套方法在另一个类目能复现吗

判断一个方法是管道还是运气,标准动作是换个输入再跑一遍。我把同一条流水线(关键词版:因为拖鞋品类有现成的商品标题数据)打在另一个类目的采集数据上——家居拖鞋,7 个搜索关键词、255 条商品标题、231 个价格样本加百度收录的用户讨论:

  • ▪ 需求标签提及率前三:防滑 24%、EVA 材质 19%、情侣/男女同款 20%;
  • ▪ 价格带中位数 33.9 元,20-40 元被挤成黄金带;
  • ▪ 差评侧语言:“毛绒棉拖易吸汗藏菌,建议拆洗内衬”→ 指向“可拆洗内胆”的产品机会;“浴室地面常年湿滑”→ 防滑是场景刚需不是卖点。

两个类目、两套数据、同一个结论骨架:高频词告诉你市场在卖什么承诺,高 lift 词告诉你市场在违约什么承诺,需求藏在违约里。 拖鞋这个例子里没有大模型参与也能得出结论,但归纳环节交给 LLM 后,从词表到需求卡片的时间从“一个下午”压缩到“一杯咖啡”。

※ ※ ※

⚠️ 这条流水线的五个坑

按踩坑顺序排:

  1. 编码坑:老评论数据的 CSV 是 GBK 编码的,pandas 直接读会乱码报错,encoding='gb18030' 先试;从网页抓的混合数据要先 rb 读进来再 errors='replace' 解码,否则一颗坏字节炸掉整个文件。
  2. jieba 坑:评论列里混进 NaN 时 jieba 抛的是 'float' object has no attribute 'decode',报错信息跟真实原因隔着十万八千里。进分词器之前先 astype(str),一行代码省一小时 debug。
  3. 小样本系数坑:一个词全量只出现 5 次、差评里出现 2 次,lift 高达 2 以上——纯噪声。cnt < 120 直接不进榜。
  4. 语法词坑:lift 榜天然会奖励“失望”“根本”“退货”这类情绪/行为词,产品词(“续航”“按键”“异味”)反而排不上来。两个解法并用:手工维护语法词黑名单(我的表里塞了 102 个),以及做“单词+相邻二字组合”的短语级统计,让“电池不耐”这种组合浮出来。
  5. LLM 越权坑:模型会把 quote 里的原文“顺手润色”成更通顺的版本。对策是在 prompt 里写死“逐字引用”,拿到输出后跑一遍校验:quote 必须能在原数据里 in 命中,命不中的卡片整条丢弃重来。这一条不做,你的需求报告里就会混进 AI 幻觉出来的“用户原话”,而且最难被发现。

※ ※ ※

👥 三类人各取所需

  • ▪ 做选品的:lift 表就是你的反向卖点清单。别在详情页写你的卖点,去修你的差评词。“不值”排第一的品,降价不如加配件(对照“配件完整齐全”那张卡)。
  • ▪ 做运营的:把“退货”类关键词做成周报指标,lift 榜每月用最新数据重跑一次——痛点的排名是会漂移的。
  • ▪ 做 agent 工程化的:注意这条流水线的分层方式。LLM 只在最后一层出场,前三层全是 20 行以内的确定性 Python。统计固化证据、模型翻译人话,这个结构对任何“从非结构化文本到决策建议”的任务都成立,换个数据源今天就能复用。

※ ※ ※

结尾

选品这件事,本质上没人缺数据,缺的是把数据变成“人话需求”的传送带。传送带搭一次就够:L1 清洗 15 行,L3 lift 15 行,L4 prompt 一张模板,中间层想换模型换模型、想换分词换分词,两头接口不动。

下一篇聊一个更扎心的话题:这个月开源模型扎堆上新,为什么你一个新模型都没真正用起来? 放量不等于能用,我会按部署门槛、上下文长度、许可协议三条硬杠过一遍筛子,只留这个月真能上手的那几个。

评论区想听听:你在自己类目的评论区里,见过最“一句话点醒产品”的评价是什么?

如果这篇对你有用,点个“在看”或者转给正在为选品掉头发的朋友,下期见。

※ ※ ※

资料来源

- 评论数据集:HuggingFace 公开数据集(镜像下载,7 万条真实中文电商评论,含 1-5 星评分);本文明细统计(清洗淘汰 151 条、实物 58,250 条、差评 11,201 条/19.2%、lift 榜、LDA 主题数、LLM 需求卡 12 张)均为本机实测输出,环境为单台 3.6GB 内存云服务器,Python 3.11 + pandas + jieba + scikit-learn。

- 接口探测实测:某东公开评论接口对数据中心 IP 返回 444 The Request Forbidden;什么值得买搜索页返回反爬验证壳;商业云爬虫 API 返回 TARGET_BLOCKED_BY_RULE。均为 2026 年 9 月实测。

- 拖鞋类目交叉验证数据:2026 年 8 月采集(smzdm 搜索页 255 条商品标题 + 231 价格样本 + 搜索引擎收录的用户讨论),品牌与店铺信息已按惯例脱敏。

- LLM 归纳层:qwen 系模型(Anthropic 兼容接口,关闭 thinking),prompt 全文见正文代码块。

- 文中出现的商品评论引文均来自公开数据集语料,仅用于方法演示,不指向任何在售商品;所有示例场景均不含作者真实业务数据。

评论 (0)