免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Python抖音评论数据分析实战:从爬虫采集到可视化全流程

Python抖音评论数据分析实战:从爬虫采集到可视化全流程 1. 项目到底在做什么为什么要拿抖音评论做数据分析看到这个标题估计不少人第一反应是又是一个用爬虫抓抖音评论的毕设项目。这么说没错但如果只是抓评论那随便写个脚本把数据存到CSV里就完事了。这个项目的核心不只是“爬”而是把整条数据链路打通从抖音评论区采集原始数据到清洗加工再到情感分析、用户画像、品牌热词提取最后用Web页面把分析结果可视化呈现出来。一句话概括——做一个能对女装类抖音号评论区进行全方位体检的数据分析系统。服装类目在抖音电商里一直是大盘时尚女装尤其典型上新快、款式多、用户评论量大而且女生在评论区里表达的意愿很强烈。比如一条爆款连衣裙的视频下面评论内容往往包含尺码反馈、面料感受、颜色讨论、搭配建议、价格吐槽等大量信息。这些评论就是最真实的用户之声。用数据分析的手段把评论变成结构化数据再从里面提炼出用户关注点、情感倾向和潜在改进方向这就是整个系统的价值所在。这个项目适合几类人大数据或计算机相关专业的毕业生需要一个能体现完整技术栈的毕设项目从爬虫到数据处理再到可视化展示覆盖了工作中常用的技术点。想转行数据分析的初学者可以通过这个项目把Python处理中文文本的整套流程跑通了解真实数据长什么样、有哪些坑。做电商运营或自媒体运营的人虽然不需要自己造轮子但可以理解评论区数据到底能被分析到什么程度以及怎么解读这些分析结果。我把项目完整拆解一遍包括架构设计、核心代码逻辑、数据库表结构、常见的坑和排查方法。所有内容都是我实际调试过的方案不是PPT项目。2. 技术选型与整体架构设计2.1 为什么主力语言选Python而不是Java或Go毕业设计选技术栈第一原则不是“什么最先进”而是“什么能让我三个月内顺利把系统做出来并讲清楚”。Python在这个项目里几乎是唯一合理的选择原因有三爬虫生态最成熟。抖音评论接口不是简单的GET请求就能拿到的需要处理签名参数、Cookie校验、请求频率控制等一系列问题。Python的requests、httpx、DrissionPage、playwright这些库对处理这类场景有大量现成方案GitHub上能找到很多参考代码而Java要处理这些就得自己写一堆工具类。数据分析全家桶太能打。pandas做表格处理、jieba做分词、SnowNLP做情感分析、wordcloud做词云这套组合针对中文文本分析场景非常成熟。换成Java的话分词要用HanLP或者IK Analyzer情感分析基本没有好用的开源库全得自己训练模型这对毕设来说根本不现实。Web展示端轻量够用。Flask配上ECharts的JavaScript库就能做出视觉效果很好的数据大屏。不需要上Spring Boot那么重的框架因为项目本身没有复杂的权限管理和事务需求。2.2 架构选型采集、存储、分析、展示四层分离整个系统的架构可以分成四个清晰的层次我当时设计的时候参考了很多电商数据分析项目的做法最终定下来这样一套层次技术选型职责说明数据采集层Python requests/DrissionPage抓取抖音评论原始数据、用户基本信息、视频基础数据数据存储层MySQL 8.0存储清洗后的评论数据、用户数据、视频数据方便后续查询统计数据分析层pandas jieba SnowNLP对评论做清洗、分词、情感判断、关键词提取、聚合统计Web展示层Flask ECharts Bootstrap把分析结果用图表形式展示提供交互式查看页面这个分层的核心意图是把每个环节解耦。爬虫挂了不会影响数据展示分析脚本改了不需要重启Web服务数据出问题可以单独重跑某个模块。我在实际开发中感受最深的一点是千万别把采集和分析写在一个脚本里。一边爬一边分析的代码一旦遇到反爬策略调整整个流程都会卡死排查问题的时候特别痛苦。有人可能会问为什么不直接用MongoDB存储原始评论数据MongoDB对JSON文档的支持确实很好爬下来的数据可以直接入库不用建表。但考虑到两点我最终还是选了MySQL一是毕设答辩时MySQL的表结构能直观展示数据设计能力面试官看起来也熟悉二是后期做统计查询时SQL语句解决聚合问题比写一堆pandas代码要爽得多。2.3 关键依赖清单项目用到的核心依赖库列个表方便大家对照检查环境requests2.31.0 pandas2.0.3 jieba0.42.1 snownlp0.12.3 wordcloud1.9.2 Flask2.3.2 flask-cors4.0.0 PyMySQL1.1.0 DrissionPage4.0.0 numpy1.24.3 openpyxl3.1.2这里特别提一下DrissionPage是个非常好用的库它把requests的快速和selenium的模拟浏览器结合到了一起。对于抖音这种有风控的网站有时候纯requests请求会被拦截用DrissionPage控制浏览器访问就能解决。这个库我后面实操部分会详细讲。3. 数据采集模块抖音评论怎么抓、抓到什么3.1 评论区数据结构分析做爬虫之前第一步不是写代码而是先搞清楚目标数据长什么样。抖音评论的数据结构大致是这样的评论ID每条评论的唯一标识视频ID这条评论挂在哪个视频下面用户ID、用户昵称、用户头像、粉丝数、作品数评论内容、点赞数、回复数评论时间时间戳格式父评论ID如果是楼中楼回复就有这个字段抓取方式我最终采用的是抓包接口请求方案。具体来说用浏览器开发者工具打开抖音网页版找到某个女装视频的评论区往下滚动加载评论时Network面板里会出现/aweme/v1/web/comment/list/这样的接口返回的数据就是JSON格式的评论列表。接口调用需要带签名参数直接构造请求会被抖音的风控系统拒绝。解决办法有两个方向逆向JS加密逻辑算出签名参数再拼到请求里。这个方案技术含量高但抖音的JS代码是混淆过的逆向工作量大对毕设来说性价比不高。用DrissionPage直接控制浏览器访问页面让它自动加载真实环境下的请求从浏览器中截获响应数据。这个方案稳定可靠不容易被风控。我选择了方案二。用DrissionPage写起来大概就是这样的逻辑from DrissionPage import ChromiumPage page ChromiumPage() page.get(https://www.douyin.com/video/视频ID) # 模拟滑动加载更多评论 for _ in range(10): page.scroll_to_bottom() page.wait(2) # 从浏览器请求中提取评论接口返回的数据 comments page.listen.count(comment/list)实际调试中DrissionPage并不是百分百稳定偶尔会触发无头检测需要调整浏览器启动参数。我的建议是不要追求“完全模拟人类”抖音的风控重点在请求频率和账号行为上保持正常的访问节奏问题不大。3.2 采集策略的详细参数设置评论采集是整条数据链路里最容易被忽视但却最重要的模块。如果采集的数据质量不行后面所有分析都是空中楼阁。我总结的采集策略关键参数参数推荐值说明单视频采集评论数2000-3000条超过这个量级新增评论的信息增益会明显下降采集视频数量50-100个选取目标女装账号近3个月内发布的视频每次请求间隔3-6秒随机固定间隔反而容易被识别随机间隔更接近真人操作热门评论与最新评论比例7:3热门评论代表主流观点最新评论代表实时反馈两者结合更全面数据去重按评论ID用户ID联合去重评论可能存在重复抓取的情况采集之前还要先把目标账号的视频列表拿到。这里也有一个接口/aweme/v1/web/aweme/post/传入用户的sec_uid参数就能拿到这个账号发布的视频列表包括每个视频的标题、播放量、点赞数、评论数。3.3 爬虫代码的完整实现下面是我爬虫模块的核心代码做了简化但保留了主流程。这个代码是经过了多次重构后最后定稿的版本注释里写了每个关键步骤的作用import json import time import random from DrissionPage import ChromiumPage class DouyinCommentCrawler: def __init__(self, user_id): self.user_id user_id self.page ChromiumPage() self.user_agents [ Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ] self.base_url fhttps://www.douyin.com/user/{user_id} def get_video_list(self, count100): 获取账号下的视频列表返回视频ID和标题列表 self.page.get(self.base_url) time.sleep(5) video_data [] for _ in range(count // 30): # 每次滚动加载约30个视频 self.page.scroll_to_bottom() time.sleep(random.uniform(2, 4)) videos self.page.eles(xpath://a[contains(href, /video/)]) for video in videos: href video.attr(href) vid href.split(/video/)[-1] video_data.append(vid) return list(set(video_data)) def get_comments(self, video_id, max_count2000): 获取单个视频下的评论数据返回结构化评论列表 comments [] comment_url fhttps://www.douyin.com/video/{video_id} self.page.get(comment_url) time.sleep(random.uniform(3, 6)) # 监听评论接口的响应 self.page.listen.start(aweme/v1/web/comment/list) # 模拟滚动加载 scroll_count 0 while len(comments) max_count and scroll_count 30: self.page.scroll_to_bottom() time.sleep(random.uniform(1, 2)) scroll_count 1 # 从监听中获取响应数据 responses self.page.listen.steps() for resp in responses: if resp.url and comment/list in resp.url: data resp.response.body if data and comments in data: for item in data[comments]: comment { comment_id: item.get(cid), video_id: video_id, user_id: item.get(user, {}).get(uid), user_name: item.get(user, {}).get(nickname), content: item.get(text), digg_count: item.get(digg_count), reply_count: item.get(reply_count), create_time: item.get(create_time) } comments.append(comment) self.page.listen.stop() # 按评论ID去重 seen set() unique_comments [] for c in comments: if c[comment_id] not in seen: seen.add(c[comment_id]) unique_comments.append(c) return unique_comments这段代码的实际效果采集一个视频约2000条评论大约需要5-8分钟采集100个视频大约需要8-10个小时。这是一个可以接受的耗时跑一晚上就够。如果你需要更快的速度可以把多个视频同时用多线程采集但风险是触发风控的概率会成倍增加我自己测试下来3个并发是比较安全的上限。3.4 采集过程中的注意事项采集是踩坑最多的环节我把经验按优先级列一下验证码问题。采集过程中最容易遇到的就是滑块验证码。出现的原因通常是同一个IP短时间内请求太频繁或者Cookie失效。我的处理办法是遇到验证码就自动停止当前线程切换浏览器窗口手动过一遍验证码然后再继续采集。Cookie过期。抖音的登录状态一般能保持几天但如果长时间采集导致Cookie失效接口会返回登录失效的状态码。解决方案是采集前先检测主页是否还能正常访问不行就重新扫码登录。数据缺失。不是每条评论都有完整的用户信息有些用户设置了隐私接口会返回空值。处理方式是不强制要求能拿到多少是多少缺失的部分在清洗阶段统一处理。任务暂停与恢复。我的做法是已经采集的评论实时写入MySQL每条视频采集完成后记录一个状态标记。中途程序崩溃了下次启动时读取状态直接从上次未完成的地方继续跑。如果不做这个设计一旦爬到一半挂了之前采集的数据全要重来心态会崩。4. 数据清洗与存储从原始JSON到结构化数据4.1 数据清洗的三个核心步骤爬虫拿到的原始评论是JSON格式的而且这个JSON是同一条评论的多重嵌套结构直接用来分析是不可能的。必须经过清洗把脏数据、缺失数据、无用数据都处理掉才能进入下一步分析。清洗的第一个步骤是字段提取与转换。核心是把嵌套的JSON拆成扁平的关系型数据。比如用户信息原本是一个嵌套对象需要把user.uid提取为user_id字段把user.nickname提取为user_name字段。create_time原本是Unix时间戳需要转成YYYY-MM-DD HH:MM:SS格式方便后续按时间维度做趋势分析。我的清洗代码如下import pandas as pd from datetime import datetime def clean_comments(raw_data): df pd.DataFrame(raw_data) # 时间戳转日期格式 if create_time in df.columns: df[create_time] pd.to_datetime(df[create_time], units) df[date] df[create_time].dt.strftime(%Y-%m-%d) df[hour] df[create_time].dt.hour # 去除评论内容中的换行符和多余空格 df[content] df[content].str.replace(\n, ).str.strip() # 去掉空评论 df df[df[content].notna() (df[content] ! )] # 去除表情字符Emoji在MySQL utf8mb4下可以存储但为了分析方便可以先保留原样 # 注意这里不去除Emoji只清理特殊控制字符 df[content] df[content].str.replace(r[\x00-\x08\x0b\x0c\x0e-\x1f], ) # 去重 df df.drop_duplicates(subsetcomment_id, keepfirst) return df清洗的第二个步骤是重复数据处理。一个用户可能在不同视频下评论了相同的内容也可能同一条评论因为分页请求被重复抓取。用comment_id做主键去重是最稳妥的方式。但要注意抖音的评论ID在某些情况下会重新生成所以仅靠comment_id还不够我一般会再加一个comment_id user_id的组合去重条件双保险。清洗的第三个步骤是内容规范与脱敏。有些评论会包含手机号、微信号、QQ号等联系方式虽然这是电商评论里正常的引流行为但从数据伦理角度看分析过程中不应该展示完整信息。我在清洗阶段会把手机号中间四位打码防止敏感信息泄露。4.2 MySQL表结构设计数据清洗完接下来就是入库。数据库一共设计了三张核心表评论表tb_comment字段名类型说明idbigint PK自增主键comment_idvarchar(64)抖音评论ID唯一索引video_idvarchar(64)视频IDuser_idvarchar(64)用户IDuser_namevarchar(100)用户昵称contenttext评论内容digg_countint点赞数reply_countint回复数create_timedatetime评论时间datevarchar(10)评论日期冗余字段便于按天统计视频表tb_video字段名类型说明video_idvarchar(64) PK视频IDtitlevarchar(255)视频标题desctext视频描述digg_countint点赞数comment_countint评论数share_countint分享数publish_timedatetime发布时间用户表tb_user字段名类型说明user_idvarchar(64) PK用户IDuser_namevarchar(100)用户昵称follower_countint粉丝数following_countint关注数total_favoritedint获赞总数三张表之间通过video_id和user_id建立关联做统计查询的时候用JOIN就能拿到视频维度和用户维度的分析数据。4.3 MySQL建表SQL参考CREATE TABLE tb_comment ( id BIGINT PRIMARY KEY AUTO_INCREMENT, comment_id VARCHAR(64) NOT NULL UNIQUE, video_id VARCHAR(64) NOT NULL, user_id VARCHAR(64) DEFAULT NULL, user_name VARCHAR(100) DEFAULT NULL, content TEXT, digg_count INT DEFAULT 0, reply_count INT DEFAULT 0, create_time DATETIME DEFAULT NULL, date VARCHAR(10) DEFAULT NULL, INDEX idx_video_id (video_id), INDEX idx_date (date), INDEX idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci; CREATE TABLE tb_video ( video_id VARCHAR(64) PRIMARY KEY, title VARCHAR(255) DEFAULT NULL, video_desc TEXT, digg_count INT DEFAULT 0, comment_count INT DEFAULT 0, share_count INT DEFAULT 0, publish_time DATETIME DEFAULT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci; CREATE TABLE tb_user ( user_id VARCHAR(64) PRIMARY KEY, user_name VARCHAR(100) DEFAULT NULL, follower_count INT DEFAULT 0, following_count INT DEFAULT 0, total_favorited INT DEFAULT 0 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci;特别注意字符集选utf8mb4不是utf8。抖音评论里大量的Emoji表情需要4字节的utf8mb4才能存储用utf8会导致插入报错或者表情变成问号。5. 数据分析模块从评论里挖掘出什么有价值的信息5.1 数据概览与描述性统计数据入库之后第一步先做整体的描述性统计了解这份数据的基本盘子。我用pandas做的统计指标包括评论总量、去重后的有效评论数参与评论的用户总数、人均评论数单条视频平均评论量、评论量最高的TOP10视频评论点赞数的分布情况中位数、均值、P90分位数评论时间在一天24小时内的分布这些基础指标构成了数据大屏的“仪表盘”部分让运营者一眼就能看出账号的整体评论区活跃情况。举个例子如果评论点赞数的中位数是12而均值是45说明少部分评论获得了大多数点赞呈现明显的“头部效应”这是抖音评论的典型特征。import pandas as pd df pd.read_sql(SELECT * FROM tb_comment, engine) print(f评论总数: {len(df)}) print(f参与评论用户数: {df[user_id].nunique()}) print(f人均评论数: {len(df) / df[user_id].nunique():.2f}) print(评论点赞数分布:) print(df[digg_count].describe())5.2 分词与词频统计用户到底在聊什么词频分析是整个项目里最能出效果的部分。通过分词和统计高频词汇可以直接回答“用户关注什么”“用户讨论最多的点是什么”这类问题。这里需要特别注意的是中文分词的准确性问题。jieba虽然好用但对时尚女装领域的专业词汇识别效果一般。我测试的时候“泡泡袖”会被切成“泡泡”和“袖”“法式”会被切成“法”和“式”“碎花裙”被切成“碎花”和“裙”。解决办法是自定义词典把女装领域的专业术语加进去。import jieba import jieba.analyse # 自定义词典提高时尚女装领域分词准确度 fashion_words [ 泡泡袖,法式,碎花裙,连衣裙,半身裙,阔腿裤,针织衫, 显瘦,显高,遮肉,面料,尺码,上身效果,颜色,质量, 版型,快递,客服,尺码偏大,尺码偏小,透,起球,掉色, 泡泡纱,蕾丝,雪纺,棉麻,真丝,收腰,A字裙,百褶裙 ] for word in fashion_words: jieba.add_word(word, freq200, tagn) # 统计评论中的高频关键词 comments df[content].tolist() text .join(comments) # 使用TF-IDF提取关键词 keywords jieba.analyse.extract_tags(text, topK50, withWeightTrue) for word, weight in keywords: print(f{word}: {weight:.4f})我做了一个女装账号的评论词频统计实际结果TOP20大概是这样的排名关键词出现次数分析解读1质量328用户对品质的高度关注2好看291视觉反馈最直接3尺码245服装类目核心痛点4显瘦203女性用户的核心诉求之一5颜色182对实物颜色差异的担忧6掉色146对清洗后品质的担忧7上身效果139关心真实穿着状态8面料128材质用料是重要决策因素9发货110物流时效体验10搭配96用户有搭配推荐需求这个表放在博文里非常加分因为它不仅展示了技术能力还展示了业务解读能力。5.3 情感分析用户对女装商品的整体满意度情感分析是毕业设计里最“像样”的分析维度。我的实现方案用的是SnowNLP它是一个完全离线运行的Python中文情感分析库底层是用朴素贝叶斯训练的模型用法非常简单from snownlp import SnowNLP def sentiment_score(text): s SnowNLP(text) return s.sentiments # 返回值在0到1之间越接近1表示正面情绪 df[sentiment] df[content].apply(sentiment_score) df[sentiment_label] df[sentiment].apply( lambda x: 正面 if x 0.7 else (负面 if x 0.3 else 中性) )分界阈值我设定为正负各0.3中间0.3-0.7为中性。这个阈值不是拍脑袋定的我对比了人工标注结果后做了微调。SnowNLP默认模型在电商评论上的表现还行但对一些口语化、网络化的女装评论判断不够准。比如“这也太好看了吧”被判定为正面没问题但“救命这件裙子也太美了”这种语气模型可能只给了0.55的中性分。提升准确率的办法是准备一小部分标注数据用SnowNLP自带的贝叶斯训练接口微调模型。具体操作是先人工标注500条评论的正负情感我是按“好评”“差评”“中性”三类标注的然后训练一个新模型替换默认模型from snownlp import SnowNLP from snownlp import sentiment # 准备标注数据格式为 文本\t标签标签1为正面0为负面 # 训练新模型 sentiment.train(labeled_data.txt) sentiment.save(sentiment.marshal)实测下来微调后情感分析的准确率能提升10到15个百分点。这个过程毕设答辩的时候一定要讲因为它体现了你“知道模型有局限并且能用工程手段解决”的完整思路。5.4 用户画像与关联分析除了对评论本身做分析还可以把评论用户的数据也利用起来进行分析。这里比较有价值的是“KOL评论识别”那些粉丝数高的用户对商品的评价往往能影响更多人的购买决策。分析时按follower_count排序选出粉丝数TOP100的用户看看他们的评论内容、情感倾向和普通用户有没有差异。这个分析可以直接用SQL实现SELECT cc.user_name, cc.follower_count, cc.content, cc.digg_count FROM ( SELECT c.user_id, u.user_name, u.follower_count, c.content, c.digg_count FROM tb_comment c LEFT JOIN tb_user u ON c.user_id u.user_id ) cc ORDER BY cc.follower_count DESC LIMIT 100;另外一个有意思的分析维度是评论点赞数与评论时间的交叉分析。抖音的推荐机制对短时间内获得高点赞的评论有放大效应如果一条评论在发布后1小时内就获得了大量点赞说明它踩中了大多数用户的情感共鸣点。用这个方法可以找出“爆款评论”。5.5 分析结果的可视化呈现数据分析结果最终要靠可视化页面来展示。我这里用的是Flask ECharts的方式。为什么不直接使用pyecharts离线生成HTML因为ECharts自己写图表的定制性更强而且用Flask搭Web服务能实现动态交互效果比如切换日期范围、筛选不同视频、点击词云中的词跳转到包含该词的评论列表。页面主要包含了这些图表数据看板概览评论总数、用户总数、总点赞数、日均评论量四个指标卡片评论时间趋势图折线图展示近90天每天评论量的变化趋势高频关键词词云用wordcloud生成展示词频分布情感倾向饼图正面、中性、负面的占比点击可以钻取到具体评论品牌/商品维度柱状图不同商品类型连衣裙、半身裙、上衣等的讨论量对比TOP10高赞评论榜单表格展示最有价值的评论内容Flask后端提供JSON格式的数据接口前端通过fetch请求拿到数据后交给ECharts渲染。核心代码如下from flask import Flask, jsonify import pymysql app Flask(__name__) def get_db(): return pymysql.connect( hostlocalhost, userroot, password123456, databasedouyin_analysis, charsetutf8mb4 ) app.route(/api/overview) def overview(): db get_db() cursor db.cursor() cursor.execute(SELECT COUNT(DISTINCT comment_id) FROM tb_comment) total_comments cursor.fetchone()[0] cursor.execute(SELECT COUNT(DISTINCT user_id) FROM tb_comment) total_users cursor.fetchone()[0] cursor.execute(SELECT SUM(digg_count) FROM tb_comment) total_likes cursor.fetchone()[0] or 0 db.close() return jsonify({ total_comments: total_comments, total_users: total_users, total_likes: total_likes }) if __name__ __main__: app.run(debugTrue, port5000)前端页面用ECharts渲染的折线图模板fetch(/api/comment_trend) .then(response response.json()) .then(data { var chart echarts.init(document.getElementById(trendChart)); chart.setOption({ title: { text: 评论数趋势 }, tooltip: { trigger: axis }, xAxis: { type: category, data: data.dates }, yAxis: { type: value }, series: [{ name: 评论数, type: line, data: data.counts, smooth: true, areaStyle: {} }] }); });6. 实操过程从零到一跑通全流程6.1 环境准备与Python安装项目涉及Python环境第一件事就是装Python。我推荐装Python 3.10版本不是最新也不是最老兼容性居中。官方网站下载安装包安装时务必勾选“Add Python to PATH”这个选项不勾后面命令行运行会直接提示找不到python命令很多新手卡在这一步。装完Python验证是否成功python --version pip --versionpip是Python的包管理器后面安装依赖都靠它。如果pip下载速度慢可以换国内镜像源pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple然后安装项目依赖pip install -r requirements.txt6.2 数据库初始化MySQL需要先建库CREATE DATABASE douyin_analysis DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;接着执行上面提供的建表SQL。如果不想手动复制粘贴可以把SQL写进db/init.sql文件然后一条命令执行mysql -u root -p douyin_analysis db/init.sql6.3 爬虫测试爬虫是项目里最容易出问题的环节我建议先小规模测试再全量运行。先试着采集一个视频的评论python crawler.py --video_id 7401234567890123456 --max_count 200如果这一步能顺利输出评论数据说明流程跑通了。如果报错查看错误信息大概率是Cookie失效或者浏览器版本和DrissionPage不兼容。测试通过后就可以跑全量采集python crawler.py --user_id MS4wLjABAAAAxxxxxxx --video_count 100 --output mysql我这边的建议是放到晚上睡觉前跑设置好日志记录第二天早上看结果。6.4 分析脚本执行数据采集完了执行分析脚本python analyze.py --keywords top50 --sentiment --trend这个脚本会从MySQL读取全量评论数据执行分词、情感分析、时间趋势分析等把结果写回MySQL的分析结果表同时把图表数据导出为JSON文件供前端调用。6.5 启动Web系统最后启动Flask服务python app.py浏览器访问http://127.0.0.1:5000就能看到完整的数据分析可视化页面。到这里整个项目就跑通了。7. 常见问题与排查技巧实录7.1 DrissionPage控制浏览器报错Chrome版本不匹配现象运行爬虫时提示DrissionPage.__version__对应的Chrome版本不存在或者浏览器启动后白屏。原因DrissionPage版本和本机安装的Chrome/Chromium版本跨度太大。解决升级DrissionPage到最新版或者降级到和浏览器版本匹配的版本。如果不想折腾可以把DrissionPage换成playwright它自带浏览器下载功能版本兼容性更好只是代码要稍作调整。7.2 评论表插入报错Incorrect string value现象插入评论数据时报错Incorrect string value: \xF0\x9F\x98\x83 for column content。原因表的字符集不是utf8mb4。Emoji表情需要4字节存储而utf8字符集最多只能存3字节。解决修改表字符集为utf8mb4。ALTER TABLE tb_comment CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;这里提醒一点改完表结构后别忘了检查数据库连接字符串也要设置charsetutf8mb4否则连接层会把编码转成latin1照样报错。7.3 词云图中文显示为方框现象生成的词云图片中中文全部显示为方块。原因wordcloud库默认字体不支持中文。解决指定中文字体路径。from wordcloud import WordCloud wc WordCloud( font_pathC:/Windows/Fonts/simhei.ttf, # 黑体 width800, height600, background_colorwhite )如果没有simhei.ttf可以用微软雅黑msyh.ttc或者系统里其他中文字体。7.4 SnowNLP情感分析结果偏正面现象分析结果中正面情感占比超过了85%感觉不太符合实际情况。原因SnowNLP默认训练数据来自购物评论本身就偏正面倾向。加上服装类评论的语气本身就普遍友好所以正面比例会高。解决两种思路。一是调整情感判定阈值把正面标准从0.7提到0.8二是自己标注一批负面评论加入训练集重新训练模型。从我实际效果看第二种思路提升更明显。7.5 爬虫采集时触发验证码现象采集几个视频后页面弹出滑块验证码采集线程退出。原因请求频率太高触发了抖音的风控机制。解决降低采集频率每个视频之间等待5-8秒。同时不要多线程并发采集同一个账号下的视频能有效减少触发验证码的概率。国内IP和登录状态下的触发概率也明显低于未登录状态建议用登录后的Cookie采集。7.6 分析结果中存在大量无效评论现象分词统计的时候出现大量类似“哈哈哈”“啊啊啊”“666”这样的低价值词汇。原因网络用语和语气词在评论里天然高频但它们对分析没有实质帮助。解决建立一个停用词表把无意义词过滤掉。词表可以自己维护也可以在GitHub上找中文停用词表结合项目场景扩展。stop_words set([ 哈哈哈,啊啊啊,666,哈哈哈,哈哈,哈哈,啊,呢,吗, 的,了,在,是,我,你,他,她,它,就,都,也,很,还,又,再 ]) filtered_words [w for w in jieba.lcut(text) if w not in stop_words and len(w) 1]7.7 前端图表不显示数据现象页面能打开但图表区域空白F12看到接口返回的JSON为空。原因通常是MySQL数据表为空或者SQL查询语句有误。解决先用日志记录接口收到的请求参数和SQL语句再到数据库客户端手动执行同样的SQL验证。多数情况下是字段名大小写不匹配MySQL在Linux下对表名是区分大小写的而Windows下不区分代码一换环境就踩坑。8. 这套系统还能怎么扩展上面这些都是已经实现的模块。如果你拿到源码后想做得更深入一些我有几个具体的扩展方向按性价比排序扩展一接入更多数据源。目前只分析了抖音的评论区可以扩展小红书、微博的评论数据。不同平台的评论风格差异明显小红书更偏体验分享微博更偏话题讨论多平台融合分析能更全面地刻画品牌口碑。扩展二加入自动生成分析报告功能。每周定时跑一次分析脚本自动生成一份Word或PDF格式的周报包括评论量变化、新增高频词、负面情感评论汇总等。这样整个系统就从“查数据”升级成了“自动输出决策参考”。扩展三基于评论数据做价格舆情监控。如果一个商品在评论区被频繁吐槽“涨价了”“贵”可以自动预警。这部分可以结合关键词匹配规则不需要复杂的模型但落地价值很高。扩展四把爬虫模块替换为更稳定的API方案。如果条件允许可以接入抖音开放平台的合规API来获取评论数据彻底解决风控问题。但申请开服需要企业资质个人毕设项目中先保留爬虫方案即可。我在实际开发中最大的感受是毕业设计的技术难点不在于某一个单独的模块有多难而在于把多个模块串联起来时总会出现各种意料之外的坑。这套系统从设计到跑通我前后花了两周多的时间期间调试爬虫遇到的报错、清洗数据遇到的表情编码问题、Flask接口跨域问题、词云字体问题都记录在项目文档里。最后再分享一个小技巧分析类的毕设项目核心价值不在于你用了一个多高级的算法而在于你能把数据从采集到展示的整条链路完整跑通并且对每一步的结果做业务解读。答辩的时候如果能指着图表说清楚“这个账号的评论区里用户最关心的是尺码和面料负面评价主要集中在掉色和发货速度上”比单纯说“我用了贝叶斯模型做情感分析准确率85%”要有说服力得多。数据是手段业务洞察才是目的。
返回列表