简介:这是一份面向文本挖掘与数据可视化初学者及中级 Python 用户的词云实践教程,以单个 PDF 文档承载 7 个循序渐进的案例,帮助读者从最简调用过渡到蒙版形状、自定义配色与关键词权重提取等进阶用法。压缩包共 1 个文件,为 PDF 格式,大小约 2.07MB,便于在电脑或平板上直接查阅。已有 108 人学习,说明其内容对入门与项目应用具有一定参考价值。文档围绕 wordcloud 与 matplotlib 两个库展开,先讲词云的定义、作用与生成流程,再逐步拆解文本预处理、权重计算、图像展示和保存等环节;每个案例均配有代码与运行结果,可据此理解中文分词、停用词处理、字体路径设置及常见参数调整。读者既能掌握从读取文本到输出词云图的完整链路,也能把案例改造成报告配图、社交媒体分析或教学演示素材,适合作为动手实践的案头资料。
1. 词云项目的真实门槛:为什么七个案例比一个“Hello WordCloud”更值得看
很多人对词云的第一个印象是“一行WordCloud().generate(text)就完事”,真到要交作品、要在汇报里放一张图的时候,才发现默认输出根本没法用:中文全是方框、词语被拆得七零八落、背景一块死白、形状是个规规矩矩的矩形,放在 PPT 里像是随手截的。词云在文本挖掘与可视化里属于典型的“入门容易、出效果难”,真正决定成品质量的不是那一行生成代码,而是字体、分词、蒙版、配色、权重这五个环节怎么串起来。这份以 wordcloud 1.9.3 与 matplotlib 3.5.3 为基础、基于 Python 3.7 与 PyCharm 环境整理的七个案例,走的是从最简调用一路加到关键词权重渲染的递进路线,适合正在做课程设计、需要把文本分析结果图形化交付的学生,也适合要在报告里快速出一张可读性过关的关键词图的从业者。
2. 环境与选型:两条库链路和一份文本素材的准备工作
先把地基打平,后面七个案例才不会在第 3 个就卡住。词云这件事在 Python 里其实只有两条链路:wordcloud 负责“算布局、画字形”,matplotlib 负责“显示和交互”,两者之间靠 numpy 数组传递图像。围绕这两条链路还会牵出三个配角:jieba 做中文分词、PIL(Pillow)读蒙版图、numpy 把图片转成 wordcloud 认得的数组。理解这个分工,后面每个案例多出来的import就都不是玄学,而是明确的职责扩容。
2.1 依赖清单与版本对齐
原文给出的基线是 Python 3.7 + wordcloud 1.9.3 + matplotlib 3.5.3,这个组合相对稳定,不建议为了追新而把三者版本拉得过开。安装本身没有技巧,关键是别只装 wordcloud 就以为万事大吉——中文案例必然要用 jieba,蒙版案例必然要用 Pillow 和 numpy。
# 核心两条链路 pip install wordcloud==1.9.3 pip install matplotlib==3.5.3 # 中文分词与蒙版读取所需的配角 pip install jieba pip install pillow numpy参数说明上只有一个点值得强调:wordcloud 在部分平台上装老版本时可能走源码编译,如果pip install长时间停在 building wheel,通常的做法是先确认本机是否有可用的 C 编译环境,或者改用与当前 Python 小版本匹配的预编译包。这不是教程的重点,但它是新手第一天最容易翻车的地方,先在这里排掉。
文本素材上,原文用了两份:一份英文纯文本constitution.txt用于最简调用,一份中文长文本xyj.txt(以西游记为内容)用于后续所有中文与蒙版案例,读取时统一encoding='utf-8'。我一般会把这几个文件放在项目上一级目录,代码里用../xyj.txt这种相对路径引用,这样七个案例放在同一个工程的不同脚本里时,路径不用各改一遍。
2.2 中文字体的处理策略
中文词云出现满屏方框,原因从来不是 wordcloud 不支持中文,而是默认字体里没有中文字形。wordcloud 的font_path参数就是给这件事准备的,原文案例里统一指向了一个本地字体文件Hiragino.ttf。
# 中文场景下 font_path 是必填项,缺失即出现方块字 wc = WordCloud( font_path='../Hiragino.ttf', # 指向本机存在的中文字体文件 width=800, # 画布宽度,像素 height=600, # 画布高度,像素 mode='RGBA', # 带透明通道,便于叠加背景 background_color=None # 透明背景,导出 PNG 后可直接贴 PPT )这里每个参数都有明确用途,不是凑数:font_path解决字形,width/height决定分辨率(800×600 是汇报场景够用的下限,要放大到海报级别就得往上调),mode='RGBA'配合background_color=None得到的是透明底图,这一组搭配是“图能直接放进深色或彩色背景版式”的关键。很多人只改字体不改背景,结果导出的图带着一块白底,往深色模板上一贴就露出一个方块,这种细节在答辩现场特别扎眼。
提示:
font_path请指向本机上真实存在的字体文件路径,不同操作系统的字体目录不同,写死一个绝对路径换台机器就跑不起来,相对路径 + 随项目携带字体文件是更稳的做法。
3. 从最简调用到中文分词:前三个案例解决“能不能出图”
前三个案例是一条清晰的爬坡线:先确认库能跑通,再暴露中文的字体问题,最后用分词把中文词云的质量拉起来。这条线值得按顺序走一遍,因为跳过第一步直接写分词版本,一旦报错就很难判断是环境问题还是逻辑问题。
3.1 案例一:最简调用的五步骨架
最简版本只有五步,但它是后面所有案例的骨架,值得拆开看每一行的作用。
# -*- coding: utf-8 -*- from wordcloud import WordCloud import matplotlib.pyplot as plt # 1. 打开文本 text = open('constitution.txt').read() # 2. 生成对象:默认参数,英文文本无需指定字体 wc = WordCloud().generate(text) # 3. 显示词云:bilinear 插值让缩放后的字形边缘更柔和 plt.imshow(wc, interpolation='bilinear') plt.axis('off') # 关掉坐标轴,否则图边会出现刻度 plt.show() # 4. 保存到文件 wc.to_file('wordcloud.png')五步分别是读文本、建对象、渲染显示、去坐标轴、落盘。generate(text)内部做的是分词(英文按空格)、统计词频、按词频分配字号、然后把词一个个塞进画布,塞不下的词会被丢弃——这也是为什么词云里通常不会出现文本里的全部词汇。interpolation='bilinear'不是装饰参数,词云内部生成的是低分辨率布局再放大,不加插值会出现锯齿感明显的边缘。plt.axis('off')属于必须加的一行,忘了它,输出图四周会带一圈坐标刻度,看起来像没做完的半成品。
这个案例的价值在于建立“基线认知”:默认参数下英文词云是可以看的,所以后面中文出问题时,你能立刻判断问题出在字体而不是库坏了。
3.2 案例二:不分词的中文,长什么样
第二个案例把文本换成了中文长文本,只加了字体、尺寸、透明模式三组参数,故意不做分词。
with open('../xyj.txt', 'r', encoding='utf-8') as f: text = f.read() wc = WordCloud( font_path='../Hiragino.ttf', width=800, height=600, mode='RGBA', background_color=None ).generate(text)这一个案例刻意保留了“错误示范”的价值:中文没有空格分隔,wordcloud 拿不到词边界,只能按它自己的切分规则硬切,结果就是词云里既有正常词语也有莫名其妙的碎片,语义读起来断断续续。字体问题解决了(不再有方框),但可读性问题暴露了。这就是方案里“先解决字形、再解决词形”的分层思路——两类问题的现象很像(都表现为“图不好看”),但成因完全不同,混在一起调只会来回打转。
3.3 案例三:jieba 分词把可读性拉回来
第三个案例引入 jieba,改动只有一行,但效果是质变。
import jieba with open('../xyj.txt', 'r', encoding='utf-8') as f: text = f.read() # jieba.cut 返回生成器,用空格拼接成 wordcloud 认得的输入格式 text = ' '.join(jieba.cut(text)) print(text[:100]) # 打印前 100 字符,肉眼确认分词结果是否合理 wc = WordCloud(font_path='../Hiragino.ttf', width=800, height=600, mode='RGBA', background_color=None).generate(text)jieba.cut(text)返回的是生成器而不是列表,必须用' '.join(...)转成空格分隔的字符串,否则 wordcloud 收到的类型不对会直接报错。这一行的本质是“把中文改造成英文词云的输入格式”,理解这点之后,后面换成任何权重字典的形式(案例七)也就顺理成章了。
print(text[:100])这行调试语句别嫌土,它是分词环节唯一的黑匣子读数:如果打出来的是“话说 唐三藏 师徒 四人 一路 西行”这类,说明分词正常;如果是一堆单字连缀,那多半是文本编码或 jieba 词典的问题,此时再怎么调 wordcloud 参数都是白调。jieba 本身支持精确模式、全模式、搜索引擎模式三种切分策略,默认走精确模式,做词云场景通常不需要换,只有在需要更高召回率(比如做关键词索引)时才考虑搜索引擎模式。
三个案例走完,你应该已经能稳定输出一张中文可读的词云图。接下来的四个案例不再解决“能不能”,而是解决“像不像、配不配、准不准”。
4. 蒙版与配色:三个案例把矩形图变成有设计感的成品
词云的视觉上限几乎完全由蒙版和颜色决定。同样是西游记文本,矩形灰字版和人物剪影彩色版在汇报里的说服力差了一个量级。这一段的三个案例是递进关系:先上形状,再上颜色来源,最后自定义颜色规则。
4.1 案例四:用蒙版替换矩形画布
蒙版(mask)本质是一张图,wordcloud 会读取它的非白色区域作为可填充范围,白色区域直接留空。
from PIL import Image import numpy as np # 蒙版图转 numpy 数组,wordcloud 只认数组形态 mask = np.array(Image.open("../black_mask.png")) wc = WordCloud( mask=mask, # 形状来源 font_path='../Hiragino.ttf', mode='RGBA', background_color=None ).generate(text)np.array(Image.open(...))这两步不能省,Image.open返回的是图像对象,wordcloud 要的是数组。蒙版图的选择有个经验:优先用“纯白背景 + 纯黑主体”的图,主体区域越大、边缘越干净,词填充得越完整;如果蒙版图本身是彩色的、带灰阶过渡,填充区域会变得零碎,词会散成几团。原文用的black_mask.png就属于前一类。另外,加了mask之后可以不写width/height,画布尺寸会跟随蒙版图尺寸走,写了也会被蒙版覆盖,这点容易让人误以为尺寸参数失效。
4.2 案例五:让颜色从蒙版图里长出来
形状对了,颜色还是单调的,第五个案例用ImageColorGenerator从蒙版图本身提取配色。
from wordcloud import WordCloud, ImageColorGenerator mask = np.array(Image.open("../color_mask.png")) wc = WordCloud(mask=mask, font_path='../Hiragino.ttf', mode='RGBA', background_color=None).generate(text) # 依据蒙版图中每个词所在位置的颜色,为词着色 image_colors = ImageColorGenerator(mask) wc.recolor(color_func=image_colors)ImageColorGenerator的逻辑是:对每个词,取它在蒙版图上占据区域的平均颜色,作为该词的颜色。所以蒙版图的色彩分布直接决定了成图风格——原图色调偏暖,词云就偏暖;原图有分区色块,词云也会跟着分区。wc.recolor()必须在generate()之后调用,顺序反了不生效;这是这个案例唯一容易写错的顺序问题。透明背景配mode='RGBA'时,重着色后仍然保留透明通道,导出贴到任何底色上都不会有白边。
4.3 案例六:自定义颜色函数的可控性
从图取色省事,但配色受限于原图。第六个案例换成自己写颜色函数,用 HSL 色相环控制风格。
import random # 颜色回调:wordcloud 为每个词调用一次,返回值即该词颜色 def random_color(word, font_size, position, orientation, font_path, random_state): # 色相固定 0(红色系),饱和度与亮度在 60%~80% 之间浮动,避免过艳或过暗 s = 'hsl(0, %d%%, %d%%)' % (random.randint(60, 80), random.randint(60, 80)) return s wc = WordCloud(color_func=random_color, mask=mask, font_path='../Hiragino.ttf', mode='RGBA', background_color=None).generate(text)回调函数的签名是固定的六个参数,即使你一个都不用也必须完整声明,少一个参数 wordcloud 调用时就会抛类型错误,这是自定义颜色时最常见的翻车点。原函数里那句print(s)建议保留在调试阶段,能直观看到每个词拿到的颜色值,确认色相范围是不是你想要的那个区间。通过调整hsl的第一个分量,就能在红、蓝、绿等色系之间整体切换,饱和度与亮度控制在 60–80 这个窄区间,是为了让整张图的明度统一,不会出现几个词特别刺眼、几个词糊在背景里的情况。
三个蒙版案例连起来看,其实是一条“可控性递增、便利性递减”的曲线:蒙版形状解决布局,取色解决风格统一,自定义函数解决品牌色或主题色的精确控制。做课程设计时如果只需要一张好看的图,案例五够用;如果是给某个活动、某个主题做视觉,案例六才有意义。
5. 关键词与权重:案例七为什么要放弃词频
前六个案例全部基于generate(text),也就是按词频决定字号。这在长文本上问题不大,但在报告、摘要、评论这类短文本上,词频会严重失真:虚词高频、专有名词低频,出来一张图满是“我们”“这个”。第七个案例改用jieba.analyse.extract_tags提关键词和权重,再走generate_from_frequencies,这是整套方案里最接近“文本挖掘”而非“文本装饰”的一步。
5.1 用 TF-IDF 权重喂给词云
import jieba.analyse with open('../xyj.txt', 'r', encoding='utf-8') as f: text = f.read() # topK 控制取前多少个关键词,withWeight=True 返回 (词, 权重) 二元组 freq = jieba.analyse.extract_tags(text, topK=200, withWeight=True) print(freq[:20]) # 先看前 20 个,确认关键词质量 # 转成 {词: 权重} 字典,generate_from_frequencies 只认这个结构 freq = {i[0]: i[1] for i in freq} mask = np.array(Image.open("../color_mask.png")) wc = WordCloud(mask=mask, font_path='../Hiragino.ttf', mode='RGBA', background_color=None ).generate_from_frequencies(freq) image_colors = ImageColorGenerator(mask) wc.recolor(color_func=image_colors) wc.to_file('main_07.png')topK=200是词量与可读性的平衡点:词太少,蒙版填不满,图和形状对不上;词太多,小字号词挤成一团,反而看不清主次。200 这个量级在中等长度的中文文本上通常正好。extract_tags默认基于 TF-IDF,它会把“在本文里频繁、但在通用语料里也频繁”的词权重压低,所以虚词、常见动词会被自动降权,这正是词频方案缺的那一环。
freq从列表转字典这一步是必须的,generate_from_frequencies接受的是{词: 数值}映射,直接传二元组列表会报错。另外注意它内部不会再去分词,词条长短、是否重复全靠你传进去的字典,所以去重这一步也由字典天然完成。
5.2 两种生成方式的取舍
| 对比项 | generate(text) | generate_from_frequencies(dict) |
|---|---|---|
| 输入形态 | 原始字符串 | 词到权重的映射 |
| 字号依据 | 词频 | 传入的权重值 |
| 是否内部分词 | 是 | 否,依赖上游已分好 |
| 适合场景 | 长文本概览、快速出图 | 短文本、报告、需精确控制主题词 |
| 与 jieba 关系 | 可配合分词 | 天然与关键词提取衔接 |
这张表可以作为选型的判断依据:如果文本来源是整本书、整站评论,generate足够;如果是几十条反馈、一篇摘要、一段产品描述,词频噪声太大,就该走generate_from_frequencies。原文把这条路线放在最后一个案例,顺序是对的——先让你看到默认方式的局限,再给出替代路径,比一上来就讲权重更容易理解为什么需要它。
6. 避坑与排查:五个最容易让词云项目返工的坑
七个案例跑完不等于交付完成,真正在答辩或评审现场出问题的,往往不是这些主线代码,而是下面这几类边角。每条按现象、原因、解决三层说。
第一,中文满屏方块。现象是图能出但文字变成一个个方框。原因是font_path没写或指向了不含中文字形的字体。解决办法是明确指定一个本机存在的中文字体文件,并且用相对路径随项目一起走,换机器时才不会断。这个坑在案例二就埋了,跳过它直接做蒙版案例,症状会一直带着。
第二,词云图四周带刻度线或白边。现象是导出的图看起来像半成品。原因分别是忘了plt.axis('off'),以及mode与background_color没配对。解决办法是把这两行固定成模板的一部分:显示前关轴,生成时给mode='RGBA'加background_color=None。
第三,蒙版填不满、词全挤在角落。现象是形状有了但只填充了一小块。原因是蒙版图的白色区域判定不干净,或者蒙版带灰阶导致可填充区域被切碎。解决办法是换一张纯白底、纯黑主体的二值化蒙版图,必要时先用图像工具把背景刷成纯白。这个坑很隐蔽,因为代码没有任何报错,纯靠看图判断。
第四,recolor写了但颜色没变。现象是调用了重着色,输出还是默认配色。原因是调用顺序错了,recolor必须在generate或generate_from_frequencies之后。解决办法是记牢“先生成后着色”这条顺序。
第五,自定义颜色函数一跑就报参数错误。现象是TypeError。原因是回调函数只写了实际用到的参数,而 wordcloud 是按固定六参数签名调用的。解决办法是老老实实写全word, font_size, position, orientation, font_path, random_state,用不到的放着即可。
注意:调试词云时始终先
7. 验收与答辩:用一张检查表和一次复现把方案交出去
词云项目的验收不该只停在“图出来了”。我在带这类作品时,习惯用一张固定的检查表过一遍,逐项打勾,缺一项就回去补,这样能避免答辩现场被问到“为什么这个词这么大”“这个字怎么是方块”时答不上来。
| 检查项 | 合格标准 | 对应案例 |
|---|---|---|
| 中文显示 | 无方框、无乱码 | 案例二、三 |
| 分词质量 | 打印前 100 字符,词语边界清晰 | 案例三 |
| 背景处理 | RGBA + 透明底,贴任意底色无白边 | 案例二起 |
| 形状匹配 | 蒙版填充率目视达七成以上 | 案例四 |
| 配色统一 | 明度区间收敛,无刺眼单词 | 案例五、六 |
| 关键词质量 | 前 20 个关键词无虚词、无单字碎片 | 案例七 |
| 可复现性 | 换机后按依赖清单重装即可跑通 | 全流程 |
检查表之外,答辩还有一个高频动作:现场改参数看结果。评审常问的是“如果文本换成一段短评论会怎样”“字号范围能不能调”。这时候你要能立刻说出改哪里——topK控制词量,max_font_size与min_font_size控制字号区间,max_words控制总词数,stopwords控制屏蔽词。把这几个参数和对应效果背下来,比背代码有用得多。原文没有展开这几个参数,但它们属于这个项目场景下必然会被问到的部分,通常的做法是把它们写进代码注释里,作为参数速查。
还有一个容易被忽略的验收点:复现性。把你的工程目录、字体文件、蒙版图、文本素材、依赖清单一起打包,然后在另一个干净环境里从头跑一遍。这一步是血泪经验——本地能跑不代表交出去能跑,最常见的是路径写成了绝对路径、字体文件忘了打包。我一般会在 README 里写死三行:Python 版本、两条核心库版本、运行时需要存在的素材文件名,评审照着装就行,省掉一轮来回沟通。
从那以后我每次做完这类可视化项目,都会强制走一遍“换环境复现 + 检查表逐项过”的流程,哪怕时间紧也绝不跳。图好看是一时的,能被别人稳定跑出来才是这份方案真正的交付价值。希望帮到你。
本文还有配套的精品资源,点击获取