尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

泡泡玛特评论数据分析实战:Python爬虫+情感分析+可视化链路

泡泡玛特评论数据分析实战:Python爬虫+情感分析+可视化链路 最近不少同学在准备毕业设计或找工作简历项目时都会问同一个问题Python 数据分析到底做什么项目才有亮点今天我想分享一个很适合拿来练手、也足够写进简历的完整案例——泡泡玛特热搜评论数据分析与可视化。这个案例覆盖了爬虫采集、数据清洗、情感分析、关键词提取、可视化大屏展示的完整链路代码量适中但技术栈非常全而且主题贴近年轻人的消费热点做出来的效果也很直观。本文将基于 Python3 手把手拆解整个项目从数据采集到最终可视化图表生成每一行代码都会解释作用。不管你是 Python 入门不久的新手还是正在准备数据分析岗位面试的求职者都可以按文章顺序复现这个项目。项目用到的核心库包括 requests、pandas、pyecharts、jieba 等我会在对应章节说明安装方式。先说明一点本文的爬虫部分以公开可访问的评论内容为演示对象重点在于讲解技术流程。实际抓取时你需要结合目标站点的页面结构和平台规则进行调整并遵守网站的爬虫协议与相关法律法规数据仅限用于学习研究。1. 项目背景与核心概念1.1 为什么选择泡泡玛特评论数据泡泡玛特是近年热度很高的潮玩品牌旗下 Molly、SKULLPANDA、DIMOO 等 IP 在社交平台上的讨论量非常大。用户评论里既包含对具体产品的评价也包含对 IP 形象、抽盒体验、价格、质量等维度的真实反馈。这些评论数据天然具备几个适合做数据分析的特点数据量可观热门产品评论区往往有成百上千条真实评论足够支撑统计分析和情感判断。文本信息丰富评论里包含大量关键词比如“好看”“隐藏款”“雷款”“品控”“发货速度”等适合做关键词提取和情感分析。用户画分明晰不少平台会展示用户的所在城市、等级、性别等信息方便做多维度的交叉分析。商业价值明显分析结果能帮助品牌了解用户口碑、发现问题产品、评估 IP 热度是一个很有说服力的业务分析场景。从学习角度来说这个项目不需要复杂的分布式爬虫架构单机即可完成全部流程同时又能把 Python 数据分析的核心技能都串联起来非常适合作为第一个完整的数据分析实战项目。1.2 数据爬虫、数据分析、数据可视化的关系很多初学者会把“爬虫”“数据分析”“可视化”当成三个独立的技能实际上在一个真实项目中它们是环环相扣的。爬虫负责解决“数据从哪来”的问题。它通过模拟浏览器请求从目标网页或接口中提取结构化数据比如评论内容、评分、时间、用户名等。数据分析负责解决“数据说明了什么”的问题。拿到原始数据后通常不能直接使用因为里面会有缺失值、重复值、无意义字符等。这一步要做数据清洗、字段提取、统计聚合、情感判断最终得到有价值的结论。数据可视化负责解决“结论如何呈现”的问题。通过柱状图、饼图、词云、地图等图表把分析结果直观地表达出来。相比一大堆 Excel 表格图表形式更适合做汇报和展示也是简历项目中容易出彩的部分。这个案例的顺序非常典型评论采集 → 数据清洗 → 关键词统计 → 情感分析 → 可视化展示。每一步都依赖上一步的结果所以建议严格按照文章顺序逐步完成。1.3 本项目适合哪些读者我在设计这个教程时主要考虑了以下三类读者Python 基础语法已经学过但不知道如何完成一个完整项目的初学者。需要做课程设计、毕业设计想找一个难度适中且有展示效果题目的同学。正在准备数据分析或 Python 开发岗位面试需要简历项目经历和面试案例的求职者。如果你目前只会编写简单的 Python 脚本对 pandas 和 pyecharts 不太熟悉当然也可以跟着做。文章中出现的每一行代码都会有注释遇到不懂的库只需要记住“它解决了什么问题”就行。2. 环境准备与项目结构2.1 开发环境说明本文示例代码基于以下环境编写具体版本可以根据你的电脑环境适当调整。操作系统Windows 10 / 11macOSLinux 均可 Python 版本Python 3.8 及以上 IDEPyCharm 或 VS Code 浏览器Chrome / Edge用于查看生成的 HTML 可视化图表建议使用虚拟环境隔离项目依赖避免污染全局 Python 环境。下面是在项目目录下创建虚拟环境的命令。python -m venv venv在 Windows 系统下激活虚拟环境venv\Scripts\activate在 macOS 或 Linux 系统下激活虚拟环境source venv/bin/activate激活后命令行提示符前会出现(venv)字样说明当前已经进入虚拟环境。2.2 依赖库安装本项目主要用到以下 Python 库库名称用途requests发送 HTTP 请求获取网页或接口数据BeautifulSoup4解析 HTML 页面提取评论信息pandas数据清洗、聚合统计、DataFrame 操作jieba中文分词提取评论关键词pyecharts生成交互式可视化图表输出 HTMLwordcloud生成词云图matplotlib生成基础静态图表配合 wordcloud 使用执行下面的命令一次性安装所需依赖。pip install requests beautifulsoup4 pandas jieba pyecharts wordcloud matplotlib如果安装速度较慢可以临时使用国内镜像源安装。pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests beautifulsoup4 pandas jieba pyecharts wordcloud matplotlib需要注意pyecharts 的版本差异会影响 API 调用方式本文以常用稳定写法为准。如果你之前安装过旧版 pyecharts建议升级到最新版本再继续操作。pip install --upgrade pyecharts2.3 项目目录结构为了保持代码整洁建议按下面的目录结构组织项目文件popmart-analysis/ ├── venv/ # 虚拟环境目录 ├── data/ # 存放原始数据和清洗后的数据 │ ├── comments_raw.csv │ └── comments_clean.csv ├── output/ # 存放输出的可视化图表 │ ├── comment_trend.html │ ├── ip_rank.html │ ├── city_distribution.html │ ├── sentiment_pie.html │ └── wordcloud.png ├── crawler.py # 评论数据采集脚本 ├── data_clean.py # 数据清洗与预处理脚本 ├── analysis.py # 数据分析与可视化脚本 └── requirements.txt # 依赖清单实际开发时可以根据项目规模灵活调整但建议把爬虫、清洗、分析三个环节拆分成不同脚本这样后期维护和调试会方便很多。如果写到 Jupyter Notebook 里则可以按单元格顺序执行效果也类似。3. 评论数据采集从网页到结构化数据3.1 爬虫的合规边界在编写爬虫之前必须先明确法律和平台规则边界。《网络安全法》《数据安全法》《个人信息保护法》都对网络数据采集有明确要求。做学习项目时请严格遵守以下几点只采集公开可访问的数据不突破登录权限、不绕过反爬机制。遵守目标网站的 robots.txt 协议。控制请求频率不要对目标服务器造成压力。采集的个人信息用于学习研究不做商业用途。不对采集到的数据做用户身份识别和敏感信息分析。本文的核心是讲解技术方法示例中的页面结构仅用于演示。实际运行时一定要根据目标站点的规则调整代码。3.2 设计评论数据字段在写爬虫之前先想清楚要采集哪些字段。设计良好的字段结构能减少后续清洗的工作量。针对泡泡玛特评论场景建议保留以下字段字段名说明示例user_name用户昵称一颗泡泡糖user_city用户所在城市上海comment_time评论时间2024-11-20 15:32:10comment_content评论正文手感很好隐藏款做工超赞product_name评论对应的产品名SKULLPANDA 温度系列rating评分或星级5.0like_count点赞数128有了这个字段设计后续无论是做时间趋势、城市分布还是词云分析都有对应的数据支撑。3.3 使用 requests 获取页面数据下面是一个基础的请求代码示例。使用 requests 库向目标评论页面发送 GET 请求并设置合理的请求头。# 文件路径crawler.py import requests import time import csv import random def fetch_html(url): 发送 HTTP GET 请求返回网页 HTML 文本。 示例代码实际使用时请根据目标站点的请求方式调整。 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, Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8, } try: resp requests.get(url, headersheaders, timeout10) resp.raise_for_status() resp.encoding utf-8 return resp.text except requests.RequestException as e: print(f[请求失败] {url}, 错误信息: {e}) return None代码中做了几件比较重要的事情自定义 User-Agent模拟浏览器环境。设置 timeout避免某个请求长时间阻塞程序。捕获 requests.RequestException便于分析失败原因。设置响应编码为 utf-8避免中文乱码。3.4 解析评论数据拿到 HTML 文本后需要使用 BeautifulSoup 解析页面结构定位到评论列表所在的标签区域。from bs4 import BeautifulSoup def parse_comments(html): 解析页面中的评论数据。 注意这里的选择器仅为演示实际运行时要根据目标页面结构调整。 if not html: return [] soup BeautifulSoup(html, html.parser) comments [] # 假设每条评论都包含在 classcomment-item 的 div 中 comment_items soup.select(.comment-item) for item in comment_items: try: user_name item.select_one(.user-name).get_text(stripTrue) user_city item.select_one(.user-city).get_text(stripTrue) comment_time item.select_one(.comment-time).get_text(stripTrue) comment_content item.select_one(.comment-content).get_text(stripTrue) product_name item.select_one(.product-name).get_text(stripTrue) rating_text item.select_one(.rating).get_text(stripTrue) comments.append({ user_name: user_name, user_city: user_city, comment_time: comment_time, comment_content: comment_content, product_name: product_name, rating: rating_text, }) except AttributeError: # 某条评论缺少字段时跳过避免程序中断 continue return comments这里的.select_one()方法返回第一个匹配的标签.get_text(stripTrue)表示提取标签文本并去掉首尾空白。由于不同网站的 HTML 结构差异很大实际使用时你需要打开浏览器开发者工具找到评论对应的真实 class 或 id再进行选择器调整。3.5 完整采集流程与数据保存实际评论数据通常不止一页需要翻页采集。翻页时要注意控制请求间隔随机休眠 1 到 3 秒降低对目标服务器的压力。def crawl_comments(base_url, total_pages10): 翻页采集评论数据保存到 CSV 文件。 all_comments [] for page in range(1, total_pages 1): page_url f{base_url}?page{page} print(f正在采集第 {page} 页URL: {page_url}) html fetch_html(page_url) page_comments parse_comments(html) if not page_comments: print(f第 {page} 页没有解析到数据停止翻页) break all_comments.extend(page_comments) # 随机休眠 1-3 秒避免请求频率过高 time.sleep(random.uniform(1, 3)) # 保存为 CSV with open(data/comments_raw.csv, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[ user_name, user_city, comment_time, comment_content, product_name, rating ]) writer.writeheader() writer.writerows(all_comments) print(f采集完成共获取 {len(all_comments)} 条评论) return all_comments if __name__ __main__: # 实际使用时请替换为目标评论页地址 demo_url https://example.com/popmart/comments crawl_comments(demo_url, total_pages5)CSV 文件使用utf-8-sig编码保存这样做的好处是用 Excel 直接打开时中文不会乱码。如果你只是用 pandas 读取使用utf-8编码也完全可以。到这里爬虫部分的完整流程就结束了。真实项目中你可能会遇到动态加载的评论数据这类数据一般通过 Ajax 接口返回 JSON 格式此时不需要解析 HTML直接请求接口地址并用resp.json()解析即可。本质思路是一样的。4. 数据清洗与预处理4.1 读取原始数据采集完成后接下来进入数据分析的关键环节数据清洗。先用 pandas 读取 CSV 文件查看数据基本状况。# 文件路径data_clean.py import pandas as pd # 读取原始数据 df pd.read_csv(data/comments_raw.csv, encodingutf-8-sig) print(原始数据形状, df.shape) print(字段列表, df.columns.tolist()) print(\n前 5 行数据) print(df.head()).shape返回数据表的行数和列数.head()默认显示前 5 条数据。这一步主要是确认数据是否成功读取并观察字段是否完整。4.2 处理缺失值与重复值评论数据中经常出现部分字段为空的情况比如用户没有填写城市、评分字段缺失等。处理方式要根据业务场景选择如果缺失比例很低可以直接删除缺失行。如果某字段缺失比例较高可以考虑填充默认值。评论内容为空的记录没有分析价值建议删除。# 查看每列缺失值数量 print(缺失值统计) print(df.isnull().sum()) # 删除评论内容为空的行 df df.dropna(subset[comment_content]) # 删除完全重复的行 df df.drop_duplicates() # 用户名和城市缺失的填充为“未知” df[user_name] df[user_name].fillna(未知用户) df[user_city] df[user_city].fillna(未知) # 重置索引 df df.reset_index(dropTrue) print(清洗后数据形状, df.shape)dropna(subset[comment_content])表示只在 comment_content 这一列检测缺失值。drop_duplicates()默认删除所有列完全相同的重复行。如果你想根据某一列去重可以写成drop_duplicates(subset[comment_content])。4.3 时间字段标准化评论时间可能是多种格式比如“2024-11-20 15:32:10”“11月20日”“刚刚”等。为了后续分析趋势需要统一转换为 pandas 的 datetime 类型。# 将评论时间转换为 datetime 类型无法转换的设为 NaT df[comment_time] pd.to_datetime(df[comment_time], errorscoerce) # 删除时间解析失败的行 df df.dropna(subset[comment_time]) # 提取日期和小时便于按天统计 df[comment_date] df[comment_time].dt.date df[comment_hour] df[comment_time].dt.hour print(df[[comment_time, comment_date, comment_hour]].head())errorscoerce是 pandas 中很实用的参数遇到无法解析的字符串时会转换为 NaT缺失时间而不会直接报错中断程序。4.4 评论文本长度与简单清洗评论正文中可能包含大量空格、换行、特殊符号、表情符号。在做词频统计之前需要做一轮文本清洗。import re def clean_text(text): 清洗评论文本 1. 去除多余空白 2. 去除非中文、非英文、非数字的符号 if not isinstance(text, str): return # 将换行、制表符替换为空格 text re.sub(r\s, , text) # 只保留中文、英文、数字和常用标点 text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9。、. ], , text) return text.strip() df[clean_content] df[comment_content].apply(clean_text) # 过滤清洗后内容为空的评论 df df[df[clean_content] ! ] # 添加文本长度列 df[content_length] df[clean_content].apply(len) print(文本清洗完成最短长度, df[content_length].min()) print(文本清洗完成最长长度, df[content_length].max())这段代码中的正则表达式有两个作用\s匹配连续空白字符并替换为单个空格[^\u4e00-\u9fa5a-zA-Z0-9。、. ]匹配所有不在中文字符、英文字母、数字和常见标点范围内的字符替换为空字符串。4.5 保存清洗后的数据完成以上步骤后把清洗结果保存为新的 CSV 文件方便后续分析脚本直接读取。# 保存清洗后的数据 clean_columns [ user_name, user_city, comment_time, comment_date, comment_hour, product_name, rating, clean_content, content_length ] df[clean_columns].to_csv(data/comments_clean.csv, indexFalse, encodingutf-8-sig) print(清洗后数据已保存到 data/comments_clean.csv)清洗环节在整个项目中非常重要。很多初学者拿到数据后直接做可视化最终图表里出现大量“None”“NaN”“未知”等脏数据分析结论自然不可信。只有保证数据质量后续的可视化才有意义。5. 数据处理与关键指标分析5.1 评论数量趋势分析拿到清洗后的数据先做基础统计。评论量的时间变化能够直观反映产品热度。# 文件路径analysis.py import pandas as pd df pd.read_csv(data/comments_clean.csv, encodingutf-8-sig) df[comment_date] pd.to_datetime(df[comment_date]) # 按日期统计评论量 daily_count df.groupby(df[comment_date].dt.date).size().reset_index(namecount) print(daily_count.head())groupby是 pandas 中最常用的聚合方法。size()统计每个日期出现的次数reset_index(namecount)把分组结果转换成 DataFrame并将计数字段命名为 count。5.2 产品 IP 热度排行评论中通常包含产品名称或 IP 系列名可以按产品分组统计评论数量找出讨论度最高的产品。# 按产品统计评论量并排序 product_rank df.groupby(product_name).size().reset_index(namecount) product_rank product_rank.sort_values(count, ascendingFalse) print(产品讨论度 Top10) print(product_rank.head(10))sort_values(count, ascendingFalse)表示按 count 列降序排列。如果产品名称中存在同一产品不同写法比如“SKULLPANDA 温度系列”和“温度系列”可以在清洗阶段做映射替换。5.3 城市分布分析如果评论数据中有用户城市字段可以按城市统计评论数量观察不同城市的消费活跃度。# 按城市统计评论量 city_rank df.groupby(user_city).size().reset_index(namecount) city_rank city_rank.sort_values(count, ascendingFalse) print(城市评论量 Top10) print(city_rank.head(10))这里有一个需要注意的问题城市字段可能包含“上海”“上海市”两种写法建议在清洗阶段做统一的省份/城市归一化或者用str.contains做模糊归类。5.4 关键词提取与词频统计中文文本无法直接按空格分词需要使用 jieba 库。jieba 支持三种分词模式这里使用精确模式它最适合文本分析场景。import jieba def extract_keywords(text): 使用 jieba 精确模式分词返回词语列表。 过滤长度为 1 的单个字和停用词。 words jieba.lcut(text) stopwords {的, 了, 是, 我, 你, 他, 这, 那, 也, 都, 就, 而, 及, 与, 或, 一个, 没有, 真的, 感觉, 还是, 可以, 这个, 那个, 什么, 怎么, 自己} result [] for word in words: word word.strip() if len(word) 1: continue if word in stopwords: continue result.append(word) return result # 对所有评论内容进行分词 df[keywords] df[clean_content].apply(extract_keywords) # 展开所有关键词并统计词频 from collections import Counter word_counter Counter() for kw_list in df[keywords]: word_counter.update(kw_list) print(Top20 高频词) for word, count in word_counter.most_common(20): print(f{word}: {count})Counter.update()可以批量更新计数。most_common(20)返回出现频次最高的前 20 个单词及其次数。5.5 简单情感倾向判断情感分析是评论分析中最有业务价值的部分。考虑到教学项目的复杂度这里使用基于情感词典的简单方法准备一份积极词表和消极词表统计评论中出现两类词语的数量最终判断评论情感。# 简单情感词典实际项目可以使用 SnowNLP 等现成工具 positive_words [好看, 可爱, 喜欢, 漂亮, 惊喜, 完美, 赞, 好评, 值得, 满意, 舒服, 高级, 精致, 强烈推荐] negative_words [雷, 差, 丑, 失望, 退货, 瑕疵, 垃圾, 后悔, 粗糙, 掉色, 破损, 客服差, 发货慢, 不值] def judge_sentiment(text): 根据情感词典粗判评论情感。 返回positive / neutral / negative pos_count sum(1 for w in positive_words if w in text) neg_count sum(1 for w in negative_words if w in text) if pos_count neg_count: return positive elif neg_count pos_count: return negative else: return neutral df[sentiment] df[clean_content].apply(judge_sentiment) # 统计情感分布 sentiment_count df[sentiment].value_counts() print(情感分布情况) print(sentiment_count)这种基于词典的方法准确率有限因为评论里存在否定表达、讽刺表达等情况。但作为入门项目演示已经足够。如果你希望提升准确率可以改用 SnowNLP、BERT 等模型这可以作为项目的进阶优化方向。6. 数据可视化让分析结果一目了然6.1 pyecharts 基础使用pyecharts 是 Python 中非常流行的可视化库它基于百度开源的 ECharts 实现能生成交互式 HTML 图表。语法上采用链式调用代码结构清晰。使用 pyecharts 时需要先导入对应图表类型。下面是一个最简单的柱状图示例。from pyecharts.charts import Bar from pyecharts import options as opts bar ( Bar() .add_xaxis([A, B, C]) .add_yaxis(评论量, [10, 20, 15]) .set_global_opts(title_optsopts.TitleOpts(title示例柱状图)) ) bar.render(output/demo_bar.html)运行代码后会在 output 目录下生成一个 demo_bar.html 文件用浏览器打开即可看到交互式图表。链式调用的意思是每个方法都返回对象本身所以可以连续调用.add_xaxis()、.add_yaxis()等方法。6.2 评论量时间趋势折线图下面结合前面统计好的 daily_count 数据生成评论量随时间变化的折线图。from pyecharts.charts import Line import pyecharts.options as opts # 按日期排序 daily_count daily_count.sort_values(comment_date) line ( Line() .add_xaxis([str(d) for d in daily_count[comment_date]]) .add_yaxis( 评论量, daily_count[count].tolist(), is_smoothTrue, label_optsopts.LabelOpts(is_showFalse), ) .set_global_opts( title_optsopts.TitleOpts(title泡泡玛特评论量时间趋势), tooltip_optsopts.TooltipOpts(triggeraxis), xaxis_optsopts.AxisOpts(name日期, axislabel_optsopts.LabelOpts(rotate45)), yaxis_optsopts.AxisOpts(name评论量), datazoom_opts[opts.DataZoomOpts(range_start0, range_end100)], ) ) line.render(output/comment_trend.html)这里几个参数的作用is_smoothTrue让折线更平滑。label_optsopts.LabelOpts(is_showFalse)隐藏折线上的数值标签让图表更干净。axislabel_optsopts.LabelOpts(rotate45)X 轴标签旋转 45 度防止日期重叠。datazoom_opts添加缩放组件方便查看长时间范围的数据。6.3 产品 IP 热度柱状图接下来生成产品讨论度 Top10 的横向柱状图。横向柱状图适合展示较长的产品名称。from pyecharts.charts import Bar # 取 Top10 数据 top10 product_rank.head(10).sort_values(count, ascendingTrue) bar ( Bar() .add_xaxis(top10[product_name].tolist()) .add_yaxis( 评论量, top10[count].tolist(), label_optsopts.LabelOpts(positionright), ) .reversal_axis() .set_global_opts( title_optsopts.TitleOpts(title泡泡玛特产品讨论度 Top10), xaxis_optsopts.AxisOpts(name评论量), yaxis_optsopts.AxisOpts(name产品名称), ) ) bar.render(output/ip_rank.html).reversal_axis()是 pyecharts 中实现横向柱状图的关键方法它会交换 X 轴和 Y 轴。排序时先将数据升序排列这样柱状图会从高到低自然展示视觉效果更好。6.4 城市分布地图pyecharts 绘制中国地图需要先注册地图数据。新版本的 pyecharts 可能需要额外安装地图扩展包。如果不需要地图也可以使用柱状图展示城市排名效果同样直观。下面先给出柱状图方式# 城市评论量 Top10 city_top10 city_rank.head(10).sort_values(count, ascendingTrue) city_bar ( Bar() .add_xaxis(city_top10[user_city].tolist()) .add_yaxis(评论量, city_top10[count].tolist()) .reversal_axis() .set_global_opts( title_optsopts.TitleOpts(title泡泡玛特评论用户城市 Top10), xaxis_optsopts.AxisOpts(name评论量), ) ) city_bar.render(output/city_distribution.html)如果你希望生成地图需要先安装地图扩展包pip install echarts-countries-pypkg echarts-china-provinces-pypkg echarts-china-cities-pypkg如果安装后仍然显示空白可以在代码中通过current_config.ONLINE_HOST切换 CDN 地址这个问题会在下一节详细说明。6.5 情感分布饼图情感分布使用饼图展示可以直观看到积极、中性、消极评论的占比。from pyecharts.charts import Pie # 准备数据 sentiment_data [ (积极, int(sentiment_count.get(positive, 0))), (中性, int(sentiment_count.get(neutral, 0))), (消极, int(sentiment_count.get(negative, 0))), ] pie ( Pie() .add( series_name情感占比, data_pairsentiment_data, radius[40%, 70%], label_optsopts.LabelOpts(formatter{b}: {d}%), ) .set_global_opts( title_optsopts.TitleOpts(title泡泡玛特评论情感分布), legend_optsopts.LegendOpts(orientvertical, pos_top15%, pos_left2%), ) ) pie.render(output/sentiment_pie.html)radius[40%, 70%]表示内半径和外半径这样生成的是环形饼图。formatter{b}: {d}%表示标签显示名称和百分比。6.6 词云图生成词云图能直观展示高频关键词。这里使用 wordcloud 库生成 PNG 图片需要配合 matplotlib 展示。如果你的系统没有中文字体词云图会出现大量方块乱码。解决办法是指定一个支持中文的字体文件比如 Windows 下的C:\Windows\Fonts\simhei.ttf或 macOS 下的PingFang.ttc。from wordcloud import WordCloud import matplotlib.pyplot as plt # 将高频词转为词典形式 word_freq_dict dict(word_counter) # 指定中文字体路径请根据你的系统调整 font_path C:/Windows/Fonts/simhei.ttf wordcloud WordCloud( font_pathfont_path, width800, height600, background_colorwhite, max_words200, max_font_size120, colormapviridis, ).generate_from_frequencies(word_freq_dict) # 使用 matplotlib 展示并保存 plt.figure(figsize(10, 8)) plt.imshow(wordcloud, interpolationbilinear) plt.axis(off) plt.title(泡泡玛特评论高频词云) plt.savefig(output/wordcloud.png, dpi300, bbox_inchestight) plt.show()generate_from_frequencies()可以直接从词频字典生成词云不需要传入原始文本这样能精准控制哪些词显示。7. 整合项目一键运行完整流程7.1 项目文件整合为了方便演示和后续扩展建议把以上代码整合为一个主流程脚本通过命令行参数控制运行哪一步。下面是一个简单的整合示例# 文件路径main.py import crawler import data_clean import analysis def run_all(): print( 步骤1采集评论数据 ) # crawler.crawl_comments(https://example.com/popmart/comments, total_pages5) print( 步骤2清洗数据 ) # data_clean.clean_data() print( 步骤3分析与可视化 ) # analysis.run_analysis() print( 全部完成 ) if __name__ __main__: run_all()实际开发中你可以把crawler.crawl_comments()、data_clean.clean_data()、analysis.run_analysis()分别实现为可调用的函数然后在main.py中按顺序调用。7.2 运行方式说明完成所有脚本后在项目根目录下执行python main.py程序会自动执行爬虫采集、数据清洗、分析统计和可视化生成。最终在 output 目录下得到多个 HTML 图表文件和一张词云 PNG 图片。如果你使用的是 Jupyter Notebook也可以把各个步骤拆成单元格逐个执行。这样在调试阶段更方便查看中间结果。8. 常见问题与排查思路在实际运行项目时你可能会遇到各种报错。下面是几个高频问题及排查思路。问题现象常见原因解决思路爬虫请求返回 403请求头不完整或请求频率过高补全 User-Agent、Referer降低请求频率中文乱码响应编码设置错误或 CSV 编码问题设置 resp.encoding utf-8CSV 保存使用 utf-8-sig评论内容解析为空HTML 选择器不匹配打开浏览器开发者工具重新定位评论标签pandas 读取 CSV 报编码错误文件保存编码与读取编码不一致统一使用 encodingutf-8 或 encodingutf-8-sigjieba 分词结果包含无意义单字未设置停用词表增加停用词过滤保留长度大于等于 2 的词pyecharts 地图显示空白地图数据未加载或 CDN 访问失败安装地图扩展包或切换 ON_LINE_HOST词云图显示方块乱码缺少中文字体指定系统已有中文字体路径matplotlib 窗口不显示图表没有调用 plt.show() 或后端配置问题检查是否调用 plt.show()或保存图片后直接查看这里重点说两个容易卡住的点。第一个是 pyecharts 地图空白。老版本的 pyecharts 会从公共 CDN 加载地图 JS 文件如果网络无法访问该地址地图区域就是空白。解决方法有两种一是安装地图数据包二是配置本地静态文件服务。对于学习项目最简单的方式是使用柱状图代替地图展示效果同样清晰。第二个是爬虫请求 403 问题。很多网站会检查请求是否来自真实浏览器最简单的方法是补全 User-Agent再加上 Referer、Origin 等请求头。如果仍然 403可能需要使用 cookies 或增加更真实的请求头组合。切记不要暴力请求避免影响网站正常服务。9. 最佳实践与工程建议9.1 代码组织与命名规范项目变大后代码组织方式会直接影响维护效率。建议遵循以下原则爬虫、清洗、分析代码放不同模块职责单一。函数命名使用动词开头比如fetch_html、parse_comments、clean_text。魔法数字定义为常量比如总页数、休眠时间范围。文件路径使用os.path.join或pathlib.Path拼接避免不同系统分隔符问题。9.2 数据存储与备份学习项目保存为 CSV 足够但如果数据量很大建议改用 SQLite 或 MySQL。使用数据库有以下好处支持增量爬取不用每次都全量采集。支持 SQL 查询方便复杂统计。数据更安全不容易因为程序中断而丢失。在分析前建议先对原始数据做备份。洗数据是不可逆操作一旦清洗逻辑写错原始数据就会丢失。你可以在采集时同时保存原始响应和使用 pandas 处理后的结果两份文件。9.3 异常处理与日志记录写爬虫时至少要有 try-except 包裹网络请求代码否则一个请求超时就会导致整个程序崩溃。更规范的做法是使用logging模块记录日志而不是到处使用print。import logging logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(app.log, encodingutf-8), logging.StreamHandler() ] ) logger logging.getLogger(__name__) logger.info(开始采集第 1 页数据) logger.warning(第 2 页请求失败重试中)日志不仅能记录正常流程也方便排查线上问题。这在实际工程中非常重要。9.4 分析结论的可解释性数据分析不能只停留在“画图”层面。每张图背后都要能解释业务含义。比如如果发现某一天评论量突然暴涨可以尝试关联当天是否有新品发布或促销活动如果某个产品消极评论占比很高可以进一步分析消极评论集中在哪些关键词上从而定位产品问题。面试中面试官通常不会只问“你怎么画这个图”而更关心“这个图说明了什么你怎么验证你的结论”。多思考分析背后的业务逻辑会让你的项目更有深度。10. 总结与下一步学习方向到这里一个完整的泡泡玛特热搜评论数据分析可视化项目就结束了。我们做的事情可以总结为五步用 requests 和 BeautifulSoup 采集评论数据用 pandas 完成缺失值处理、时间格式化、文本清洗用 jieba 做中文分词和关键词提取用情感词典粗判评论情感用 pyecharts 和 wordcloud 生成可视化图表。整个过程不依赖付费工具完全使用 Python 开源库完成。如果你希望在这个基础上继续深入推荐按下面的方向进阶。第一把爬虫部分升级为 Scrapy 框架。Scrapy 自带并发请求、去重、中间件、Pipeline 等机制适合大规模采集。这也是爬虫岗位面试中常考的内容。第二把静态可视化升级为 Web 应用。可以使用 Flask 或 Django 搭建后台通过 ECharts 实现数据大屏的效果。这样项目会更像一个完整的商业产品。第三用更专业的模型替代情感词典。比如 SnowNLP、BERT 中文情感分类模型分析准确率会明显提升。这类改进点非常适合写在简历项目里体现你对模型效果的思考。第四引入自动化定时采集。把爬虫部署到服务器上用 cron 或 APScheduler 定时执行配合数据库做增量更新就能形成一个持续运行的数据分析系统。这个项目上手难度适中但覆盖的知识面很广。只要你把每一行代码都吃透理解每一步的输入输出完全有资格把它作为简历上的核心项目。随便打开一个可视化图表你能讲清楚它的数据来源和处理流程面试官就会认为你是真的做过而不是背代码。如果你决定动手复现这个项目建议先不要着急跑完整个流程而是从爬虫开始每完成一个环节就输出一个中间结果这样遇到问题时也能快速定位。遇到报错就在评论区告诉我也可以直接搜索错误信息通常都能找到解决方案。希望这篇教程能帮你完成一个拿得出手的数据分析项目也欢迎收藏备用。
返回列表