如何用 Python 写一个优雅的词云

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。

1. 模块安装

通常我们的安装方式有两种,一种是直接使用 pip 安装,我们打开 cmd 执行下列语句:

pip install wordcloud
复制代码

另外我们还可以去这里下载 wordcloud 的 whl 文件,进入网址后如图,我使用的是 Python 3.7,64 位,所以我下载红框部分的文件:

在这里插入图片描述

下载后我们进入文件的根目录:

cd C:\Users\zaxwz\Downloads
复制代码

然后执行下列语句:

pip install wordcloud-1.6.0-cp37-cp37m-win_amd64.whl
复制代码

install 后面部分为文件的全称,我们也可以选择打出 wordc,然后使用 tap 键自动补全。执行上面语句后就开始安装 wordcloud 模块了。

2. wordcloud 模块介绍

我们词云的主要实现是用过 wordcloud 模块中的 WordCloud 类实现的,我们先来了解一个 WordCloud 类。

2.1 生成一个简单的词云

我们实现一个简单的词云的步骤如下:

  1. 导入 wordcloud 模块
  2. 准备文本数据
  3. 创建 WordCloud 对象
  4. 根据文本数据生成词云
  5. 保存词云文件

我们按照上面的步骤实现一个最简单的词云:

# 导入模块
from wordcloud import WordCloud
# 准备文本数据
sentence = "Do not go gentle into that good night!"
# 创建词云对象
wc = WordCloud()
# 根据文本数据生成词云
wc.generate(sentence)
# 保存词云文件
wc.to_file("wc.png")    
复制代码

我们按照上述步骤,实现一个简单词云的代码正好是五句,我们实现的效果如下:

在这里插入图片描述

可以看到,上面词云还是很单调的,背景也是全黑的,我们会在后续的学习中慢慢改进。

2.2 构造 WordCloud 的一些参数

我们先看看 WordCloud 中的一些参数,如下表,各个参数的介绍都写了。

参数 参数类型 参数介绍
width int(default=400) 词云的宽
height int(default=200) 词云的高
background_color color value(default=”black”) 词云的背景颜色
font_path string 字体路径
mask nd-array(default=None) 图云背景图片
stopwords set 要屏蔽的词语
max_font_size int(default=None) 字体的最大大小
min_font_size int(default=None) 字体的最小大小
max_words number(default=200) 要显示词的最大个数
contour_width int 轮廓粗细
contour_color color value 轮廓颜色
scale float(default=1) 按照原先比例扩大的倍数

我们来测试一下上面的参数:

# 导入模块
from wordcloud import WordCloud
# 准备文本数据
sentence = "He had already passed sixty of the stages leading to it, and he had brought from his journey nothing but errors and remorse. Now his health was poor, his mind vacant, his heart sorrowful, and his old age short of comforts."
# 准备禁用词,需要为set类型
stopwords = set(['go', 'to'])
# 设置参数,创建WordCloud对象
wc = WordCloud(
    width=200,                  # 设置宽为400px
    height=150,                 # 设置高为300px
    background_color='white',    # 设置背景颜色为白色
    stopwords=stopwords,         # 设置禁用词,在生成的词云中不会出现set集合中的词
    max_font_size=100,           # 设置最大的字体大小,所有词都不会超过100px
    min_font_size=10,            # 设置最小的字体大小,所有词都不会超过10px
    max_words=10,                # 设置最大的单词个数
    scale=2                     # 扩大两倍
)
# 根据文本数据生成词云
wc.generate(sentence)
# 保存词云文件
wc.to_file('wc.png')
复制代码

执行上述代码,生成如下词云:

在这里插入图片描述

我们使用如下代码获取图片的大小:

import os
# 获取文件大小
size = os.path.getsize('./wc.png')
# 输出大小
print(size)
复制代码

输出结果如下:

24966
复制代码

我们在构造 WordCloud 对象时,将 scale 设置为 1,将获取的词云文件保存为 wc2.png,我们按照上面的代码输出其大小,结果如下:

11988
复制代码

发现内存减半了,笔者最开始不知道这个属性的时候将它设置为 15,导致产生了一张 100M 的图片。

在上面的参数中,还有一些会在后面给大家讲解到。

2.3、WordCloud 的一些方法

这里说三个我们要用到的方法,具体如下:

方法名称 传入参数 方法描述
generate text 根据文本生成词云
recolor [random_state, color_func, colormap] 对现有输出重新着色
to_file filename 输出到文件

其中 to_file 我们已经使用过了,就是传入文件路径就可以了,generate 也使用过,传入文本,让 WordCloud 对象根据文本生成词云。recolor 方法后续会使用到,后面再给大家讲解。

2.4 生成一个有形状的词云

上面的例子我们都是使用单调的矩形,下面我们利用 WordCloud 的 mask 属性,生成一个有形状的词云。我们先准备好应该文本数据,我选取了乔布斯在斯坦福的演讲,保存为 jobs.txt 文件,这是是全英文的,我们先读取文件:

# 以只读形式,utf8编码打开文件jobs.txt
f = open('jobs.txt', 'r', 'utf8')
# 读取文件中数据
article = f.read()
# 关闭文件
f.close()
复制代码

我们有了文本数据后,我们还需要一个 ndarray 对象,有许多方法可以获取,这里使用 opencv:

# 读取图片,返回ndarray对象
im = cv2.imread('1.png')
复制代码

opencv 的安装如下:

pip install opencv-python
复制代码

然后我们就可以开始生成词云了,完整代码如下:

from wordcloud import WordCloud
import cv2
# 打开文件
f = open('jobs.txt', 'r', encoding='utf8')
# 读取文件
article = f.read()
# 关闭文件
f.close()
# 读取图片
im = cv2.imread('1.png')
# 生成词云
wc = WordCloud(
    width=400,
    height=500,
    background_color='white',
    max_font_size=50,
    mask=im     # 设置mask属性,让词语按照im轮廓绘制词云(背景必须是全白的)
)
# 根据文本生成词云
wc.generate(article)
# 保存词云文件
wc.to_file('w2.png')
复制代码

效果图如下:

在这里插入图片描述

左边为 1.png,右边为生成的词云。

2.5 生成中文词云

在上面的例子中,我们全是使用英文作为文本数据,我们现在尝试使用中文作为文本数据,生成一个简单的词云。代码如下:

# 导入模块
from wordcloud import WordCloud
# 准备文本数据
sentence = "不要温顺的走进那个良夜"
# 创建词云对象
wc = WordCloud()
# 根据文本数据生成词云
wc.generate(sentence)
# 保存词云文件
wc.to_file("wc.png")    
复制代码

生成效果图如下:

在这里插入图片描述

发现全是矩形,这是因为 WordCloud 默认不支持中文的缘故,我们需要设置一个可以支持中文的字体,我们将代码修改为如下:

# 导入模块
from wordcloud import WordCloud
# 准备文本数据
sentence = "不要温顺的走进那个良夜"
# 创建词云对象
wc = WordCloud(font_path='msyh.ttc')
# 根据文本数据生成词云
wc.generate(sentence)
# 保存词云文件
wc.to_file("wc.png")
复制代码

在这里插入图片描述

上面我们设置了 font_path,字体文件可以在 C:\Windows\Fonts 中找到。但是我们又发现了一个问题,就是这次显示的并没有分词,而是一整句话。如果我们使用其它文章测试,也会发现词云是以句子的形式呈现的,解决这个问题就需要我们用到 jieba 分词模块了。

3. jieba 分词模块

3.1 使用 jieba 分词

我们先下载该模块:

pip install jieba
复制代码

jieba 分词的作用就是用来讲句子中可能是词语的部分分割出来,它的分割模式有三种,分别是全模式、精确模式和搜索引擎模式,我们这里了解一下精确模式:

import jieba
# 准备分词的句子
sentence = "不要温顺的走进那个良夜"
# 默认采用精确模式分词
words = jieba.cut(sentence)
# 将分好的词用" "连接
text = " ".join(words)
# 输出
print(text)
复制代码

输出结果如下:

不要 温顺 的 走进 那个 良夜
复制代码

3.2 jieba 结合 WordCloud 使用

我们可以先用 jieba 将句子分词,然后再作为文本数据生成词云,代码如下:

import jieba
from wordcloud import WordCloud
# 准备句子
sentence = "不要温顺的走进那个良夜"
# 创建WordCloud对象,设置字体
wc = WordCloud(font_path='msyh.ttc')
# 用jieba将句子分词
words = jieba.cut(sentence)
# 用“ ”将词语隔开
text = " ".join(words)
# 根据词语生成词云
wc.generate(text)
# 保存词云文件
wc.to_file('wc.png')
复制代码

生成词云如下:

在这里插入图片描述

会使用结巴分词工具后我们可以生成更为复杂的词云了。

4. ImageColorGenerator 对象

在上述的例子中,所有词云我们都没有对其颜色进行控制,而 ImageColorGenerator 对象就是一个获取图片颜色生成器的类,我们可以把它理解为一个取色器。在上面我们提到了 recolor 方法,一直都没有具体说,在这里我们就将使用到这个方法。

4.1 获取图像颜色

获取图形颜色非常简单,我们只需要创建一个 ImageColorGenerator 对象就可以了:

import cv2
from wordcloud import ImageColorGenerator
# 读取图片
im = cv2.imread('1.png')
# 获取图像颜色生成器
im_color = ImageColorGenerator(im)
复制代码

我们获取颜色后,就可以对图像进行重绘了。

4.2 重绘图像

我们使用 recolor 给词云上色,代码如下:

import cv2
import jieba
from wordcloud import WordCloud,ImageColorGenerator
# 读取图像
im = cv2.imread('1.jpg')
# 获取颜色生成器
im_color = ImageColorGenerator(im)
# 打开文件
f = open('csb.txt', 'r', encoding='utf8')
# 读取文件
article = f.read()
# 分词
words = jieba.cut(article)
# 拼接词语
text = " ".join(words)
# 创建词云对象
wc = WordCloud(
    background_color='white',
    font_path='msyh.ttc',
    mask=im,
)
# 根据文本生成词云
wc.generate(text)
# 给词语上色
wc.recolor(color_func=im_color)
# 保存词云
wc.to_file('wc.png')
复制代码

其中 csb.txt 是出师表,上述代码执行效果如下:

在这里插入图片描述

绿藻头就被形象的显示出来了,大家可以使用其它素材尝试一下。

本文所有代码都已上传 GitHub:

github.com/IronSpiderM…

Guess you like

Origin juejin.im/post/7061233300693581831