ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

用Python分析电商评论:从爬虫到情感分析,教你选出最受欢迎的黑丝

用Python分析电商评论:从爬虫到情感分析,教你选出最受欢迎的黑丝 前几天一个朋友问我“用Python能不能分析出哪款黑丝好看”我刚开始以为他在开玩笑但仔细琢磨了一下这其实就是一个标准的Python数据分析项目。把“哪款更好看”这种主观判断转化成评论区高频词、情感得分和款式差异的客观统计本质上跟爬电影评论做口碑分析、抓微博热搜做情绪监控是同一套思路。用Python去解决这种带点“人情世故”的难题反而特别有意思。这篇文章我就把这个项目的完整过程拆开讲从数据采集、清洗、分词、情感分析到最终可视化每一步都给出可直接复制的思路和代码。如果你是Python初学者可以把它当成一个综合练习如果你已经有基础这里面关于爬虫稳定性、中文分词细节、情感分析误判的坑也值得扫一眼。项目做完之后你不仅能给朋友一个有理有据的选购建议还能把爬虫、数据分析、可视化的流程完整走一遍。1. 先把这个“送命题”拆成技术题1.1 为什么是Python为什么是评论区给女朋友挑一件穿搭单品最大的难点在哪里答案不是“挑哪个”而是“我根本不知道她喜欢什么”。这时候有个很朴素的思路去电商平台翻评论区看看买过的人怎么说。但问题是一款黑丝的评论动辄几千上万条人工一条条看下去眼睛花了也总结不出规律。Python在干这种活的时候优势太明显了。它能批量抓取评论数据能对文本自动分词能计算每条评论的情感倾向最后还能把结果画成图。这套流程听起来复杂但拆开之后每一个环节都有现成的库可以用requests负责抓页面BeautifulSoup负责解析HTMLpandas负责清洗数据jieba负责中文分词SnowNLP负责情感分析matplotlib和wordcloud负责画图。整套技术栈全部开源免费而且网上资料极多跑不通的时候随便一搜就有答案。选Python还有一个隐形的理由这件事本身带有试错性质。数据抓不全、评论文本乱、情感分析不准这些都是预期内的问题Python的交互式开发方式Jupyter Notebook或者直接在终端里跑脚本能让你每一步都看到中间结果调起来非常顺手。用别的语言不是不行但在这个场景下Python就是那个让你最快拿到结论的工具。1.2 整体流程和工具链这个项目的技术路线可以分成四段数据采集从某电商平台抓取黑丝商品的评论数据包括评论内容、评分、款式/颜色信息、购买时间等。数据清洗去重、去缺失、过滤无效评论把字段整理成结构化表格。文本分析对评论文本做中文分词统计高频关键词再用情感分析给每条评论打分判断正面还是负面。可视化与结论用词云展示大家关心的关键词用柱状图/雷达图对比不同款式的综合表现最终输出选购建议。关于环境我建议直接用Anaconda安装Python 3.9以上版本然后一次性装好依赖库pip install requests beautifulsoup4 pandas jieba snownlp matplotlib wordcloud这里有个小提醒如果你用的是macOS或者Linuxwordcloud和snownlp这种库偶尔会碰到编译问题。遇到这种情况优先用conda安装而不是pip因为conda的预编译包会更齐全。Windows用户一般直接pip就能搞定。做这个项目之前我先把话放这儿爬虫只是工具抓取数据时一定要尊重对方网站的规则控制请求频率不要高频爬取更不要用于商业用途。咱们做的是个人学习项目这一点心里要有数。2. 数据采集评论才是真正的“群众意见”2.1 确定采集对象与字段在设计爬虫之前得先想清楚两个问题抓什么数据抓多少数据。我当时选品类的思路是搜索“黑丝连裤袜”按销量排序取前56款正好是一个翻页周期然后逐款抓取它们的评论。这样能保证数据覆盖不同价位、不同材质、不同品牌的商品样本足够多元。评论数据里需要保留的核心字段有这些商品ID和商品标题用来区分是哪一款评论内容这是分析的主体评分如果有用于情感分析的交叉验证颜色/尺码信息很多评论会附带购买的具体SKU这个信息极有用能帮你分析“哪个颜色更受欢迎”评论时间用来观察是否存在刷评集中爆发的情况字段设计的时候要留点富余宁可先多存几列也别后面分析到一半发现少抓了某个字段再回头补。2.2 写爬虫时最容易翻车的几个点爬虫的主体代码并不复杂核心就三步发请求、解析页面、提取字段。但实际跑起来你大概率会遇到下面几个问题我先提前踩一遍坑。第一个坑是请求头。很多平台的页面如果识别出你是爬虫会直接拒绝访问或者返回验证码页面。解决方法是伪装User-Agent最好再加一个Referer。正常情况下这样就能通过大部分基础校验。第二个坑是动态加载。现在很多电商平台的评论数据不是直接写在HTML里的而是通过异步接口加载的。如果是这种情况直接requests拿到的页面里根本没有评论信息需要打开开发者工具F12看Network面板找到返回评论数据的JSON接口直接请求那个接口。这一步是很多新手最容易卡住的地方。第三个坑是请求频率。千万别写个for循环一口气发几百个请求不然你的IP很快就会被封掉。正确做法是在每次请求之间加随机延时时间控制在1到3秒之间比较合适。下面是我当时使用的一个通用抓取模板用BeautifulSoup解析静态HTMLimport requests import time import random from bs4 import BeautifulSoup headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Referer: https://www.example.com/, } def fetch_comments(list_url, max_pages10): comments [] for page in range(max_pages): url list_url.format(pagepage) try: resp requests.get(url, headersheaders, timeout10) if resp.status_code ! 200: print(f第{page}页返回异常: {resp.status_code}) continue soup BeautifulSoup(resp.text, html.parser) items soup.select(.comment-item) for item in items: text_node item.select_one(.comment-content) if text_node: comments.append(text_node.get_text(stripTrue)) print(f第{page}页抓到 {len(items)} 条评论) except Exception as e: print(f第{page}页出错: {e}) time.sleep(random.uniform(1, 3)) return comments注意这里的.comment-item和.comment-content是CSS选择器实际使用时要根据目标平台的HTML结构调整。我的建议是先抓一页下来打印出HTML结构确认评论在哪个标签里面再写选择器。不要上来就盲写选择器否则大概率一个也抓不到。抓下来的数据建议直接存成CSV方便后面用pandas读取import csv def save_to_csv(comment_list, filename): with open(filename, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([comment]) for c in comment_list: writer.writerow([c])关于编码问题我要多说一句写CSV的时候encoding参数最好用utf-8-sig而不是utf-8。这个细节坑了很多人用前者存出来的文件在Excel里打开中文不会乱码。2.3 异步接口数据的处理技巧如果你打开页面发现评论不在HTML源码里就得改用接口爬取。这类接口通常返回JSON格式数据解析起来反而更简单import requests import json import time import random def fetch_api_comments(api_url_template, max_pages10): comments [] for page in range(max_pages): url api_url_template.format(pagepage) try: resp requests.get(url, headersheaders, timeout10) data resp.json() # 具体字段名需要看你抓到的JSON结构 items data.get(data, {}).get(comments, []) for item in items: comments.append(item.get(content, )) except Exception as e: print(f接口第{page}页出错: {e}) time.sleep(random.uniform(1, 3)) return comments用接口有个好处是数据结构很规整字段名直接对应业务含义。但缺点是很多接口有签名校验需要在代码里处理加密参数。这种时候我的建议是不要死磕逆向换一个思路用Selenium这种浏览器自动化工具模拟真人滚动页面来加载评论。虽然速度慢一点但胜在稳定而且不用费劲去逆向加密逻辑。对个人项目来说稳定比速度重要得多。3. 数据分析把“好看”变成可量化的指标3.1 数据清洗与归类数据抓回来之后先别急着分析评论数据里到处都是“脏数据”。常见的问题有重复评论、纯表情评论、无意义的“此用户未填写评价内容”、广告导流内容等等。这些都要先过滤掉。import pandas as pd import re df pd.read_csv(comments.csv) # 去重 df df.drop_duplicates(subset[comment]) # 去掉空值和超短评论 df df[df[comment].notna()] df df[df[comment].str.len() 4] # 过滤掉明显是广告的内容 ad_pattern re.compile(r加微信|扫码|代购|秒发|领取优惠) df df[~df[comment].str.contains(ad_pattern)]清洗完之后我还建议把评论按购买颜色和款式做个简单归类。因为有些评论会提到“买了肤色很自然”“黑色更百搭”这类带SKU信息的评论在分析的时候价值极高。如果抓取的时候没有单独拿到颜色字段也可以直接通过正则从评论文本里提取def extract_color(text): color_list [黑色, 肤色, 灰色, 咖啡色, 白色, 棕色] for color in color_list: if color in text: return color return 未知这样就能把“喜欢黑色”和“喜欢肤色”这类信息汇总起来看一下不同颜色的口碑差异。3.2 分词、词频与情感打分数据清洗完之后真正的重头戏来了对评论文本做分析。先做分词和词频统计。中文分词要用jieba它在大多数生活和电商场景下都表现稳定。直接使用jieba.cut()把每一条评论切成词然后过滤掉单字和停用词再统计出现次数。import jieba from collections import Counter stopwords set(这个 那个 真的 感觉 还是 一款 非常 不过 但是.split()) def tokenize(text): return [w for w in jieba.cut(text) if len(w) 1 and w not in stopwords and not w.isdigit()] word_counter Counter() for comment in df[comment]: word_counter.update(tokenize(comment)) top_words word_counter.most_common(30) print(top_words)我跑完之后排在前面的词基本集中在显瘦、不掉档、自然、透气、舒服、薄、百搭、透肉、弹性、舒适、勒、掉色、起球。看到这些词你就知道女生买黑丝真正关心的是上腿效果、穿着舒适度和质量而不是品牌或者价格。但是光看词频还不够因为“舒服”可能是好评里的“舒服”也可能是差评里的“不舒服”。所以还必须做情感分析。SnowNLP是一个很适合做中文情感分析的库用法非常简单from snownlp import SnowNLP def sentiment_score(text): try: return SnowNLP(text).sentiments except Exception: return 0.5这个方法的返回值在0到1之间越接近1表示情感越正面。我一般把0.6作为正面评论的阈值低于0.4算负面中间则视为中性。需要提醒的是SnowNLP默认的训练语料偏商品评论在“黑丝”这个品类下效果还算凑合但遇到“显瘦到没朋友”这种反讽句式也偶尔会翻车。所以我建议不要单靠一个模型可以把情感得分和评论区星级评分结合起来如果某条评论评分是1星但情感得分很高大概率是模型判断错了。3.3 构建综合评分模型有了词频和情感得分就可以给不同款式打分排名了。我的思路是这样的先把评论按商品ID分组然后计算每个商品的平均情感得分代表整体口碑再统计每个商品评论中出现“显瘦”“舒服”“质量”“不掉档”这些核心关键词的次数代表优点突出程度。最后把两个指标归一化后加权求和。def score_product(group): avg_sentiment group[sentiment].mean() keyword_hits group[keywords_count].sum() return avg_sentiment * 0.6 keyword_hits * 0.4 df[sentiment] df[comment].apply(sentiment_score) df[keywords_count] df[comment].apply(lambda x: sum(1 for w in [显瘦, 舒服, 不掉档, 透气, 自然] if w in x)) product_score df.groupby(product_id).apply(score_product).sort_values(ascendingFalse)跑完这步你会发现排名靠前的款式有一个很明显的共性评论里高频出现“自然”“透气”“不掉档”三个词。这说明在这个品类里“自然百搭”和“穿着舒服”才是女生真正买单的理由而不是花哨的颜色或设计。这里有个坑必须说分组之后各个组的样本量差异非常大。有的爆款有几千条评论有的只有几十条。样本量太少的组得分没有统计意义排序靠前可能只是偶然。建议在做排序前先过滤掉评论数少于50条的款式或者对样本量做一个加权处理。4. 可视化给女朋友看的那种“报告”4.1 词云图怎么设置中文字体分析做完之后如果你只是给对方丢一个排名表那这个项目就少了一半的乐趣。可视化的意义不只是展示数据还能帮你快速向女朋友或者朋友解释“你是怎么得出这个结论的”。第一步是画词云。词云的原理很简单把词频高的关键词用更大字号显示出来一眼就能看出评论集中在哪些维度上。用Python的wordcloud库三行代码就能出图但新手最常栽的坑就是中文乱码。因为wordcloud默认字体不支持中文必须指定一个中文字体路径。from wordcloud import WordCloud import matplotlib.pyplot as plt # Windows系统一般自带微软雅黑 font_path C:/Windows/Fonts/msyh.ttc # macOS系统可以用这个路径 # font_path /System/Library/Fonts/PingFang.ttc wordcloud WordCloud( font_pathfont_path, width800, height600, background_colorwhite, max_words100, collocationsFalse ).generate_from_frequencies(dict(word_counter)) plt.figure(figsize(10, 7)) plt.imshow(wordcloud, interpolationbilinear) plt.axis(off) plt.show()这里有个细节generate_from_frequencies接收的是词频字典而不是原始文本。如果你直接传文本进去会把连在一起的分词结果当成一个词效果会差很多。另外collocationsFalse这个参数很重要它控制的是是否合并相邻词语在中文场景下一般建议关掉避免出现“真 的 很 好 看”被合并成奇怪的词组。4.2 用雷达图对比款式评分词云能展示总体的舆论风向但要对比具体哪款更好用雷达图非常直观。我挑了排名前三的款式分别从“舒适度”“显瘦效果”“自然度”“耐穿性”“颜色”五个维度打分然后画在一张雷达图上对比。这五个维度的分数怎么来就是统计该款评论里对应关键词的提及比例再映射到1到10分。import numpy as np import matplotlib.pyplot as plt labels [舒适度, 显瘦效果, 自然度, 耐穿性, 颜色] scores_a [9, 8, 7, 8, 9] # 第一款 scores_b [7, 9, 8, 6, 7] # 第二款 scores_c [6, 7, 9, 9, 8] # 第三款 angles np.linspace(0, 2 * np.pi, len(labels), endpointFalse).tolist() angles angles[:1] def plot_radar(scores, color, label): values scores scores[:1] ax.plot(angles, values, colorcolor, labellabel, linewidth2) fig, ax plt.subplots(figsize(8, 8), subplot_kwdict(polarTrue)) plot_radar(scores_a, red, A款) plot_radar(scores_b, blue, B款) plot_radar(scores_c, green, C款) ax.set_xticks(angles[:-1]) ax.set_xticklabels(labels, fontsize12) ax.legend(locupper right, bbox_to_anchor(1.2, 1.1)) plt.show()雷达图的视觉冲击力比表格强很多特别适合在最后展示结论的时候用。从我的实际体验来看如果这三款里有一款在“舒适度”和“自然度”两个维度上同时突出那它就大概率是全场最佳。因为这两个维度对应的是评论区里最密集的好评关键词背后代表了最广泛的群众意见。5. 踩坑实录与几个实用建议5.1 爬虫阶段的坑我这次爬虫踩的最大的坑是编码问题很多平台的评论接口返回的是GBK编码直接resp.json()会报错或者出现乱码。解决方法是先看响应头里有没有charset字段没有的话就用resp.content.decode(gbk)手动解码。第二个坑是页面结构变化。同一个页面PC端和移动端的评论数据结构完全不同而且平台隔几个月就会改版一次。我建议不要长期依赖一套选择器写爬虫时尽量把解析逻辑封装成独立函数页面一改就直接改函数内部别的地方不用动。第三个坑是IP被封。实测下来就算每次请求间隔1到3秒连续跑几百个请求也可能会触发风控。保险的做法是限制单次任务不超过1000条评论或者暂停一段时间再继续。千万别为了追求速度把延时调到0.1秒我试过结果就是整个IP段被限制访问项目直接停摆一天。5.2 分析阶段的坑分词是整个分析阶段最容易出问题的地方。jieba对“黑丝”“透肉”“不掉档”这类垂直品类的词汇经常切得不准确比如把“不掉档”切成“不掉”和“档”。解决办法是准备一个自定义词典把这些行业术语加进去。custom_words [黑丝, 连裤袜, 透肉, 不掉档, 踩脚, 肤色, 微透] for word in custom_words: jieba.add_word(word)加了自定义词典之后词频统计的准确性会提升一个档次。特别是“不掉档”这种词它本身就是品类的核心卖点如果被切碎了后面的情感分析和关键词统计都会失真。情感分析那边的坑则是误判。SnowNLP在遇到“太显瘦了”、“穿上像没穿一样”这种带夸张语气的表达时偶尔会给出偏中性的分数。我的解决办法是对极端评分做一个后处理如果评论中出现“太”“绝了”“超”“好喜欢”这类程度副词和正面词组合直接把它标记为强正面。5.3 一个容易被忽略的问题样本偏差最后我必须提醒一下数据分析的天然局限。评论数据本质上只代表了“愿意写评论的人”而愿意写评论的人往往带着比较强烈的正面或负面情绪中性体验的人很少会发声。这意味着你看到的口碑分布可能比真实情况更两极分化。还有一个偏差是时间维度。新款上市初期评价往往比较友好因为第一批买的人通常是有明确购买意向前来的人而过了半年随着销量扩大负面评价的比例会上升。如果你抓取的评论集中在某款刚上市的时间段它的得分可能会虚高。解决方法是把评论时间作为一个分析维度对比不同时间段的平均情感得分。如果一款产品的好评率在三个月内稳定在较高水平那才是真正值得信任的口碑。5.4 别忘了“好看”是件主观的事数据能告诉你大众的偏好但你女朋友不是大众。她可能更偏好深色系可能对某种材质过敏可能就喜欢不那么显瘦但更舒适的款式。所以这套分析的价值不是替你做决定而是帮你把一个模糊的“不知道买什么”缩小到两三款候选然后带着结论去做最终的确认。我最后给朋友的建议是选一两个综合评分高的款式再看一下评论里“肤色款”和“黑色款”哪个更适合日常穿着然后下单前直接问一句女朋友的偏好。用数据分析提高命中率再用沟通保证命中率。这比蒙着眼睛买或者完全依赖别人的评价都要靠谱得多。6. 最后说几句实操心得跑完这个项目我最深的体会是数据分析改变生活这件事落到实处就是从“我感觉”变成“数据显示”。当你把几万条评论抓下来跑完一轮词频和情感分析之后得到的结论往往比个人经验更客观也更有说服力。如果你也想上手练一遍我的建议很直接不要纠结于把这个项目做得多么完整先跑通一个最小版本。先抓100条评论做清洗、分词、词频、情感分析最后画一张词云图。整个流程走下来两个小时就能完成但这两个小时覆盖了爬虫、pandas、jieba、SnowNLP、matplotlib这些Python数据分析最核心的库比看十篇教程都有用。再分享一个小技巧分析结果出来之后可以把词云图或者雷达图做成一张卡片发给对方附上一句“这是根据几千条真实评论分析出来的结论你看喜欢哪个方向”。这种表达方式本身就是一种用心比单纯送一件东西更能打动人。数据负责帮你提高胜率而细节决定最终分数。
返回列表