
简介本资源是一套面向Python数据采集与可视化初学者的微博热搜话题分析实践项目聚焦社交媒体舆情挖掘场景帮助学习者掌握从网页抓取、文本清洗到词云生成的完整流程。压缩包共7个Python脚本文件11KB涵盖热搜爬取、词频统计、停用词过滤、多时段词云图绘制含4版头条热搜词云图及热搜指数计算等核心功能代码结构清晰、注释充分适合作为自然语言处理与网络爬虫的入门级实战范例。已有2205人学习下载读者可直接运行调试快速复现词云可视化效果理解jieba分词、wordcloud绘图及requests反爬应对等关键技术点并基于代码拓展时间序列对比或热点关联分析。1. 微博热搜话题榜词云分析不是简单画图而是从原始 HTML 抓取、清洗、加权、可视化的一整套 NLP 流程你打开微博热搜榜看到“#张颂文新剧开播#”“#AI写春联被夸爆#”“#春节返程高峰#”——这些标题背后是千万级用户实时互动产生的语义信号。但直接截图做词云那只是贴图不是分析。真正的「微博热搜话题榜词云分析」核心在于从微博网页源码中稳定提取带热度值的原始话题文本剔除广告、引导语、平台标识等噪声对“话题词”而非“描述句”做分词与权重映射最终生成能反映真实舆论焦点的可解释词云图。它不依赖微博官方 API已限流且需认证也不靠第三方爬虫库黑盒封装而是用 Requests BeautifulSoup 精准定位 DOM 节点用 Jieba 做领域适配分词需加载微博热词词典用 WordCloud 的font_path和collocationsFalse控制视觉干扰最后用 Matplotlib 的tight_layout()解决中文乱码与布局溢出。适合数据分析师、舆情监测岗、NLP 入门者——只要你会pip install requests beautifulsoup4 jieba wordcloud matplotlib就能在本地复现完整链路且所有步骤均可调试、可审计、可嵌入定时任务。2. 用 Requests BeautifulSoup 稳定抓取微博热搜榜 HTML 源码并提取带热度的话题列表微博热搜榜页面https://s.weibo.com/top/summary结构清晰但存在反爬机制无登录态时返回基础榜单含tr行内td classtd-01序号、td classtd-02话题链接与文本、td classtd-03热度值。关键不是“能不能爬”而是“怎么爬得稳、可复现、不被拦截”。2.1 构造带 UA 与 Referer 的请求头绕过基础风控微博对无 Referer 或低频 UA 的请求会返回空表格或跳转。必须模拟真实浏览器行为import requests from bs4 import BeautifulSoup 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, Referer: https://s.weibo.com/, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/webp,image/apng,*/*;q0.8,application/signed-exchange;vb3;q0.7, Accept-Language: zh-CN,zh;q0.9,en;q0.8, Connection: keep-alive } url https://s.weibo.com/top/summary response requests.get(url, headersheaders, timeout10) response.raise_for_status() # 显式抛出 HTTP 错误 response.encoding utf-8 # 强制编码避免乱码提示timeout10是硬性要求。微博服务器响应波动大超时设太短如 3 秒会导致频繁失败设太长如 30 秒则阻塞后续流程。10 秒是实测平衡点。2.2 使用 BeautifulSoup 定位td classtd-02内的话题文本与td classtd-03的热度值微博 HTML 中每个热搜条目为tr其中td-02包含a href/weibo?q%23...%23标签其text是带#的话题名如#张颂文新剧开播#td-03的text.strip()是纯数字热度如1245678soup BeautifulSoup(response.text, html.parser) hot_topics [] for tr in soup.select(table#top_rank_list tbody tr): td02 tr.select_one(td.td-02) td03 tr.select_one(td.td-03) if td02 and td03: a_tag td02.find(a) if a_tag and a_tag.text.strip(): topic_text a_tag.text.strip() # 过滤掉“置顶”“沸”“新”等非话题文本它们在 td-02 内但非 a 标签 if topic_text.startswith(#) and topic_text.endswith(#): try: heat int(td03.text.strip().replace(,, )) hot_topics.append({ topic: topic_text, heat: heat }) except ValueError: continue # 热度非数字则跳过如“实时上升”等异常值 print(f成功提取 {len(hot_topics)} 条有效热搜话题) # 示例输出[{topic: #张颂文新剧开播#, heat: 1245678}, ...]参数说明与容错设计soup.select(table#top_rank_list tbody tr)精准定位主表格行避免抓取页脚或广告行a_tag.text.strip().strip()清除前后空格与换行防止#张颂文新剧开播#\n导致后续分词失败topic_text.startswith(#) and topic_text.endswith(#)强制校验话题格式排除“微博热搜榜”“查看更多”等干扰项heat int(...)中replace(,, )处理带千分位逗号的热度如1,234,567→1234567try/except捕获非数字热度不中断整个流程。2.3 将原始话题列表保存为 JSON 并验证结构抓取后立即序列化便于后续步骤复用与调试import json with open(weibo_hot_topics_raw.json, w, encodingutf-8) as f: json.dump(hot_topics, f, ensure_asciiFalse, indent2) # 验证打印前 3 条 for item in hot_topics[:3]: print(f话题: {item[topic]:20} | 热度: {item[heat]})注意不要跳过这一步。微博 HTML 结构偶有微调如 class 名变更JSON 文件是判断抓取是否成功的唯一可信依据。若文件为空或字段缺失问题一定出在2.1或2.2的 selector 上而非后续 NLP 步骤。3. 用 Jieba 分词 自定义词典清洗话题文本构建带热度权重的词频字典热搜话题文本如#张颂文新剧开播#不能直接丢给 Jieba——它会把#张颂文新剧开播#拆成[#, 张颂文, 新剧, 开播, #]导致#占高频、真实关键词被稀释。必须先做话题净化去#、去停用词、保留核心实体再按热度加权统计。3.1 构建微博领域专用停用词表与自定义词典Jieba 默认词典对微博场景覆盖不足。需补充停用词#、【、】、「、」、、、《、》、/、_、·、、…、、、。、、、、“、”、‘、’、、、《、》、【、】、、、『、』强制分词词张颂文、AI写春联、春节返程高峰、唐宋诗词来自热搜热词与网络热词合并词AI写春联不应拆为[AI, 写, 春联]而应整体作为一词import jieba import re # 加载停用词从文件或内置列表 stopwords set([#, 【, 】, 「, 」, , , 《, 》, /, _, ·, , …, , , 。, , , , “, ”, ‘, ’, 、, 『, 』]) # 添加微博热词到 jieba 词典提升分词准确率 jieba.add_word(张颂文, freq10000) jieba.add_word(AI写春联, freq8000) jieba.add_word(春节返程高峰, freq7500) jieba.add_word(唐宋诗词, freq6000) jieba.add_word(社工网站, freq5000) # 响应热词“社工网站查询微博uid” def clean_topic(topic_str): 清洗单个话题字符串去#、去标点、去停用词、保留中文与英文单词 # 去首尾 #并移除所有非中文、非英文、非数字字符保留空格分隔 cleaned re.sub(r^#|#$, , topic_str) # 去首尾 # cleaned re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9\s], , cleaned) # 替换标点为空格 cleaned re.sub(r\s, , cleaned).strip() # 合并多余空格 return cleaned # 示例清洗 print(clean_topic(#张颂文新剧开播#)) # 输出张颂文新剧开播 print(clean_topic(【AI写春联被夸爆】)) # 输出AI写春联被夸爆3.2 对每个话题执行分词、过滤、加权生成最终词频字典核心逻辑每个话题的热度值按分词后词数均分到每个词上而非简单计数。例如#AI写春联被夸爆#热度 1200000分词得[AI写春联, 被, 夸爆]则AI写春联获得1200000 * 0.5因它是核心实体权重更高夸爆获得1200000 * 0.3被获得1200000 * 0.2。此处采用简化策略仅保留长度 ≥2 的词且排除停用词每个词权重 话题热度 / 有效词数from collections import defaultdict word_freq defaultdict(int) for item in hot_topics: topic_clean clean_topic(item[topic]) if not topic_clean: continue # 分词并过滤 words jieba.lcut(topic_clean) valid_words [ w.strip() for w in words if len(w.strip()) 2 and w.strip() not in stopwords and re.match(r^[\u4e00-\u9fa5a-zA-Z0-9]$, w.strip()) ] if not valid_words: continue # 每个有效词获得均分热度 base_weight item[heat] / len(valid_words) for word in valid_words: word_freq[word] int(base_weight) # 转为排序列表 word_freq_sorted sorted(word_freq.items(), keylambda x: x[1], reverseTrue) print(Top 10 词频:) for word, freq in word_freq_sorted[:10]: print(f{word:12} : {freq})关键参数说明len(w.strip()) 2过滤单字如“被”“的”“和”这些在微博话题中极少承载核心语义re.match(r^[\u4e00-\u9fa5a-zA-Z0-9]$, w.strip())确保词只含中文、英文、数字排除AI写春联中的写单独出现因AI写春联已作为整体加入词典base_weight item[heat] / len(valid_words)实现热度按语义单元分配避免#春节返程高峰#4 个字与#AI写春联#4 个字在词频中贡献相同——实际前者热度通常更高故其每个词权重更大。3.3 导出词频 CSV 供后续可视化或人工审核import csv with open(weibo_word_freq.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([word, frequency]) for word, freq in word_freq_sorted: writer.writerow([word, freq]) print(词频 CSV 已保存共, len(word_freq_sorted), 个词)该 CSV 可直接导入 Excel 做人工校验如检查AI写春联是否被正确识别为一词而非AI和写春联分离是调试分词效果的黄金标准。4. 用 WordCloud Matplotlib 生成高可读性词云图并解决中文乱码与布局溢出问题词云不是炫技而是信息传达工具。默认 WordCloud 会把高频词堆在中心、低频词挤在边缘且中文默认字体不支持导致方块乱码。必须显式指定字体、控制最大词数、禁用词组连用、调整背景色与尺寸。4.1 下载并指定思源黑体Noto Sans CJK作为中文字体路径Windows 用户常犯错误直接用simhei.ttf黑体但该字体不支持部分 Unicode 扩展区汉字如“頑”“驛”。推荐使用 Google 与 Adobe 联合开发的开源字体Noto Sans CJK SC简体中文版覆盖全 Unicode 中文字符。from wordcloud import WordCloud import matplotlib.pyplot as plt # 下载地址https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKsc-hinted.zip # 解压后取 NotoSansCJKsc-Regular.otf或 .ttf font_path NotoSansCJKsc-Regular.otf # 替换为你的实际路径 # 验证字体路径是否存在 import os if not os.path.exists(font_path): raise FileNotFoundError(f字体文件未找到{font_path}。请下载 Noto Sans CJK SC 并设置正确路径。) # 构建词云对象 wc WordCloud( font_pathfont_path, width1200, height800, background_colorwhite, max_words100, # 最多显示 100 个词 colormapviridis, # 颜色映射比默认更柔和 random_state42, # 固定随机种子保证每次生成一致 collocationsFalse, # 关键禁用词组连用否则 AI写春联 会被拆成 AI 和 写春联 prefer_horizontal0.8 # 80% 词水平排列提升可读性 )提示collocationsFalse是微博词云的生命线。若开启默认 TrueWordCloud 会将相邻高频词自动组合如AI和写春联出现在同一话题中则生成AI写春联词但此机制不可控、不可预测。关闭后完全依赖word_freq字典输入结果可复现、可审计。4.2 从词频字典生成词云并用 Matplotlib 精确控制布局# 生成词云图像传入 dict wc.generate_from_frequencies(dict(word_freq_sorted)) # 使用 matplotlib 绘图非 wc.to_image()以便精确控制 plt.figure(figsize(15, 10)) plt.imshow(wc, interpolationbilinear) plt.axis(off) # 隐藏坐标轴 plt.tight_layout(pad0) # 关键解决词云边缘被截断问题 # 保存高清 PNG300 DPI plt.savefig(weibo_hotword_cloud.png, dpi300, bbox_inchestight) plt.show() print(词云图已生成weibo_hotword_cloud.png)参数深度解析width1200, height800设定画布尺寸。过小如 400×300导致词挤压变形过大如 2400×1600增加渲染时间且无实际增益max_words100微博热搜通常前 50 名已覆盖 80% 热度设 100 保证顶部词全部可见colormapviridis比jet更符合数据可视化规范色阶连续、色盲友好prefer_horizontal0.8微博话题多为 2~4 字词水平排列更易识别若设为 0.5则大量竖排词降低可读性plt.tight_layout(pad0)pad0是精髓。WordCloud 默认 padding 过大导致词云四周留白过多、实际内容区域缩小。设为 0 并配合bbox_inchestight才能让词云填满整个 PNG 画布。4.3 生成带热度数值标注的词频排行榜辅助验证词云词云是概览数值表是依据。生成 Top 20 表格与词云对照# 取 Top 20 top20 word_freq_sorted[:20] print(\n 微博热搜 Top 20 词频排行榜 ) print(f{排名:4} {词语:12} {热度:12} {占比(%):10}) print(- * 45) total_heat sum(freq for _, freq in word_freq_sorted) for i, (word, freq) in enumerate(top20, 1): pct (freq / total_heat) * 100 print(f{i:4} {word:12} {freq:12,} {pct:.2f})输出示例 微博热搜 Top 20 词频排行榜 排名 词语 热度 占比(%) --------------------------------------------- 1 张颂文 1,245,678 18.32 2 AI写春联 987,654 14.52 3 春节返程高峰 876,543 12.89 ...此表可直接用于汇报证明词云中“张颂文”字号最大并非偶然而是其贡献了 18.32% 的总热度权重。5. 进阶技巧用 Python 脚本参数化控制抓取与可视化流程支持定时更新与多平台部署一个静态词云图价值有限。真正落地的方案必须支持每日自动抓取、自动清洗、自动绘图、自动覆盖旧图、失败自动告警。这需要将前述步骤封装为可传参的 CLI 脚本并利用系统定时任务Linux cron / Windows Task Scheduler驱动。5.1 将全流程封装为weibo_wordcloud.py支持命令行参数# weibo_wordcloud.py import argparse import sys def main(): parser argparse.ArgumentParser(description微博热搜词云分析工具) parser.add_argument(--output-dir, default., help输出目录路径) parser.add_argument(--font-path, requiredTrue, help中文字体路径如 NotoSansCJKsc-Regular.otf) parser.add_argument(--max-words, typeint, default100, help词云最大词数) parser.add_argument(--dpi, typeint, default300, help输出图片 DPI) parser.add_argument(--debug, actionstore_true, help启用调试模式打印中间步骤) args parser.parse_args() # 步骤1抓取 if args.debug: print( 步骤1抓取微博热搜榜...) hot_topics fetch_weibo_hot_topics() # 步骤2清洗与词频统计 if args.debug: print( 步骤2清洗话题并统计词频...) word_freq build_word_frequency(hot_topics) # 步骤3生成词云 if args.debug: print( 步骤3生成词云图...) generate_wordcloud( word_freqword_freq, font_pathargs.font_path, output_dirargs.output_dir, max_wordsargs.max_words, dpiargs.dpi ) print(f✅ 词云已生成{args.output_dir}/weibo_hotword_cloud.png) if __name__ __main__: main()5.2 使用方式一行命令完成全链路# Linux/macOS python weibo_wordcloud.py --font-path ./NotoSansCJKsc-Regular.otf --output-dir ./output --max-words 80 --dpi 200 # WindowsCMD python weibo_wordcloud.py --font-path D:\fonts\NotoSansCJKsc-Regular.otf --output-dir D:\weibo_output --debug参数说明--font-path必填强制用户指定字体避免乱码--output-dir指定输出位置便于与日志、原始 JSON 分离--max-words 80比默认 100 更聚焦适合嵌入 PPT 或报告--dpi 200平衡质量与文件大小200 DPI 已满足印刷需求--debug开发阶段启用打印每步耗时与关键变量生产环境关闭。5.3 配置 Linux cron 每日 9:00 自动执行附失败邮件告警# 编辑 crontab crontab -e # 添加以下行假设脚本在 /home/user/weibo/ 0 9 * * * cd /home/user/weibo /usr/bin/python3 /home/user/weibo/weibo_wordcloud.py --font-path /home/user/weibo/NotoSansCJKsc-Regular.otf --output-dir /home/user/weibo/output 21 | mail -s Weibo WordCloud Daily Report admincompany.com注意21将标准错误重定向到标准输出确保异常堆栈也能发邮件mail命令需系统已配置 SMTP如 ssmtp 或 msmtp。若无邮件服务可改用 /home/user/weibo/cron.log 21记录日志。5.4 Windows 批处理 任务计划程序实现同等效果新建run_daily.batecho off cd /d D:\weibo_tool python weibo_wordcloud.py --font-path D:\fonts\NotoSansCJKsc-Regular.otf --output-dir D:\weibo_output if %errorlevel% neq 0 ( echo [ERROR] 词云生成失败 D:\weibo_output\error.log exit /b %errorlevel% ) else ( echo [OK] %date% %time% 词云生成成功 D:\weibo_output\success.log )在“任务计划程序”中创建基本任务触发器每天 09:00操作启动程序 →cmd.exe参数/c D:\weibo_tool\run_daily.bat条件勾选“只有在计算机使用交流电源时才运行”防笔记本电池耗尽中断。至此从手动分析到全自动流水线全部闭环。你不再需要每天打开浏览器复制粘贴只需确保服务器开机、网络畅通、字体路径正确——词云图就会准时出现在指定文件夹。本文还有配套的精品资源点击获取