资讯详情

Python词云制作教程:wordcloud+jieba中文分词与七案例交付

📅 2026/11/2 7:40:55 | 华诺云谱 👁 阅读
Python词云制作教程:wordcloud+jieba中文分词与七案例交付
简介面向文本挖掘与数据可视化初学者及中级 Python 用户的词云实践教程围绕个性化词云的完整生成流程展开帮助读者掌握从文本预处理、词频或 TF-IDF 权重计算到用 wordcloud 与 matplotlib 出图、展示和保存的关键方法。压缩包共 1 个 PDF 文件大小约 2.07MB内容以图文讲解配合代码示例呈现便于按章节系统阅读。教程设置 7 个递进案例从最简调用到中文分词、蒙版形状、自定义配色及关键词与权重提取并附运行结果和环境版本说明同时讲解停用词过滤、字体路径与背景色设置、中文分词必要性等易错点可对照复现常见词云效果并迁移到报告、数据分析或社交媒体文本展示中。目前已有 109 人学习下载适合希望用案例快速入门并查漏补缺的读者。1. 从一份语料到七张成图这套 python 词云方案要解决的其实是交付问题很多人第一次做文本可视化本能反应是先统计词频、画柱状图、截图贴进报告——图是有了但答辩时被问一句「你想表达什么」就卡壳。词云反过来几十万字压成一张图出现得越多的词越大观众三秒就能抓住主线。这份 python 词云完整教程用 7 个案例把整条链路拆开——读文本、处理中文编码、分词、加蒙版、取色、提关键词权重、导出成图案例之间是递进关系不是七个孤立的 demo。它面向两类人要交一份能跑通的 python 课程资源的学生和需要在分析报告里放一张真正能看的图的从业者。下面按「选型 → 总体设计 → 逐案实现 → 避坑 → 验收」把这份资源拆成一份可照搬的方案。2. 环境与依赖选型wordcloud、matplotlib、jieba 的三层分工2.1 版本锁定与虚拟环境这套教程给出的环境是 python 3.7 wordcloud 1.9.3 matplotlib 3.5.3编辑器用 PyCharm。这三个数字看起来只是记录实际上决定了后面七个案例能不能一次跑通。wordcloud 的底层依赖是 pillow 和 numpy1.9.x 系列在 3.7 上的轮子wheel是齐全的matplotlib 3.5.3 是 3.7 上比较稳的一档再往上抬版本就会开始要求更高的 pythonpip install时会退化成源码编译在没装编译器的机器上直接失败。所以第一步不是写代码是把依赖钉死在一个独立环境里# 在项目根目录下创建虚拟环境避免污染全局 python python -m venv wcenv # 激活Linux / 类 Unix source wcenv/bin/activate # 如果是另一类操作系统用 wcenv\Scripts\activate # 按教程给出的版本一次性装齐 是硬约束不要省略 pip install wordcloud1.9.3 matplotlib3.5.3 jieba0.42.1 pillow numpypip install里用而不是直接写包名是因为词云这类小项目最容易死在「昨天还能跑、今天重装就报错」上。版本号写死之后requirements.txt也就是顺手的事——把上面那行命令里的包名和版本抄进去即可。jieba本身是纯 python 包版本约束没那么敏感但既然要交课程设计或毕设依赖表里少一行都算文档不完整。装完之后跑一句验证比打开编辑器看 import 有没有红线可靠得多# 一次性导入四个关键依赖并打印版本确认环境符合预期 import wordcloud, matplotlib, jieba, PIL print(wordcloud :, wordcloud.__version__) print(matplotlib:, matplotlib.__version__) print(jieba :, jieba.__version__) print(pillow :, PIL.__version__)四个版本号都打印出来且和预期一致说明环境这一关过了。如果 wordcloud 报ImportError: cannot import name WordCloud八成是装了个同名的空壳包或者安装过程被中断过pip uninstall wordcloud再重装即可这是踩过不止一次的坑。2.2 三个库各管一段别互相越界初学者最容易把这三个库用乱以为 jieba 也能画图或者以为 matplotlib 能直接读中文文本。实际分工很清楚记住一句话就够了——jieba 负责「切」WordCloud 负责「画」matplotlib 负责「显」。jieba 的角色是文本切分与关键词权重。中文不像英文有空格天然分隔不切词直接喂给 WordCloud它只会按空格切结果整段中文变成一个大 token词云里就孤零零几个词甚至只有一个。jieba 提供三种分词模式教程里用的是最常用的精确模式jieba.cut(text)试图把句子按最合理的方式切开适合词云这种要求「词有意义」的场景。另外两种是全模式把所有可能成词的都扫出来快但歧义多和搜索引擎模式在精确模式基础上对长词再切适合建索引。做词云精确模式加默认词典基本够用。WordCloud 的角色是布局与合成。generate(text)这一行内部干了很多事按空格把文本切成 token、统计词频、按画布尺寸做碰撞检测排布、用 PIL 把每个词画上去、最后返回一个 WordCloud 对象。注意它返回的不是 PIL Image而是自己——这个对象实现了数组接口所以能直接塞进plt.imshow()。matplotlib 的角色是显示、坐标轴控制与图形管理。它只负责把 WordCloud 对象当成一张图渲染出来。plt.axis(off)去掉坐标轴刻度是词云图的基本礼貌带刻度的词云图在报告里一眼就显得外行。真正落到文件则不需要 matplotlib 参与WordCloud 自带to_file()。提示plt.show()和wc.to_file()是两条独立的路前者把图送到屏幕或编辑器内嵌窗口后者直接写磁盘。答辩用的图一定要走 to_fileshow()出来的东西在切换到下一张图时会消失。2.3 目录约定语料、字体、蒙版、输出分开放七个案例会用到四类外部文件文本语料、中文字体、蒙版图片黑色形状图和彩色取色图、输出图片。混在一个目录里跑第一天还行第三天自己都分不清哪张是蒙版哪张是结果。我一般会这样摆wordcloud-demo/ ├── data/ # 语料 │ └── novel.txt ├── fonts/ # 中文字体文件 │ └── your_font.ttf ├── masks/ # 蒙版图 │ ├── black_mask.png # 黑底白形决定形状 │ └── color_mask.png # 彩色原图决定配色 ├── output/ # 生成的词云图 └── cases/ # 七个案例脚本四个目录各自独立的好处不光是整洁。案例 04 到 07 都依赖masks/如果蒙版和输出图同名同目录to_file(main_4.png)覆盖掉蒙版是分分钟的事而蒙版一旦被覆盖后面三个案例全部失效这种翻车在赶 due 的夜里格外致命。目录先立住再动代码。3. 总体设计四段流水线把「一坨文本」变成「一张图」3.1 预处理层编码、标点、停用词词云的质量九成取决于预处理而不是WordCloud()里的参数。这一层要做四件事顺序不能乱。第一是编码。中文语料几乎不可能是 ASCIIopen()不带encoding参数时会用系统默认编码打开在某些环境下直接抛UnicodeDecodeError。教程里七个案例统一用with open(path, r, encodingutf-8) as f是标准写法with顺便把文件句柄管好避免长脚本里句柄泄漏。第二是标点与噪声。词云里出现一堆「」「。」「——」是典型的新手痕迹。jieba 分词后可以用正则把非中文字符滤掉或者维护一个小型停用词表。停用词表不需要多权威把自己语料里高频但无信息量的词如「一个」「我们」「可以」随手加进去就够用几十个词的规模已经能明显改善成图效果。第三是长度过滤。WordCloud 有min_word_length参数默认对英文有效但对中文作用有限更稳妥的做法是在预处理阶段用len(w) 2筛掉单字。中文单字成词的绝大多数是虚词或语气词留在图里只会占地方。第四是采样上限。max_words默认 200对大语料来说完全够用。真要做全量建议先统计词频取 topN再走案例 07 那条generate_from_frequencies的路线比让generate()自己数要可控。3.2 权重层词频、TF-IDF 与 extract_tags 三条路线词云里字的大小对应权重而权重的来源有三种各自适用场景不同。路线一词频默认。generate(text)直接按出现次数定大小。优点是零成本缺点是对长文本不公平——「的」「了」这类词天然高频即使加了停用词某些语义弱的词依然会占据视觉中心。适合语料干净、主题集中的场景。路线二TF-IDF。词频乘以逆文档频率能压掉跨文档的通用词。问题在于单文档场景下 IDF 无从计算除非你手上有语料集。所以教程的七个案例没有直接上 TF-IDF这不是偷懒是单文档做 TF-IDF 意义有限。路线三jieba.analyse.extract_tags。这是 jieba 内置的关键词提取基于 TF-IDF 思路但内置了一份通用语料的 IDF 表单文档也能跑。案例 07 用的就是它extract_tags(text, topK200, withWeightTrue)返回[(词, 权重), ...]列表权重是归一化后的小数直接喂给generate_from_frequencies()就能出图。这条路线的实际收益很明显——图上留下的全是真正承载主题的名词和动词虚词基本绝迹。3.3 渲染层mask、color_func 与 canvas 的执行顺序渲染层有三个东西会互相影响画布尺寸、蒙版、颜色函数。它们的作用顺序是固定的理解了这个顺序调参就不会瞎试。mask一旦传入画布的宽高就以蒙版的像素尺寸为准此时再传width/height是无效的——这是案例 04 之后所有案例都不写尺寸的原因。蒙版要求是「白形黑底」的数组词只往非黑区域填。np.array(Image.open(...))把 PIL 图转成三维数组高、宽、通道WordCloud 内部按亮度判断哪些像素可画。color_func在布局完成之后逐个词调用决定每个词的颜色。签名是func(word, font_size, position, orientation, font_path, random_state)返回一个颜色字符串。案例 06 用 HSL 拼随机色就是在这个函数里返回hsl(0, 70%, 70%)这种格式。recolor(color_func...)是布局完成后的二次上色案例 05 的ImageColorGenerator(mask)走的就是这条路先用蒙版形状排好版再按蒙版原图对应位置的颜色给每个词上色效果是词的颜色和背景图色调融为一体。顺序反了就不生效这是很多人卡住的地方。3.4 关键参数与调参方向参数作用默认调参方向font_path中文字体文件路径无英文默认字体中文必填否则全是方框width/height画布尺寸400 × 200传了 mask 就失效mask形状蒙版数组None白形黑底决定轮廓background_color背景色black配modeRGBA用 None 出透明底max_words最多显示词数200语料大时上调到 500min_font_size最小字号4图空时上调图挤时下调max_font_size最大字号自动想让主词更突出就限死color_func逐词配色函数随机色自定义 HSL 或按蒙版取色mode图像模式RGB透明背景配RGBAcontour_width轮廓线宽0加 2~4 会有描边感这张表不需要背调参时对着看就行。真正需要提前想清楚的是font_path和mask两项——它们决定了图能不能出、像不像样其余参数属于打磨阶段的事。4. 七个案例的递进实现从五行代码到带权重的关键词图4.1 案例 01最小闭环先把「跑通」这件事做掉第一个案例的价值不在于效果而在于用最短的代码验证环境、文件读取、出图三步都通。任何项目我都建议先做这一步别一上来就蒙版加取色出了错都不知道是哪一层的问题。# -*- coding: utf-8 -*- from wordcloud import WordCloud import matplotlib.pyplot as plt # 1. 读语料with 保证句柄释放 with open(data/sample_text.txt, r, encodingutf-8) as f: text f.read() # 2. 默认参数生成先不管好看不好看 wc WordCloud().generate(text) # 3. 交给 matplotlib 显示关掉坐标轴 plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() # 4. 落盘答辩用的就是这张 wc.to_file(output/wordcloud.png)interpolationbilinear是插值方式词云是位图双线性插值能让缩略图看起来平滑一些不写也能出图只是放大时锯齿明显。这段代码的失败点只有一个语料文件路径不对报FileNotFoundError。所以文件路径要么用相对脚本的路径要么干脆用os.path.join拼绝对路径。案例 01 用英文语料是刻意的先不引入字体和分词两个变量把黑匣子缩小到一个。4.2 案例 02-03中文的两个坎——字体与分词案例 02 是第一道坎中文塞进WordCloud()之后图上一片方框。原因很直白WordCloud 默认字体不含中文字形。解决方式是指定font_path指向一个真实存在的中文字体文件。# -*- coding: utf-8 -*- # 中文不分词只解决字体不解决切词 from wordcloud import WordCloud import matplotlib.pyplot as plt with open(data/novel.txt, r, encodingutf-8) as f: text f.read() wc WordCloud( font_pathfonts/your_font.ttf, # 必须指向真实存在的中文字体 width800, height600, # 画布尺寸比默认值大一圈 modeRGBA, # 支持透明通道 background_colorNone # 背景透明方便贴到 PPT 上 ).generate(text) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(output/main_2.png)modeRGBA加background_colorNone是一对组合缺一个都出不来透明底前者告诉 PIL 保留 alpha 通道后者告诉 WordCloud 别填背景色。这套参数从案例 02 一直沿用到 07是整份教程最实用的一个固定搭配。不过案例 02 图出来的效果会让人失望——中文不分词的时候WordCloud 按空格切整段文本挤成极少数几个巨型 token图基本是空的。这正是案例 03 要解决的问题。# -*- coding: utf-8 -*- # 中文分词在字体基础上补上切词 from wordcloud import WordCloud import matplotlib.pyplot as plt import jieba with open(data/novel.txt, r, encodingutf-8) as f: text f.read() # 精确模式切词再用空格拼回去WordCloud 才认得 text .join(jieba.cut(text)) print(text[:100]) # 打印前 100 字肉眼确认切得对不对 wc WordCloud( font_pathfonts/your_font.ttf, width800, height600, modeRGBA, background_colorNone ).generate(text) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(output/wordcloud.png) .join(jieba.cut(text))这一行是整个教程的关键转折点jieba 返回的是生成器直接塞给 WordCloud 不认用空格 join 成字符串后WordCloud 的默认分词器按空格切正好还原成词列表。中间那句print(text[:100])别删它是唯一能低成本确认分词质量的窗口——如果打印出来是一堆单字说明 jieba 词典没加载好如果是长句没切开检查是不是误用了全模式。4.3 案例 04-06蒙版形状、蒙版取色与自定义颜色函数案例 04 开始进图形。核心是mask参数需要一张「白形黑底」的图——形状部分为白色或高亮度其余为黑色。WordCloud 读取后只在亮区排词。# -*- coding: utf-8 -*- from wordcloud import WordCloud from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba with open(data/novel.txt, r, encodingutf-8) as f: text f.read() text .join(jieba.cut(text)) # 蒙版转数组注意是三通道 RGB mask np.array(Image.open(masks/black_mask.png)) wc WordCloud( maskmask, # 传了 maskwidth/height 自动失效 font_pathfonts/your_font.ttf, modeRGBA, background_colorNone ).generate(text) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(output/main_4.png)这里有个隐式约束蒙版图必须是 RGB 三通道。如果拿一张带 alpha 的 PNG 直接转数组会得到四维高、宽、4WordCloud 处理时会出问题稳妥的做法是打开时先Image.open(...).convert(RGB)。案例 05 解决「颜色和形状不搭」的问题。用一张彩色原图做蒙版形状来自它配色也来自它# -*- coding: utf-8 -*- from wordcloud import WordCloud, ImageColorGenerator from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba with open(data/novel.txt, r, encodingutf-8) as f: text f.read() text .join(jieba.cut(text)) mask np.array(Image.open(masks/color_mask.png).convert(RGB)) wc WordCloud( maskmask, font_pathfonts/your_font.ttf, modeRGBA, background_colorNone ).generate(text) # 关键一步布局完成后再按原图取色重新上色 image_colors ImageColorGenerator(mask) wc.recolor(color_funcimage_colors) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(output/main_5.png)ImageColorGenerator(mask)的逻辑是对每个词所在的像素区域取平均色作为这个词的颜色。所以蒙版原图里哪个区域偏红落在那个区域的词就偏红。recolor()必须在generate()之后调用顺序反了颜色不会生效——这一条我在第一次做的时候反复试了半小时才反应过来。案例 06 把颜色控制权完全交出来写一个自定义函数# -*- coding: utf-8 -*- from wordcloud import WordCloud from PIL import Image import numpy as np import matplotlib.pyplot as plt import random import jieba with open(data/novel.txt, r, encodingutf-8) as f: text f.read() text .join(jieba.cut(text)) def random_color(word, font_size, position, orientation, font_path, random_state): 逐词回调返回 HSL 字符串色相固定、饱和度和亮度在区间内抖动 s hsl(0, %d%%, %d%%) % ( random.randint(60, 80), # 饱和度 60%~80% random.randint(60, 80) # 亮度 60%~80% ) return s mask np.array(Image.open(masks/color_mask.png).convert(RGB)) wc WordCloud( color_funcrandom_color, # 函数对象不加括号 maskmask, font_pathfonts/your_font.ttf, modeRGBA, background_colorNone ).generate(text) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(output/main_06.png)回调函数的六个参数是固定签名用不到的可以不管但顺序不能改。色相写死成 0 是红色系把第一个 0 改成random.randint(0, 360)就是全色域。color_funcrandom_color传的是函数对象本身写成random_color()会在传参时立刻执行并返回一个字符串WordCloud 拿到字符串当函数调用直接报TypeError。4.4 案例 07用 extract_tags 拿权重generate_from_frequencies 出图最后一个案例把权重这条路走通也是七个里最接近「能交付」的一个。# -*- coding: utf-8 -*- from wordcloud import WordCloud, ImageColorGenerator from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba.analyse with open(data/novel.txt, r, encodingutf-8) as f: text f.read() # 直接对原始长文本提关键词不需要先分词 freq jieba.analyse.extract_tags(text, topK200, withWeightTrue) print(freq[:20]) # 先看一眼 top20 合不合理 freq {i[0]: i[1] for i in freq} # 转成 dict喂给下面的接口 mask np.array(Image.open(masks/color_mask.png).convert(RGB)) wc WordCloud( maskmask, font_pathfonts/your_font.ttf, modeRGBA, background_colorNone ).generate_from_frequencies(freq) # 注意不是 generate image_colors ImageColorGenerator(mask) wc.recolor(color_funcimage_colors) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(output/main_07.png)extract_tags的topK200控制返回词数withWeightTrue让它返回(词, 权重)二元组列表而不是纯词列表权重是归一化后的小数最大约 1。用字典推导式转成{词: 权重}之后调generate_from_frequencies注意这个方法名和generate不同它跳过分词和词频统计直接按你给的权重建图。这条路线相对前六个的优势是可控性你能在print(freq[:20])这一步提前发现问题。如果 top20 里全是「说道」「一个」这类词说明语料是叙事文本需要补停用词如果 top20 里有大量人名说明词云会围绕角色展开可以在报告里直接拿来说事。这张打印出来的列表本身就是分析结论的一部分比一张图更有说服力。5. 避坑与排查五个最容易翻车的点5.1 现象中文全变成方框豆腐块原因只有一个——font_path指向的字体不含中文字形或者路径根本不存在不存在时 WordCloud 会静默回退到默认字体不报错所以更难查。解决分两步先确认文件真实存在os.path.exists(font_path)打印一下再确认这份字体覆盖了中文。最稳的方式是直接拿系统里任意一款已知支持中文的字体文件复制到fonts/目录下路径写相对路径。注意字体文件缺失时不会抛异常只会静静出一张满是方框的图。所以字体路径要放在第一个被验证的位置而不是等到出图之后才回头怀疑。5.2 现象中文被一个字一个字拆开图上全是单字原因是漏了 .join(jieba.cut(text))这一步或者jieba.cut的结果直接传给了WordCloud()。WordCloud 收到生成器对象时不会报错它会把文本转成字符串再按空格切结果就是一个中文字符一个 token。解决就是补上 join。补完之后立刻print(text[:100])验证切得对不对肉眼一看便知。如果 join 了还是单字检查是不是误用了jieba.cut(text, cut_allTrue)全模式。5.3 现象蒙版形状不生效词还是铺满整个矩形三种可能蒙版不是白形黑底比如做成了黑形白底WordCloud 会认为是全黑一个词都放不下或者报错蒙版是 RGBA 四通道np.array出来形状不对同时传了mask和width/height尺寸被画布参数干扰。解决打开蒙版图convert(RGB)再转数组把蒙版图的形状部分做成纯白(255,255,255)、背景纯黑(0,0,0)别用灰色过渡传了 mask 就把 width/height 删掉。5.4 现象要求透明背景保存出来却是黑底或者白底原因是mode和background_color没有配对。只写background_colorNone而mode还是默认的RGBPIL 没有 alpha 通道可存透明会被填成黑色只写modeRGBA不写background_colorNone背景会被填成默认的黑。解决两个参数一起给。另外要确认输出格式是 PNGJPEG 不支持透明存成 jpg 透明区域一律变白。5.5 现象报ValueError: We need at least 1 word to plot a word cloud这条报错的意思是分词之后一个可用的词都没有。常见于三种情况语料文件路径错了读进来是空字符串编码read 成乱码jieba 切不出有效词stopwords或者min_word_length过滤得太狠把词全筛掉了。解决在generate之前加一行print(len(text), text[:100])长度是 0 就查路径长度正常但全是乱码就查 encoding长度和内容都对就临时去掉所有过滤参数跑一遍确认是哪个参数筛多了。这个报错虽然吓人但定位路径是最清晰的先看 print 就不会瞎猜。6. 验收与答辩怎么证明这套词云方案是真的跑通了七个案例跑完截图存了一堆但答辩或交付时被问「你这个方案完成度如何」光有图答不上来。我的做法是准备一张验收表逐项自查也直接给评审看。验收项检查方法合格线环境可复现新建虚拟环境按requirements.txt重装一条命令装完无编译报错中文渲染案例 02 出图没有一个方框字形完整分词质量打印text[:100]输出是词不是单字串蒙版生效案例 04 出图词严格落在形状轮廓内取色一致案例 05 出图词色与蒙版原图色调对应透明背景输出 PNG 拖进深色背景边缘无白边、无黑框权重可控案例 07 打印 top20前 20 词能用人话说出主题这张表的关键在于每一项都对应一个「可执行的检查动作」而不是「看起来不错」。比如「透明背景」这一项我会把 PNG 直接拖进一个深色底的 PPT 页面里看一眼白边和黑框立刻现形比如「权重可控」我会拿 top20 列表在报告里写一段结论写不出来就说明提取的词有问题得回去调停用词。答辩环节还有一步容易被忽略现场改一个参数再跑一遍。评审问「如果语料换成另一本书你要改什么」标准答案是只改data/下的文件路径和topK其余代码不动。为了证明这一点可以现场把max_words从 200 改成 50 重跑案例 07图会明显变稀疏——这一下比讲十句架构都管用。血泪经验是别现场演示第一次跑的代码任何没在干净环境下重跑过的脚本都可能当场给你脸色看。最后是一个习惯。从那以后我每次交图之前都会在空白目录里从零跑一遍这七个案例只信这一次输出的文件不信之前目录里的任何截图。词云这种「玄学感」很强的可视化参数改一行结果差很多靠记忆拼凑出来的效果图十有八九和代码对不上评审一追问就露馅。这套教程的七个案例、配套语料和蒙版图都打包在一起照着目录结构摆好从案例 01 一路跑到 07那份验收表上的七项就能一次性打满勾剩下的精力花在报告里怎么讲这张图比反复调颜色划算得多。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑