ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

用Python实现中文分词与情感分析:以JDG vs AL赛后虎扑讨论为例

用Python实现中文分词与情感分析:以JDG vs AL赛后虎扑讨论为例 JDG 1:0 AL 这场打完虎扑游戏区的帖子数量、回复速度和热评画风本身就是一份很值得分析的数据样本。与其一遍遍刷帖子看评论不如用 Python 把这轮讨论抓下来做一次中文分词、情感分析和可视化。本文就以“JDG 1:0 AL 赛后虎扑讨论”为场景完整拆解从数据采集、清洗、分析到出图的全流程整个过程可以直接复用到 LPL 其他场次的赛后舆论分析里。先说清楚本文不会教大家去爬取非公开数据也不会针对虎扑的接口做绕过式采集。示例代码的目的是演示“如何对公开讨论内容做文本分析”你在实际使用时需要遵守目标网站的 robots 协议和服务条款控制请求频率只处理公开可见的信息。如果你是刚开始接触 Python 爬虫和文本分析的新手可以按顺序从第一节看到最后如果你已经有基础可以直接跳到第三节看核心代码第四节有完整的项目结构和运行方式。1. 背景与核心概念1.1 为什么要分析赛后论坛热评LPL 比赛结束后虎扑游戏区、各个战队专区会迅速出现大量讨论帖。一场比赛从结束到当晚帖子内容通常包含几种类型战术复盘、选手评价、BP 分析、赛果预测、“开会”性质的吐槽帖以及大量只看热闹的吃瓜回复。这些文本数据有几个特点时效性强比赛结束后的 1 到 4 小时是发帖和回复的高峰期。口语化严重大量网络用语、选手黑称、梗和缩写。情绪表达密集情感倾向非常鲜明。内容结构松散一条评论可能只有几个字也可能是一个长段落。如果把虎扑相关讨论帖和评论抓下来用程序跑一遍分词、词频统计、情感分析再配合可视化图表就能从“感觉舆论炸了”变成“舆论具体炸在哪里、主要情绪是什么、讨论焦点是什么”。本文选用的场景是 JDG 对阵 AL 的比赛比赛结果是 JDG 1:0 AL。这个比分是整篇文章的数据场景锚点代码里也以这个场景作为示例输入。1.2 涉及的核心技术完成这个分析项目需要用到以下技术点技术作用requests发送 HTTP 请求获取网页或接口数据pandas数据清洗、去重、表格化处理jieba中文分词把句子拆成词语SnowNLP中文文本情感倾向打分wordcloud根据词频生成词云图matplotlib / pyecharts绘制柱状图、饼图、趋势图其中 jieba 和 SnowNLP 是纯 Python 实现的库不需要额外安装复杂的底层依赖对新手比较友好。1.3 需要区分几个容易混淆的概念分析论坛文本时有三个概念经常被混用在这里先做一个区分爬虫Crawler按照一定规则自动抓取网页数据的程序。它解决的是“数据从哪来”的问题。分词Segmentation把连续的汉字序列按语义拆成词语。比如“JDG赢了”拆成“JDG / 赢了”。它解决的是“计算机怎么读懂中文”的问题。情感分析Sentiment Analysis判断一段文本表达的是正面、负面还是中性情绪。它解决的是“舆论整体情绪是什么”的问题。三个技术是流水线关系爬虫拿到原始数据分词把数据变成可统计的词项情感分析在分词结果之上做情绪判断。2. 环境准备与版本说明本文示例默认使用以下环境你本机的版本不需要完全一致但建议尽量接近操作系统Windows 10 / 11 或 macOS 均可Python 版本3.8 及以上IDEVS Code 或 PyCharm也可以用 Jupyter Notebook 分步运行核心依赖库requests、pandas、jieba、snownlp、wordcloud、matplotlib如果版本需要根据你的项目实际情况调整本文以通用、常见环境为例重点演示配置思路和代码逻辑。2.1 安装依赖库建议先创建虚拟环境再安装依赖。在项目根目录打开终端执行python -m venv venvWindows 激活虚拟环境venv\Scripts\activatemacOS / Linux 激活虚拟环境source venv/bin/activate然后安装依赖pip install requests pandas jieba snownlp wordcloud matplotlib安装完成后可以用下面的命令确认是否成功python -c import jieba, snownlp, wordcloud; print(dependency ok)如果没有输出报错说明依赖安装成功。2.2 项目结构规划为了方便后续维护和扩展建议按下面的结构组织项目hupu_lol_analysis/ ├── config.py # 请求头、基础配置 ├── spider.py # 帖子链接采集、评论采集 ├── clean.py # 数据清洗 ├── analyze.py # 分词与情感分析 ├── visual.py # 可视化出图 ├── main.py # 主程序入口 ├── data/ │ ├── raw_posts.json # 原始帖子数据 │ ├── raw_comments.json # 原始评论数据 │ ├── cleaned_comments.csv # 清洗后的数据 │ └── sentiment_result.csv # 情感分析结果 └── output/ ├── wordcloud.png # 词云图 ├── sentiment_pie.png # 情感分布饼图 └── hot_words_bar.png # 高频词柱状图这个结构把“采集、清洗、分析、可视化”四个阶段拆成独立模块任何一个阶段出问题只需要单独调试对应文件。3. 核心原理拆解3.1 数据采集从 HTML 或接口中提取信息爬虫的核心思路是“模拟浏览器发起请求接收响应再解析响应内容”。以虎扑论坛为例一个典型的帖子列表页会包含帖子标题、作者、回复数、浏览数和帖子链接。这些信息通常有两种存在形式直接写在 HTML 里需要用解析库提取。由页面加载时异步请求接口返回 JSON 数据直接在 JSON 里取字段。第二种方式更稳定。因为 JSON 数据结构清晰不需要处理复杂的 HTML 标签。下面是一个简化版的抓取思路示例注意这里只演示逻辑不针对任何具体接口做过拟合# 文件路径spider.py核心片段非完整程序 import requests def fetch_json(url, headers): 发送 GET 请求并解析 JSON 响应 try: resp requests.get(url, headersheaders, timeout10) resp.raise_for_status() return resp.json() except requests.RequestException as e: print(f请求失败: {e}) return None这里的headers是请求头用来告诉服务器“这是一个正常的浏览器请求”。合法的请求头至少应该包含User-Agent后面会在 config.py 里统一配置。关键点在于requests 只负责拿数据不负责解析数据。解析数据的工作要自己写代码完成这也是爬虫项目中比较容易出错的环节。3.2 数据清洗去掉噪声文本从网页或接口拿到的原始文本通常很脏常见问题有字符串里混入 HTML 标签比如span、br。评论里包含大量空行、空格、特殊符号。同一个用户重复发同样内容。文本里包含表情符号或不可见字符。这些脏数据如果不处理会直接影响分词和词频统计的结果。比如“\u3000”这种全角空格会占用词频统计的额度导致真正有价值的词被挤掉。清洗的原则是在保留有效信息的前提下尽可能去除无关字符。示例代码如下# 文件路径clean.py import re import pandas as pd def clean_text(text): 清洗单条文本 if not isinstance(text, str): return # 去除 HTML 标签 text re.sub(r[^], , text) # 去除 URL text re.sub(rhttp[s]?://\S, , text) # 去除 用户 text re.sub(r\S, , text) # 去除全角空格和其他空白符 text re.sub(r\s, , text) # 只保留中英文、数字和常见标点 text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9。、], , text) return text.strip() def clean_comment_frame(df): 对评论 DataFrame 执行批量清洗 df[cleaned] df[content].apply(clean_text) # 去掉清洗后为空的行 df df[df[cleaned] ! ] # 按内容去重同一个用户重复发言保留一条 df df.drop_duplicates(subset[user, cleaned]) return df正则表达式是关键。\u4e00-\u9fa5是中文汉字的 Unicode 编码范围a-zA-Z0-9是英文字母和数字后面的中文标点符号单独列出来保留。这样清洗后剩下的文本基本只有有效内容。3.3 中文分词让计算机“读懂”中文中文和英文最大的区别是词之间没有天然的空格分隔。英文可以按空格直接切分中文必须依赖分词算法。jieba 是 Python 里最常用的中文分词库它支持三种模式模式说明适用场景精确模式最精确地切分适合文本分析词频统计全模式把所有可能的词都切出来速度快但有冗余搜索引擎分词搜索引擎模式在精确模式基础上对长词再次切分搜索建议示例import jieba text JDG赢下AL这场比赛虎扑讨论区热闹翻了 words jieba.lcut(text, cut_allFalse) print(words) # 输出类似[JDG, 赢下, AL, 这, 场, 比赛, , 虎扑, 讨论区, 热闹, 翻, 了]注意上面输出是示意结果实际分词可能根据 jieba 版本和词典略有差异。这里有一个实际项目中必须处理的问题很多游戏术语和选手名字默认词典里没有。比如“纳尔”“盲僧”“小虎”“theshy”等词jieba 可能会错误地切开。解决办法是往 jieba 里添加自定义词典import jieba custom_words [ JDG, AL, 纳尔, 盲僧, 打野, 上单, 中单, ADC, 辅助, 团战, 运营, 翻盘, 小龙, 大龙, BP ] for word in custom_words: jieba.add_word(word)jieba.add_word可以动态加入单个词语权重更高也可以用一个userdict.txt文件批量加载适合维护大量专有名词。3.4 情感分析量化舆论情绪SnowNLP 是一个中文文本处理库内置了一个训练好的情感分类模型。它的sentiments属性会返回一个 0 到 1 之间的浮点数数值越接近 1表示情感越正面。数值越接近 0表示情感越负面。0.5 附近表示情绪相对中性。示例from snownlp import SnowNLP text1 JDG今天打得真好纪律性拉满了 text2 这个BP我是真的看不懂 s1 SnowNLP(text1).sentiments s2 SnowNLP(text2).sentiments print(s1) # 大概率接近 1 print(s2) # 大概率接近 0SnowNLP 的优点是开箱即用缺点也很明显默认模型是基于电商评论语料训练的对游戏圈的网络用语、阴阳怪气的表达判断不一定准确。在实际项目中更推荐的做法是先用 SnowNLP 做初步情感打分快速看整体分布。对明显偏差的数据做人工抽检。条件允许的情况下用自己标注的数据集微调模型或者接入大模型 API 做更细粒度的情感分类。3.5 可视化让数据说话分析结果光有数字不够直观还需要图表辅助表达。本文用两个图词云图展示讨论中出现频率最高的词汇直观感受舆论焦点。情感分布饼图展示正面、中性、负面评论的占比量化舆论倾向。wordcloud 库生成词云时需要指定中文字体路径否则中文会显示成方框。Windows 系统一般用C:\Windows\Fonts\simhei.ttfmacOS 一般用/System/Library/Fonts/PingFang.ttc具体路径需要根据自己系统调整。4. 完整实战案例下面按照项目结构实现一个完整的“JDG 1:0 AL 赛后虎扑讨论分析”小工具。4.1 配置模块 config.py# 文件路径config.py 基础配置请求头、URL 模板、自定义词典 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: application/json, text/plain, */*, Referer: https://bbs.hupu.com/, } # 示例接口地址模板 # 注意真实使用时请以目标网站实际接口为准这里仅作占位演示 LIST_API_TEMPLATE https://example.com/api/match_posts?match_id{match_id}page{page} COMMENT_API_TEMPLATE https://example.com/api/comment_list?post_id{post_id}page{page} # 比赛场景参数 MATCH_ID jdg_vs_al # 示例 ID实际使用时替换为真实比赛 ID # 自定义分词词典 CUSTOM_WORDS [ JDG, AL, LPL, 打野, 上单, 中单, ADC, 辅助, 团战, 运营, 翻盘, BP, 纳尔, 盲僧, 选手, 教练, 虎扑, ] # 词云字体路径按实际系统调整 FONT_PATH C:/Windows/Fonts/simhei.ttf配置模块的好处是所有需要调整的参数集中在一个文件里不需要在代码里到处改。4.2 爬虫模块 spider.py# 文件路径spider.py 数据采集模块获取比赛相关帖子和评论 import json import time import requests from config import HEADERS, LIST_API_TEMPLATE, COMMENT_API_TEMPLATE, MATCH_ID def fetch_json(url): 发送请求并返回 JSON 数据 try: resp requests.get(url, headersHEADERS, timeout10) resp.raise_for_status() return resp.json() except requests.RequestException as e: print(f请求失败: {url}, 错误: {e}) return None def get_post_list(match_id, max_pages5): 获取比赛相关帖子列表 posts [] for page in range(1, max_pages 1): url LIST_API_TEMPLATE.format(match_idmatch_id, pagepage) data fetch_json(url) if not data: break # 假设返回结构为 data 里的 list 字段 page_posts data.get(data, {}).get(list, []) if not page_posts: break for item in page_posts: posts.append({ post_id: item.get(post_id), title: item.get(title), reply_count: item.get(reply_count), view_count: item.get(view_count), author: item.get(author), created_at: item.get(created_at), }) # 控制请求频率避免对服务器造成压力 time.sleep(1) print(f共获取到 {len(posts)} 个帖子) return posts def get_comments(post_id, max_pages3): 获取指定帖子的评论 comments [] for page in range(1, max_pages 1): url COMMENT_API_TEMPLATE.format(post_idpost_id, pagepage) data fetch_json(url) if not data: break page_comments data.get(data, {}).get(list, []) if not page_comments: break for item in page_comments: comments.append({ post_id: post_id, user: item.get(user_name), content: item.get(content), like_count: item.get(like_count), created_at: item.get(created_at), }) time.sleep(0.5) return comments def save_json(data, path): 把数据保存为 JSON 文件 with open(path, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) if __name__ __main__: posts get_post_list(MATCH_ID, max_pages3) save_json(posts, data/raw_posts.json) all_comments [] for post in posts[:5]: # 先分析前 5 个帖子避免请求过多 comments get_comments(post[post_id], max_pages2) all_comments.extend(comments) time.sleep(1) save_json(all_comments, data/raw_comments.json) print(f共采集评论 {len(all_comments)} 条)这段代码有几个关键设计time.sleep()用于控制请求频率避免对服务器造成过大压力。fetch_json统一处理请求异常避免某个帖子失败导致整个程序崩溃。先保存原始数据再做后续分析方便排查问题。需要特别说明的是LIST_API_TEMPLATE这里的 URL 是占位示例真实的虎扑接口地址、参数格式、返回结构需要你根据目标网站的实际页面情况去观察。本文的重点是整体流程设计而不是某一个具体接口的硬编码。4.3 数据清洗模块 clean.py# 文件路径clean.py 数据清洗模块 import re import pandas as pd from config import CUSTOM_WORDS def clean_text(text): 清洗单条文本 if not isinstance(text, str): return text re.sub(r[^], , text) text re.sub(rhttp[s]?://\S, , text) text re.sub(r\S, , text) text re.sub(r\s, , text) text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9。、], , text) return text.strip() def load_comments_to_df(raw_path): 加载 JSON 原始评论并转成 DataFrame df pd.read_json(raw_path) df[cleaned] df[content].apply(clean_text) df df[df[cleaned] ! ] df df.drop_duplicates(subset[user, cleaned]) return df def add_userdict(): 把自定义词典加入 jieba import jieba for word in CUSTOM_WORDS: jieba.add_word(word) if __name__ __main__: df load_comments_to_df(data/raw_comments.json) df.to_csv(data/cleaned_comments.csv, indexFalse, encodingutf-8-sig) print(f清洗后剩余评论 {len(df)} 条)这里有个细节保存 CSV 时用了utf-8-sig编码而不是普通的utf-8。原因是 Excel 直接打开utf-8编码的 CSV 时会出现中文乱码utf-8-sig带了 BOM 头Excel 能正确识别。4.4 分析与情感模块 analyze.py# 文件路径analyze.py 文本分析与情感计算模块 import jieba import pandas as pd from collections import Counter from snownlp import SnowNLP from clean import add_userdict def tokenize_and_count(df, top_n30): 对清洗后的评论做分词并统计词频 add_userdict() word_counter Counter() for text in df[cleaned]: words jieba.lcut(text, cut_allFalse) # 过滤单字、纯数字和常见停用词 words [w for w in words if len(w) 1 and not w.isdigit()] word_counter.update(words) return word_counter.most_common(top_n) def sentiment_score(text): 返回 SnowNLP 情感得分 if not text: return 0.5 return SnowNLP(text).sentiments def analyze_sentiment(df): 对整个 DataFrame 执行情感分析 df[sentiment] df[cleaned].apply(sentiment_score) def label(score): if score 0.6: return 正面 elif score 0.4: return 负面 else: return 中性 df[sentiment_label] df[sentiment].apply(label) return df if __name__ __main__: df pd.read_csv(data/cleaned_comments.csv) df analyze_sentiment(df) df.to_csv(data/sentiment_result.csv, indexFalse, encodingutf-8-sig) hot_words tokenize_and_count(df, top_n20) for word, count in hot_words: print(f{word}: {count}) label_counts df[sentiment_label].value_counts() print(label_counts)情感阈值这里取了 0.6 和 0.4这个阈值不是固定标准。你可以先跑一次看结果分布再根据实际语料调整。如果明显感觉整体得分偏高可以把正面阈值提高到 0.65 或 0.7。4.5 可视化模块 visual.py# 文件路径visual.py 可视化模块 import matplotlib.pyplot as plt from wordcloud import WordCloud from config import FONT_PATH def draw_wordcloud(freq_dict, output_path): 根据词频字典生成词云图 wc WordCloud( font_pathFONT_PATH, width1200, height800, background_colorwhite, max_words100, ) wc.generate_from_frequencies(freq_dict) plt.figure(figsize(12, 8)) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.savefig(output_path, dpi150, bbox_inchestight) plt.close() def draw_sentiment_pie(label_counts, output_path): 绘制情感分布饼图 plt.figure(figsize(8, 8)) labels list(label_counts.index) sizes list(label_counts.values) colors [#4CAF50, #F44336, #FFC107] plt.pie(sizes, labelslabels, colorscolors[: len(labels)], autopct%1.1f%%, startangle90) plt.title(赛后期评论情感分布) plt.savefig(output_path, dpi150, bbox_inchestight) plt.close() def draw_hot_words_bar(hot_words, output_path): 绘制高频词柱状图 plt.figure(figsize(12, 6)) words [w for w, _ in hot_words] counts [c for _, c in hot_words] plt.barh(words[::-1], counts[::-1], color#2196F3) plt.xlabel(出现次数) plt.title(赛后讨论高频词 Top 20) plt.tight_layout() plt.savefig(output_path, dpi150, bbox_inchestight) plt.close()词云图这里用generate_from_frequencies而不是generate。区别在于前者直接接收一个“词语: 词频”的字典不需要再把文本拼成字符串让 wordcloud 重新分词效率和可控性都更好。4.6 主程序 main.py# 文件路径main.py 主程序串联采集、清洗、分析、可视化全流程 import pandas as pd from collections import Counter from spider import get_post_list, get_comments, save_json from clean import load_comments_to_df from analyze import analyze_sentiment, tokenize_and_count from visual import draw_wordcloud, draw_sentiment_pie, draw_hot_words_bar from config import MATCH_ID def main(): print( 1. 数据采集 ) posts get_post_list(MATCH_ID, max_pages3) if not posts: print(没有获取到帖子流程结束) return save_json(posts, data/raw_posts.json) all_comments [] for post in posts[:5]: comments get_comments(post[post_id], max_pages2) all_comments.extend(comments) save_json(all_comments, data/raw_comments.json) print(f采集完成共 {len(all_comments)} 条评论) print( 2. 数据清洗 ) df load_comments_to_df(data/raw_comments.json) df.to_csv(data/cleaned_comments.csv, indexFalse, encodingutf-8-sig) print(f清洗完成剩余 {len(df)} 条评论) print( 3. 情感分析 ) df analyze_sentiment(df) df.to_csv(data/sentiment_result.csv, indexFalse, encodingutf-8-sig) label_counts df[sentiment_label].value_counts() print(情感分布) print(label_counts) print( 4. 分词与词频统计 ) hot_words tokenize_and_count(df, top_n20) for word, count in hot_words: print(f{word}: {count}) print( 5. 可视化 ) freq_dict dict(hot_words) draw_wordcloud(freq_dict, output/wordcloud.png) label_counts df[sentiment_label].value_counts() draw_sentiment_pie(label_counts, output/sentiment_pie.png) # 画高频词图之前把 hot_words 反转成 (次数, 词) 排序保证横向条形图从高到低 hot_words_sorted sorted(hot_words, keylambda x: x[1], reverseTrue) draw_hot_words_bar(hot_words_sorted, output/hot_words_bar.png) print( 分析完成图片已保存到 output 目录 ) if __name__ __main__: main()4.7 运行与验证cd 到项目根目录依次执行python spider.py python clean.py python analyze.py python visual.py或者直接运行主程序python main.py预期输出大致如下 1. 数据采集 共获取到 12 个帖子 采集完成共 236 条评论 2. 数据清洗 清洗完成剩余 210 条评论 3. 情感分析 情感分布 负面 98 正面 72 中性 40 4. 分词与词频统计 JDG: 45 AL: 38 团战: 29 打野: 25 运营: 18 BP: 15 ... 5. 可视化 分析完成图片已保存到 output 目录 上面的数字是示例输出用来帮助你判断程序的运行模式是否正确。你实际抓取到的数据量、词频、情感分布取决于当时的比赛进程、讨论热度和你采集的帖子数量。如果评论量特别少建议调大max_pages或者扩大帖子筛选范围。4.8 结果说明跑完整个流程后你应该得到三类产物清洗后的 CSV 数据表包含原始评论、清洗后文本、情感得分、情感标签。这一份是最基础的“分析底稿”。词云图一眼看出讨论焦点。如果“打野”“团战”“BP”这类词特别大说明讨论集中在比赛过程如果某个选手名字特别大说明焦点在个人表现上。情感分布图量化乐观派和悲观派的比例。正面评论多说明舆论认可度高负面评论多说明“开会”倾向明显。以 JDG 1:0 AL 这场为例1:0 的比分意味着比赛可能比较胶着也可能是一方碾压。不同比赛内容会直接影响评论的情绪走向。技术分析的目的是把“感觉上的舆论”变成“可视化的舆论”至于舆论是否客观那是另一个层面的问题。5. 常见问题与排查思路在实际运行项目时最常遇到的问题集中在采集和中文处理两个环节。这里整理了一份排查清单问题现象常见原因解决思路请求返回 403 Forbidden请求头不完整或者触发反爬策略补充完整 User-Agent、Referer降低请求频率检查是否需要登录后才能访问请求超时目标网站响应慢或被限流调大 timeout增加重试机制延长 sleep 时间JSON 解析报错接口返回的不是 JSON可能是 HTML 或空内容先用resp.text打印前 500 个字符确认返回内容检查 URL 参数是否完整中文字体显示为方框wordcloud 未指定中文字体路径在 WordCloud 构造时传font_path路径指向系统已安装的中文字体CSV 用 Excel 打开乱码保存时用了utf-8编码改用encodingutf-8-sig保存分词结果里大量单字默认词典不包含游戏术语用jieba.add_word添加自定义词把常用停用词过滤掉SnowNLP 全部评论都偏正面默认模型不匹配游戏语料调整情感阈值人工抽检部分结果考虑用更合适的模型评论去重后数量骤减同一个用户刷屏或内容模板化检查drop_duplicates的 subset 字段如果希望保留刷屏现象就不要按用户去重程序跑到一半中断某个请求抛异常导致主流程终止为每个帖子增加 try-except把已采集的数据分批保存如果出现无法确定原因的问题建议按下面的顺序排查先单独请求一个 URL用curl或浏览器开发者工具确认能否拿到数据。打印响应内容的前 500 个字符确认数据格式。把异常堆栈信息完整贴出来不要只看最后一行报错。检查数据文件是否已经成功生成定位是采集阶段还是分析阶段的问题。6. 最佳实践与工程建议6.1 采集阶段的合规与性能爬虫不是“能跑就行”生产环境的采集程序必须考虑合规、性能和稳定性。这里给出几条建议遵守目标网站的规则。使用前查看网站服务条款和 robots 协议不要对非公开数据、登录后可见的数据做强制采集。控制请求频率。单线程加合理间隔比高并发更安全。比赛讨论类数据并不会有太高的实时性要求慢一点没关系。加随机延时。固定间隔容易被识别可以在 1 到 3 秒之间随机延时。做好失败重试。对 500、502、503 这类临时错误可以重试 2 到 3 次对 403、404 这类确定性错误不需要重试。分批保存。不要等全部采集完再落盘每采集一部分就保存一次防止程序中断导致数据全丢。6.2 数据清洗的边界清洗可以适度但不要过度。把表情、乱码、HTML 标签去掉是合理的但如果你把“菜的抠脚”这类表达中的关键词误删就会丢失重要信息。建议的做法是清洗前先保存原始数据。清洗时只去掉确定无用的内容比如标签、URL、用户。清洗后人工抽查 20 到 50 条确认没有误删有效内容。6.3 情感分析的局限SnowNLP 默认模型对游戏圈文本的适配性一般这一点要有清醒认识。比如“我上我也行”这句话字面看是正面实际可能是嘲讽再比如“这波不亏”可能是反向表达。在项目中使用情感分析结果时建议把它当作“趋势参考”而不是“绝对结论”。更重要的是不要对单条评论的情感标签过度依赖要看整体分布。如果 200 条评论里负面占 60%这个比例本身比某一条评论是不是被判错更有分析价值。6.4 代码结构分层本文的项目结构刻意做了模块拆分这种分层在后续扩展时特别有用。比如如果不想爬虫想直接读别人导出的数据文件只需要替换spider.py。如果不想用 SnowNLP想换大模型接口只需要改analyze.py里的sentiment_score。如果想新增“讨论热度随时间变化”的分析只需要在clean.py里把created_at字段解析成时间特征然后在visual.py里加一个折线图函数。模块之间只通过数据文件传递信息低耦合方便单测和排错。6.5 日志与监控工程化代码建议加日志而不是全靠print。可以用 Python 标准库logging把运行时间、采集数量、异常信息记录到文件里。这样即使隔天再看运行结果也能知道当天发生了什么。import logging logging.basicConfig( filenamelogs/analysis.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, )6.6 数据量变大后的扩展方向如果只是分析一场比赛几百条评论用 pandas 完全够用。但如果要分析整个赛季几十场比赛、几万条评论建议考虑把数据存入 SQLite 或 MySQL而不是散落在 JSON 文件里。用统一的match_id字段关联比赛、帖子、评论三层数据。把分词结果提前缓存避免每次重复分词。把情感分析改为异步批量处理提高吞吐量。7. 总结与学习路线本文以 JDG 1:0 AL 的赛后虎扑讨论为场景完成了一个完整的文本分析流程用 requests 采集比赛相关帖子和评论。用正则表达式和 pandas 做数据清洗。用 jieba 做中文分词和词频统计。用 SnowNLP 做情感打分和倾向分类。用 wordcloud 和 matplotlib 输出词云、饼图、柱状图。这个流程可以迁移到很多场景不只是 LPL 比赛。比如 NBA 赛后讨论、新品发布会网友评价、某部剧播出后的弹幕情感分析核心逻辑都是一样的采集文本、清洗、分词、统计、可视化。如果你想在这个基础上继续深入下面几个方向比较值得投入爬虫进阶学习 Scrapy 框架、请求代理池、验证码处理解决更大规模数据采集问题。文本分析进阶学习 TF-IDF、TextRank 关键词提取了解 LDA 主题模型做更深入的议题挖掘。情感模型优化自己标注一批游戏评论数据微调一个更适合游戏语料的情感分类模型。可视化进阶用 pyecharts 做交互式图表或者把分析结果做成自动化的日报看板。大模型应用用大模型对评论做摘要、观点聚类、选手口碑分析比传统模型更适应网络用语。最后提醒一句技术是用来降低信息处理成本的不要为了“分析”而分析。JDG 1:0 AL 这场比赛真正的看点、讨论焦点、选手发挥永远需要结合比赛录像和战术数据一起看。文本分析能告诉你“舆论在聊什么、情绪偏向哪边”但它不会告诉你“谁说得对”。把技术工具和比赛理解结合起来才能做出真正有价值的赛后分析。如果本文对你有帮助建议先跑通main.py的整个流程再动手修改自定义词典和情感阈值。第一次跑通完整流程比研究任何单独某个库的细节都更有价值。
返回列表