中文微博评论的Python文本分析:从清洗分词到情感词频统计
2026/9/16 15:11:58 网站建设 项目流程

简介:面向微博评论文本分析场景的Python脚本,适合初学文本处理或对社交媒体数据感兴趣的开发者参考。压缩包内包含1个Python源文件,整体仅2KB,轻量且易于阅读修改。脚本围绕微博评论数据展开,覆盖从获取、清洗到分析的常见流程:在文本层面涉及字符串分割、标点与停用词清理、数字与特殊字符过滤;在数据层面借助日期时间解析与表格结构处理评论、转发等字段;同时涉及网络请求、自然语言处理基础操作及可视化手段,帮助读者理解情感倾向、词频分布等分析思路。项目中还体现了异常处理和模块化设计,可作为学习代码组织方式的微型样例;整体将数据爬取、清洗、统计、可视化等步骤串联起来,便于快速把握轻量文本分析脚本的结构。资源已有145人学习,适合作为个人练习或小规模课程的入门材料。

1. 从 my_text_test.zip 说起:微博评论文本分析能解决什么问题

如果你手头正好有一个名为my_text_test.zip的压缩包,解压后里面是my_text命名的 Python 代码文件,那它十有八九是一个以“微博评论 + 文本分析”为核心的小型项目骨架。这类项目的典型诉求是:把微博评论这种短文本、口语化、噪声大的数据,用 Python 脚本跑成词频、情感倾向、话题热点之类的可量化结果,而不是靠人一条条刷屏去读。my_text_test.zip通常打包了主代码my_text.py、测试用的 CSV 或 JSON 样本,以及一份依赖清单,适合用来快速验证“从数据到结论”这条管线是否走得通。

这类项目对三类人最有价值:一是刚学完 Python 基础语法、想拿真实中文语料练手的入门者;二是运营或产品岗位的技术同学,需要用脚本替代手工整理微博评论;三是想复用一套通用文本分析框架的开发者——把微博评论的采集和清洗换成其他短文本语料,核心思想完全一致。本文就按“数据怎么进、文本怎么洗、分析怎么算、结果怎么验”这条链路展开,每一步都给可复现的命令和代码。

2. 微博评论数据获取:把评论文档整理成 my_text_test 可读的输入

2.1 评论数据从哪来:优先用可控的数据入口而不是页面解析

做微博评论分析,第一步卡在数据获取。my_text_test.zip里的my_text代码一般不会内置爬虫,它更关心的是“拿到评论之后怎么分析”。常见做法是:通过微博开放平台申请接口权限,或者从自己管理的账号后台导出评论数据,再或者使用公开的微博评论数据集做离线实验。我一般会建议先把数据落成 JSON Lines 或 CSV,每行一条评论,字段不要贪多,保留comment_iduser_idcreated_attext四个字段就够起步。

直接去解析网页 HTML 在微博场景里非常脆弱:页面结构频繁调整、登录态校验复杂、接口签名参数多,维护成本远高于收益。如果你只是做技术验证,优先用自己可控的数据源,把精力放在分析环节。下面这段代码演示如何把原始评论文档整理成后续分析需要的标准格式:

import json import re from pathlib import Path def load_comments_from_csv(csv_path: str) -> list[dict]: """读取微博评论 CSV,输出统一结构的评论列表""" import csv comments = [] with open(csv_path, encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: text = re.sub(r"\s+", " ", row.get("评论内容", "")).strip() if not text: continue comments.append({ "comment_id": row.get("评论ID", ""), "user_id": row.get("用户ID", ""), "created_at": row.get("发布时间", ""), "text": text, }) return comments # 使用示例 # comments = load_comments_from_csv("weibo_comments.csv") def save_as_jsonl(comments: list[dict], output_path: str = "weibo_comments.jsonl") -> None: """以 JSON Lines 格式保存,方便 my_text.py 后续逐行处理""" with open(output_path, "w", encoding="utf-8") as f: for item in comments: f.write(json.dumps(item, ensure_ascii=False) + "\n") # 执行 # save_as_jsonl(comments)

这段代码做两件事:从 CSV 读取评论并剔除空白字符残留,然后转存为 JSONL。JSONL 的好处是每行一条独立记录,my_text代码读取时可以逐行处理,不必一次性把全部数据载入内存;对微博评论这种动辄上万条的数据量,这种流式处理方式能明显减少内存压力。

2.2 my_text 代码的输入约定:字段命名与编码细节

如果你的my_text_test.zip解压后主代码叫my_text.py,它多半已经定义好了对输入字段的预期。常见约定是读取一个名为comments.jsonl的文件,字段名和上面代码输出的一致。如果字段名不一致,你需要做一层映射,而不是去改主代码——保留原始数据字段,在读取时重命名,这样换数据源时不用改分析逻辑。

编码是另一个高频坑。Windows 下导出的 CSV 经常是 GBK 编码,直接open会抛UnicodeDecodeError。读取时显式指定编码,或者失败后回退到 GBK:

def open_with_fallback(path: str): try: return open(path, encoding="utf-8") except UnicodeDecodeError: return open(path, encoding="gbk")

提示:Windows 用户建议在项目根目录建一个run.bat,内容写chcp 65001后再执行 Python 脚本,能避免终端里中文打印乱码的问题。

3. 文本清洗与分词:my_text 代码里的预处理链路

3.1 清洗规则:微博评论里的噪声比普通文本多在哪

微博评论的中文文本分析,难点不在分词算法本身,而在于噪声处理。一条典型评论长这样:"哈哈哈哈哈太真实了!//@某大V:转发微博 // 理性讨论[赞] #话题# https://t.cn/xxx"。这里既有转发标记、@用户、话题标签,还有 URL 和表情符号,如果不过滤就直接分词,词频统计里会混入大量无意义符号。my_text代码里通常会用一段正则把这些模式统一清掉。

import re def clean_comment(text: str) -> str: """清洗微博评论文本:去URL、@用户、话题标签、表情符号、连续重复标点""" # 去 URL text = re.sub(r"https?://\S+", "", text) # 去 @用户 text = re.sub(r"@[\w\u4e00-\u9fa5\-]+", "", text) # 去 话题标签 #...#,保留标签内的词 text = re.sub(r"#([^#]+)#", r"\1", text) # 去 转发标记 text = re.sub(r"//\s*", " ", text) # 去 方括号表情 [赞]、[泪] 等 text = re.sub(r"\[[\u4e00-\u9fa5]{1,4}\]", "", text) # 连续重复标点压缩为单个 text = re.sub(r"([,。!?!?,.]){2,}", r"\1", text) # 连续重复汉字压缩:"哈哈哈哈哈" -> "哈哈哈"(保留3个) text = re.sub(r"([\u4e00-\u9fa5])\1{3,}", r"\1\1\1", text) return text.strip()

参数说明:@[\w\u4e00-\u9fa5\-]+中的\w匹配字母数字下划线,\u4e00-\u9fa5匹配中文字符,\-把连字符也纳入用户名范围,避免截断中文昵称。连续重复汉字压缩到 3 个是经验值,因为“哈哈哈”已经能表达语气,再多就是纯噪声。清洗后的效果示例:"哈哈哈哈哈太真实了!"变成"哈哈哈太真实了!""//@某大V:转发微博"被整体移除。

3.2 分词与停用词:jieba 的自定义词典和停用词表怎么配

清洗之后进入分词环节。微博评论是社交短文本,大量使用网络词汇,比如“集美”“绝绝子”“破防”,这些词 jieba 默认词库里没有,会被切成单字。解决办法是让my_text.py加载一份自定义词典。常见做法是在项目里放一个user_dict.txt,每行一个词,格式为“词 词频 词性”,词频可以不写,jieba 会用默认值。

import jieba import jieba.analyse # 加载自定义词典,解决网络新词被错误切分的问题 jieba.load_userdict("user_dict.txt") # 启用并行分词,适合大规模评论;注意 Windows 下需放在 if __name__ == "__main__" 内 # jieba.enable_parallel(4) STOPWORDS = set() with open("stopwords.txt", encoding="utf-8") as f: for line in f: word = line.strip() if word: STOPWORDS.add(word) def tokenize(text: str) -> list[str]: """jieba 精确模式分词 + 停用词过滤 + 单字过滤""" words = jieba.lcut(text, cut_all=False) result = [] for w in words: w = w.strip() if not w: continue if w in STOPWORDS: continue # 去掉纯标点和单字语气词 if len(w) == 1 and not w.isdigit(): continue result.append(w) return result # 使用示例 # tokens = tokenize("哈哈哈太真实了,这波操作绝绝子") # ['哈哈哈', '真实', '这波', '操作', '绝绝子']

参数说明:jieba.lcut(text, cut_all=False)用精确模式,适合做词频、关键词提取这类需要准确边界的任务;cut_all=True是全模式,召回率高但会产生冗余词,不适合文本分析。“单字过滤”这里要谨慎——如果文本是“这个人真牛”,分词后“牛”是单字,但它是有效词。所以在过滤单字前,可以先查一遍自定义词典,把有意义的单字词放进去绕过过滤。

停用词表的获取不需要自己从头整理,常见的做法是下载一个开源中文停用词表,再往里面追加微博特色的词,比如“哈哈哈”“转发”“分享”“网页链接”这类在评论里高频但无分析价值的词。追加式维护的好处是:不同项目的停用词集合有差异,但基础表是通用的。

提示:Windows 下使用jieba.enable_parallel(4)会报错,因为多进程在 Windows 的 spawn 模式下必须在if __name__ == "__main__"保护内调用。文本量不到 10 万条时,单线程性能完全够用,不建议轻易开并行。

4. 微博评论的情感分析与词频统计:让 my_text 输出有业务含义的结果

4.1 基于情感词典的评论打分:不做训练也能判断正负向

微博评论分析里,情感判断是最高频的需求。你不需要一上来就上机器学习模型,基于情感词典的打分法在短文本场景下非常有效。基本思路是:准备一份带情感分值的中文词典,正面词记为正分,负面词记为负分,评论的总体情感分数就是所有命中词的分值之和。my_text.py里可以内置一个小型情感词典,也可以从外部加载。

import json from collections import Counter # 情感词典示例:实际使用时可加载完整词典,如 BosonNLP 情感词典 SENTIMENT_DICT = { "喜欢": 2.0, "好评": 2.5, "满意": 2.0, "赞": 1.5, "推荐": 2.0, "差评": -2.5, "垃圾": -3.0, "失望": -2.0, "坑": -1.5, "退钱": -2.0, "绝绝子": 1.8, "破防": -1.2, # 自定义网络情感词 } def analyze_sentiment(tokens: list[str]) -> dict: """基于情感词典的简单打分,返回分数和命中词""" score = 0.0 hit_words = [] for word in tokens: if word in SENTIMENT_DICT: score += SENTIMENT_DICT[word] hit_words.append(word) if score > 0.5: label = "positive" elif score < -0.5: label = "negative" else: label = "neutral" return {"score": round(score, 2), "label": label, "hit_words": hit_words} # 单条评论情感分析 # tokens = tokenize("物流太慢了,差评!") # print(analyze_sentiment(tokens)) # {'score': -2.5, 'label': 'negative', 'hit_words': ['差评']}

情感词典方案的局限在于:它无法处理否定结构,比如“不满意”会被切成“不”和“满意”,然后“满意”命中正分,导致判断错误。缓解办法是在分词后扫描相邻词,如果前面出现“不”“没”“别”“无”等否定词,就把后面情感词的分数取反。这个逻辑虽然粗糙,但在微博短评论这种长度受限的文本上,准确率远高于直觉预期。

4.2 词频与共现统计:从大量评论里快速定位讨论焦点

当评论量达到几千条以上,逐条看已经不现实。这时词频统计能快速告诉你:“用户评论里出现最多的 20 个词是什么”。my_text.py里的词频模块,核心就是collections.Counter

from collections import Counter def frequency_analysis(all_tokens: list[list[str]], top_n: int = 20) -> list[tuple[str, int]]: """输入是每条评论分词后的 token 列表,输出 TopN 词频""" counter = Counter() for tokens in all_tokens: counter.update(tokens) return counter.most_common(top_n) # 批量处理 comments_jsonl def batch_process(jsonl_path: str = "weibo_comments.jsonl"): all_tokens = [] sentiment_results = [] with open(jsonl_path, encoding="utf-8") as f: for line in f: if not line.strip(): continue data = json.loads(line) text = clean_comment(data["text"]) tokens = tokenize(text) all_tokens.append(tokens) sentiment_results.append(analyze_sentiment(tokens)) return all_tokens, sentiment_results # all_tokens, sentiment_results = batch_process() # top_words = frequency_analysis(all_tokens, top_n=20) # print(top_words)

词频的局限是丢失上下文:“好”和“不好”都算一次“好”的词频。所以更进一步可以做共现分析——统计同一批评论里哪两个词经常同时出现。共现矩阵的实现不复杂,对每条评论的分词结果做两两组合,用Counter累积:

from itertools import combinations def co_occurrence_analysis(all_tokens: list[list[str]], top_n: int = 15) -> list[tuple[tuple[str, str], int]]: """词共现统计:同一评论内出现的词对记为一次共现""" co_counter = Counter() for tokens in all_tokens: # 去重后取两两组合,避免同一评论里重复词造成虚高 unique_tokens = list(set(tokens)) if len(unique_tokens) < 2: continue for pair in combinations(unique_tokens, 2): # 排序保证 "苹果/价格" 和 "价格/苹果" 算同一个词对 sorted_pair = tuple(sorted(pair)) co_counter[sorted_pair] += 1 return co_counter.most_common(top_n)

参数说明:combinations(unique_tokens, 2)生成两两组合,set(tokens)去重是为了避免“好好好好”这种评论里同一词多次出现导致共现虚高。词对排序是一个关键细节:如果不排序,同一对词会以两种顺序进入 Counter,统计值被拆成两半。这一步的结果可以直接输出为 CSV,配合networkx画共现网络图。

4.3 情感分布与高频词的交叉分析参数

单看整体词频或整体情感分布,容易得到“用户整体偏正面”这种正确但无用的结论。更有价值的分析是交叉:把评论按情感分组,分别看负面评论里的高频词和正面评论里的高频词——这能直接定位“用户因为什么满意、因为什么不满”。my_text.py的分析模块可以接受一个group_by参数,如下表所示:

参数取值作用
group_by"all"/"positive"/"negative"/"neutral"指定统计范围,默认 all
top_n10~50 的整数控制输出词数,评论量小于 1000 时建议 10
min_word_len1~2过滤单字词的最小长度,设 2 更严格
use_stopwordsTrue/False是否启用停用词表,分析特定话题时可关闭

负面评论的词频分析代码逻辑很简单:在batch_process时把情感标签记录到每条评论上,然后按标签过滤 tokens。比如发现负面评论的高频词集中在“发货”“客服”“售后”,问题焦点就清楚了;正面评论高频词集中在“质量”“快递”“效果”,那优势项也清楚了。这种交叉分析的价值,远高于单独看一张词云图。

5. 把 my_text_test 跑成日常可复用的三个调试技巧

5.1 用断言锁定管线输出,改代码不怕跑偏

my_text_test.zip里那个_test后缀不是白起的,它暗示了这个项目的测试属性。给my_text.py的每一步都加上轻量断言,重构清洗或分词逻辑时才能快速发现问题。比如清洗函数必须保证:输入含 URL 的文本,输出不含http开头子串;分词函数必须保证:输出列表中不包含空字符串。

def test_pipeline(): sample = "哈哈哈哈哈太真实了!//@某大V:转发微博 [赞] https://t.cn/xxx #热搜#" cleaned = clean_comment(sample) assert "http" not in cleaned, "URL 未清除干净" assert "@" not in cleaned, "@用户未清除干净" assert "//" not in cleaned, "转发标记未清除干净" tokens = tokenize(cleaned) assert all(len(t) > 0 for t in tokens), "分词结果包含空串" assert tokens.count("哈哈哈") == 0, "重复压缩未生效" sentiment = analyze_sentiment(tokens) assert sentiment["label"] in ("positive", "negative", "neutral"), "情感标签越界" print("pipeline checks passed") if __name__ == "__main__": test_pipeline()

这里断言的是函数的不变式(invariants),而不是具体的输出内容——因为清洗规则调整后,输出内容会变,但不变量必须保持不变。用这种思路写断言,后续迭代时回归成本极低。

5.2 抽样打印中间结果:定位“是清洗问题还是分词问题”

文本分析最让人烦躁的是:最后结果不对,但不知道哪一步错了。我一般会在batch_processfor循环里加一个计数器,每处理 500 条打印一次当时的清洗结果和分词结果。一眼就能判断是清洗正则的问题(原文该清没清),还是分词词典的问题(词切得不对)。打印时注意截断长度,一条评论打 30 个字符就足够看出问题。

for idx, line in enumerate(f): if not line.strip(): continue data = json.loads(line) text = clean_comment(data["text"]) tokens = tokenize(text) if idx % 500 == 0: print(f"[{idx}] raw: {data['text'][:40]}") print(f"[{idx}] clean: {text[:40]}") print(f"[{idx}] tokens: {tokens[:10]}")

如果清洗后原文带了 HTML 实体如&amp;,说明没走 unescape;如果分词结果里还有“了”“的”这类停用词,说明停用词表没加载成功。这两种情况在微博评论场景都极其常见。

5.3 中文词云图输出时避免方块乱码

最后一步往往是可视化。如果用wordcloud库生成词云,默认字体不支持中文,输出全是一个个方框。解决办法是显式指定一个中文字体文件路径,Windows 系统一般用C:/Windows/Fonts/simhei.ttf(黑体),macOS 用/System/Library/Fonts/PingFang.ttc。加上这个参数后词云图才真正可用。配合上面frequency_analysis的输出,把词频字典传入generate_from_frequencies,比传入整段文本再重新分词要快得多,因为省去了一次重复的jieba.cut。这一步做完,my_text_test.zip这条“下载解压 → 跑通输入输出 → 调整参数 → 出分析报告”的链路,就真正变成了可以反复使用的文本分析小工具。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询