资讯动态

Python+LDA微博文本分析可视化:从数据抓取到主题建模实践

发布时间:2026/10/3 9:22:40 来源:尧图企业网站定制
简介基于Python的微博数据抓取、文本分析与可视化项目适合用于毕业设计、期末大作业或课程设计。项目实现了从微博数据采集到LDA主题建模、情感分析、聚类分析及多种可视化展示的完整流程含树图、3D柱状图、饼图、词云、地图等。代码配有详细注释并附带文档说明方便新手理解部署。包体共53个文件约66.36MB涵盖20个Python源码文件、多个HTML可视化结果、PNG图片、txt/json数据文件以及词向量模型、xls结果表等能清晰看到分析过程与输出效果。目前已有179人学习下载。项目经过调试可直接运行适合作为高分毕设或大作业交付。下载后按说明配置即可使用可作为数据分析课程设计、毕业设计以及新媒体文本挖掘相关任务的重要参考。1. 微博文本分析与可视化这套 Python LDA 源码为什么值得拆做微博文本分析有个很现实的痛点数据能抓到但不知道拿它干什么。爬下来几万条微博清洗、分词、去停用词之后面对的还是一堆散词看不出这几万条文本到底在讨论什么主题。而这份基于 Python 抓取微博数据、做 LDA 主题建模、最终落到树图、3D 柱状图、词云、地图、关系图等可视化页面的项目源码恰好把这条链路完整打通了。它不是只给你一个 LDA 模型文件而是从采集端到展示端全都有代码还带文档说明。对正在找毕业设计、期末大作业素材的人来说拿到手最关心的三件事——能不能跑通、代码能不能看懂、答辩时能不能讲清楚——这套源码基本都覆盖到了。我拆完整个项目后先把结论放这儿这是一套典型的“数据采集 → 文本预处理 → 主题建模 → 多图可视化”教学型项目适合照着改、照着讲不建议原样交。2. 数据抓取与文本预处理先搞定微博数据长什么样2.1 从 JSON 到结构化语料读懂 Agu_content.json 与 Agu_comment.json打开项目压缩包最先看到的是两个 JSON 文件Agu_content.json和Agu_comment.json。这两个文件是整套分析的数据源头。前者是微博正文内容后者是评论内容。说是抓微博数据但源码包本身并没有内置一个实时爬虫脚本而是把抓取结果沉淀成了 JSON 格式。这在毕设场景里其实是合理设计——答辩时你可以说“数据通过爬虫采集并持久化到本地 JSON”不必现场演示爬取省去被封号、登录态失效这些不可控因素。两个 JSON 的数据结构决定了后面所有预处理脚本怎么写。Agu_content.json里每条记录通常包含微博文本、发布时间、点赞数、转发数这类字段而Agu_comment.json则承载评论者 ID、评论文本、评论时间。做预处理之前第一步永远是先探明 JSON 结构而不是直接写清洗函数import json with open(Agu_content.json, r, encodingutf-8) as f: data json.load(f) # 先看数据类型和单条记录长什么样 print(type(data)) if isinstance(data, list): print(记录条数:, len(data)) print(单条字段:, list(data[0].keys())) print(示例文本:, data[0].get(text, data[0])[:50])这段代码的作用有两个一是确认 JSON 是数组还是字典直接决定后面遍历逻辑怎么写二是把单条记录的字段名打出来避免凭猜写字段名导致 KeyError。我一般会建议拿到任何一个数据文件第一步都是跑这个探查脚本把结构摸清楚再往下走。很多新手拿到项目跑不通不是代码错了而是数据字段对不上——比如有的数据源用content有的用text差一个字母后面全崩。2.2 繁简转换与文本清洗zh_wiki.py 和 langconv.py 的用法项目里有两个不太起眼但非常关键的文件zh_wiki.py和langconv.py。这两个文件是一套完整的繁简转换工具zh_wiki.py维护着繁简字映射表langconv.py负责执行转换逻辑。为什么要做这个微博数据里大量混着繁体中文尤其是转发的港台资讯、娱乐内容。如果不做繁简统一分词阶段“台湾”和“臺灣”会被切成两个词LDA 建模时主题词分布的噪声会明显增大。预处理脚本prepro.py和senti_pre.py内部会调用这套转换工具。实际使用时不需要每次都手动写转换函数常见的做法是引入后直接调用from langconv import Converter def traditional_to_simplified(text: str) - str: 繁体转简体基于项目内置的 zh_wiki 映射表 return Converter(zh-hans).convert(text) raw_text 這部電影的票房表現非常亮眼 clean_text traditional_to_simplified(raw_text) print(clean_text) # 输出: 这部电影的票房表现非常亮眼这个转换函数有两个使用细节。第一Converter(zh-hans)里的参数写死为zh-hans表示转简体想转繁体就写zh-hant。第二zh_wiki.py的映射表不是全覆盖的遇到生僻字或网络新造字可能转换失败这种情况原样保留即可不影响整体分析。文本清洗的另一半工作是去 URL、去 用户名、去多余空白字符这块逻辑通常也集中在prepro.py里。清洗的干净程度直接决定分词质量正则表达式的匹配范围宁严勿松。3. LDA 主题建模与树图产出直接拆 LDA.py 的实现逻辑3.1 向量化与主题数选择LDA.py 的核心参数解读LDA 在很多同学眼里是个黑匣子——把文本丢进去出来几个主题每个主题带一堆词。但想让这个黑匣子输出能用于答辩的结果必须理解LDA.py里的几个关键参数。这个项目用的是 gensim 库的 LdaModel也有版本用 sklearn 的 LatentDirichletAllocation两种实现的核心参数含义是相通的。主题数num_topics或n_components是最需要调的参数。主题数太少所有文本被压成几个大杂烩主题看不出差异主题数太多每个主题只剩两三篇文档支撑树图上全是细碎分支答辩时讲不清楚。常见做法是先按文档规模粗估——几百条到几千条的微博语料主题数先设 5 到 8 个跑完看主题词的连贯性再微调。from gensim import corpora, models import jieba # texts 为前序预处理得到的分词结果列表每个元素是一条微博的分词列表 dictionary corpora.Dictionary(texts) # 过滤极端词在少于 2 条文档中出现或在超过 60% 文档中出现的词都去掉 dictionary.filter_extremes(no_below2, no_above0.6) corpus [dictionary.doc2bow(text) for text in texts] lda_model models.LdaModel( corpuscorpus, id2worddictionary, num_topics6, # 主题数根据语料规模调整 passes20, # 整体语料迭代轮数 iterations200, # 单篇文档采样迭代次数 random_state42, # 固定随机种子保证结果可复现 alphaauto, # 主题先验分布自适应 etaauto # 词分布先验自适应 ) for idx, topic in lda_model.print_topics(num_words15): print(f主题 {idx}: {topic})参数说明filter_extremes的两个阈值很关键——no_below2去掉只出现过一次的单词no_above0.6去掉超过六成文档都在用的高频词这种词通常是“微博”“转发”这类无区分度的噪声。passes和iterations控制模型收敛程度数值太小主题不稳定太大训练时间成倍增加。random_state是整篇代码里最重要的一个参数不固定随机种子每次跑主题都不一样答辩时前后对不上会很尴尬。3.2 从 LDA 结果到 LDA_total.csv中间桥梁是主题分布矩阵模型训练完后LDA.py会把每条微博的主题分布输出成LDA_total.csv。这个文件是后续可视化脚本的数据底座——树图、3D 柱状图都要读它才能画出来。CSV 的典型结构是每行一条微博第一列写文档编号后面的列写该微博在 6 个主题上的概率分布概率和为 1。import pandas as pd rows [] for doc_id, bow in enumerate(corpus): # get_document_topics 返回该文档在 6 个主题上的概率分布 topic_dist lda_model.get_document_topics(bow, minimum_probability0) # 转成定长 6 维向量缺失的主题补 0 probs [0.0] * 6 for topic_id, prob in topic_dist: probs[topic_id] round(prob, 4) rows.append([doc_id] probs) df pd.DataFrame(rows, columns[doc_id] [ftopic_{i} for i in range(6)]) df.to_csv(LDA_total.csv, indexFalse, encodingutf-8-sig)这里有两个细节值得注意。第一minimum_probability0必须显式指定否则 gensim 默认会把小于 0.01 的概率直接归零导致很多文档的主题分布稀疏且不完整。第二CSV 保存时用utf-8-sig编码这是给 Excel 看的——用普通utf-8存Excel 打开会乱码这个坑几乎每个做数据分析的人都踩过。输出LDA_total.csv之后后面的tree.py、3Dbar.py、pie.py就全部围绕这个文件开展工作相当于把建模和分析两个阶段解耦了。3.3 tree.py 与树图可视化把主题层级结构画出来tree.py是这套项目的可视化亮点它读取LDA_total.csv结合每条微博原始文本生成一棵主题树。树图的价值在于展示“主题—子主题—代表文本”的层级关系。根节点是全部语料往下按主题分裂每个分支挂上该主题下概率最高的几条微博文本。这样答辩时你指着一棵树就能讲清楚“这个主题下用户最关心什么”。树图实现通常基于 pyecharts 的Tree组件或 Plotly 的treemap。pyecharts 的 Tree 组件数据结构是嵌套字典需要把扁平的主题分布矩阵重新组装成树形结构from pyecharts import options as opts from pyecharts.charts import Tree import pandas as pd df pd.read_csv(LDA_total.csv) data [{name: 全部微博, children: []}] for topic_id in range(6): # 找出该主题下概率最高的前 10 条微博 topic_col ftopic_{topic_id} top_docs df.nlargest(10, topic_col) children [] for _, row in top_docs.iterrows(): children.append({ name: f微博{row[doc_id]}, value: round(row[topic_col], 2) }) data[0][children].append({ name: f主题{topic_id 1}, children: children }) tree ( Tree(init_optsopts.InitOpts(width1200px, height800px)) .add(主题树, data, collapse_interval2) ) tree.render(tree.html)这段代码的生成逻辑是两层嵌套的 children第一层是主题第二层是代表微博。collapse_interval2控制展开层级默认全部展开会导致页面拥挤设成 2 时初始只展开到主题层点击才下钻到具体微博。value字段存的是该微博在这个主题上的概率鼠标悬浮能看到数值。树图能不能“讲出故事”取决于上面这个nlargest(10, topic_col)的取值——取太少分支空荡荡取太多叶子节点全是低概率微博文本内容没代表性。我一般取 8 到 12 条能看到主题差异又不至于太杂。4. 多维可视化体系从 3D 柱状图到词云、地图、关系图4.1 3Dbar.py 与 pie.py主题分布的广度与占比视角3Dbar.py产出3Dbar.html这是一种很讨喜的展示形式——X 轴是主题编号Y 轴是文档编号Z 轴是该文档在这个主题上的概率。三维柱状图直观展示了每篇微博在 6 个主题上的“响应强度”比二维热力图更能引起答辩老师的注意。pie.py产出pie.html饼图展示的是 6 个主题在整个语料中的占比主题权重计算方式通常是把所有微博在该主题上的概率求和再归一化。import pandas as pd from pyecharts.charts import Pie from pyecharts import options as opts df pd.read_csv(LDA_total.csv) topic_cols [ftopic_{i} for i in range(6)] # 每个主题的总权重 所有微博在该主题概率之和 topic_weights df[topic_cols].sum().tolist() topic_names [f主题{i 1} for i in range(6)] pie ( Pie() .add(主题占比, [list(z) for z in zip(topic_names, topic_weights)], radius[40%, 70%]) .set_global_opts(title_optsopts.TitleOpts(title微博主题占比分布)) .set_series_opts(label_optsopts.LabelOpts(formatter{b}: {d}%)) ) pie.render(pie.html)饼图的关键在formatter{b}: {d}%——{b}显示主题名{d}显示百分比。不设置的话默认只显示数值答辩时还得心算占比体验很差。radius[40%, 70%]是环形饼图的经典参数内径 40% 外径 70%中间留白区域可以放总微博条数说明文字。4.2 wc.py 词云与 map.py 地图把文本和地域绑定展示wc.py生成词云核心依赖 jieba 分词 wordcloud 库。词云图在毕设项目里几乎是标配但有个容易翻车的点wordcloud 默认不支持中文必须指定中文字体路径否则生成的图片全是方框。wc.py里通常会加载simhei.ttf或msyh.ttf不同操作系统字体路径不一样Windows 在C:/Windows/Fonts/Linux 在/usr/share/fonts/。from wordcloud import WordCloud import jieba with open(key_words2.txt, r, encodingutf-8) as f: text f.read() # 使用 jieba 分词并用空格连接wordcloud 才能正确识别词边界 seg_list jieba.cut(text, cut_allFalse) seg_str .join(seg_list) wc WordCloud( font_pathC:/Windows/Fonts/simhei.ttf, # 中文字体关键配置 width1600, height900, background_colorwhite, max_words200, collocationsFalse # 避免 wordcloud 自动组合二元词组 ).generate(seg_str) wc.to_file(wordcloud.png)collocationsFalse是个容易忽略的参数。默认情况下 wordcloud 会自动检测二元词组比如“中国”“足球”变成“中国足球”但 jieba 已经做了分词双重组合会生成大量无意义词组。地图方面map.py产出map.html处理逻辑是把微博带有的地理位置信息省份、城市聚合后映射到中国地图上可视化看哪个区域讨论热度最高。地图的色阶配置需要 pyecharts 的Map组件数据格式是[(省份名, 数值), ...]省份名必须与 pyecharts 内置名称完全一致比如“广东”不能写成“广东省”否则匹配不到。4.3 graph.py 关系图与 lines.py 折线图话题扩散与时序趋势graph.py产出graph.html画的是用户互动关系图——节点是用户边是评论、转发关系。这个图对数据量有要求几千条文本跑出来的关系图动辄几十个节点、上百条边不做剪枝就会变成一团毛线。常见做法是只取互动次数 TOP 20 的用户构成子图。lines.py产出line.html折线图展示微博发布数量的时间趋势横轴是日期纵轴是微博条数。这个图在毕设里往往起到“背景交代”作用——说明某个时间段内话题热度上升对应某事件发生。import pandas as pd from pyecharts.charts import Line from pyecharts import options as opts # 假设有日期字段和每日微博计数 df_time pd.read_csv(time_series.csv) line ( Line() .add_xaxis(df_time[date].tolist()) .add_yaxis(微博发布量, df_time[count].tolist(), is_smoothTrue, markpoint_optsopts.MarkPointOpts( data[opts.MarkPointItem(type_max)] )) .set_global_opts( title_optsopts.TitleOpts(title微博发布量时序变化), datazoom_opts[opts.DataZoomOpts(range_start0, range_end50)] ) ) line.render(line.html)折线图有个值得做的细节datazoom_opts加个缩放条。微博数据通常覆盖几十天不缩放的话前半段波动被压缩得看不清加上缩放条后答辩现场可以滚动查看任何时间段细节这个小交互很加分。markpoint_opts标注最大值点一眼能看出波峰在哪天。5. 避坑指南与常见问题排查跑通这套项目的 5 条血泪经验5.1 现象一运行 LDA.py 报错ModuleNotFoundError: No module named gensim原因环境没装 gensim或者虚拟环境与当前 Python 解释器不一致。这是最基础的依赖问题但也是大多数同学跑不通的第一道坎。解决先确认当前 Python 版本再用pip install补齐依赖。项目根目录有requirements.txt就批量安装没有就逐个装。我建议统一用pip install gensim jieba pandas pyecharts wordcloud一次性装齐避免装到一半报缺包。python --version pip install --upgrade gensim jieba pandas pyecharts wordcloud5.2 现象二tree.html 打开是空白页控制台报 JavaScript 错误原因pyecharts 版本问题。pyecharts 1.x 和 0.5.x 的 API 差异非常大Tree()的调用方式完全不同。项目里如果用了某个版本的写法你的环境装的是另一个版本生成的 HTML 根本没法渲染。解决看项目代码 import 语句如果写的是from pyecharts import Tree说明是 0.5.x 老版本需要pip install pyecharts0.5.11如果写的是from pyecharts.charts import Tree说明是 1.x 及以上。5.3 现象三词云或地图画出来全是方框、乱码原因wordcloud 缺中文字体或地图匹配不到省份名。解决词云在WordCloud()参数中显式指定font_path指向系统已有中文字体地图检查数据里的省份名是否与 pyecharts 内置名称完全一致比如“湖南”与“湖南省”这种差异先用项目自带的省份列表做一次 set 差运算排查。5.4 现象四LDA 每次运行结果都不一样主题词经常变原因LDA 是概率模型采样过程有随机性。解决在LdaModel()里设置random_state42固定随机种子。如果项目源码没设置自己补上这行参数。这一步非常关键别小看它——答辩时老师问“为什么结果可复现”这就是答案。5.5 现象五运行预处理脚本卡死或内存飙高原因数据量超出了当前环境的内存承载范围。几千条微博不至于卡死但几万条评论如果全量加载到内存分词就会明显卡顿。解决分批次处理比如每次读 1000 条处理完写回磁盘释放内存。常见做法是用pd.read_csv()的chunksize参数分批读取。import pandas as pd # 分批读取每批 1000 行处理完即释放 for chunk in pd.read_csv(large_file.csv, chunksize1000): process_chunk(chunk) # 预处理函数写在循环体外6. 二次开发与答辩验证从跑通到讲清楚的最后一公里这个项目如果只停留在“能跑、能出图”拿高分还差一口气。我拆过很多毕设源码发现真正的分水岭在于你能不能在没有源码的情况下用自己的数据从头到尾复现一遍流程。建议拿到项目后先做一次“数据替换演练”——把Agu_content.json换成你自己爬的一份微博数据或者用项目里的爬虫思路重新采集一遍。替换数据有两条路。第一条路是继续用 JSON 格式保持字段名与现有脚本一致这样prepro.py、senti_pre.py不用改任何代码。第二条路是改字段映射比如你新数据的文本字段叫weibo_text那就需要在预处理脚本开头加一行映射代码把weibo_text改成程序认识的text。具体做法是import json with open(my_weibo.json, r, encodingutf-8) as f: data json.load(f) # 新数据的字段名与项目默认不一致做一次映射归一 for record in data: record[text] record.pop(weibo_text)数据替换完重新跑一遍完整流程注意观察 LDA 主题词是否语义可解释。如果主题 1 的 15 个词全是“转发”“评论”“链接”这类词说明清洗环节没做好回prepro.py里补停用词表和 URL 过滤规则。主题词相邻主题间高度重合说明主题数设多了把num_topics从 6 降到 4 再试。关于答辩讲解我建议重点抓两个点一是 LDA 的建模链路从分词到词典到语料到模型每一步输入输出是什么要能画出来二是可视化之间的关联逻辑——树图展示主题层级3D 柱状图展示分布强度饼图展示全局占比三个图服务于同一个LDA_total.csv互相印证的关系讲清楚评委基本就会认可项目的完整性。最后分享一个我拆这类项目养成的习惯拿到压缩包第一件事不管代码写得多好先打开README.md看作者自己写的运行说明再看requirements.txt确认依赖清单最后才动代码。项目里既然带了这两个文件你就要充分利用它们——README 里写的 Python 版本、安装顺序、注意事项都是作者趟过坑之后留下的路标。从那以后我每次复现别人的毕设项目都强制自己先走一遍 README 再碰代码省下的调试时间比想象中多得多。希望这套微博文本分析项目也能让你少踩几个坑把精力花在真正有价值的分析上。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑