140行代码自己动手写一个词云制作小工具(文末附工具下载)

2021-08-05 15:23:52 浏览数 (1)

我们的第85篇原创

作者:才哥


大家好,我是才哥。

继之前出过表格拆分与合并小工具、pdf转word小工具后,今天我们迎来了词云制作小工具

记得在去年早些时候,我还不太熟悉python的时候,为了看看我们用户的评价和公开聊天信息关键词,在网上找了一些代码进行简单的参数修改就为出一张简单的词云图来。不过效果就很差了,没有停用词和自定义关键词等等概念,做出来的效果也差强人意不过似乎也还凑合当时不太会的偶。

其实,在往期的很多推文中都出现过词云制作的身影,今天我们就把它们封装起来,做成一个小工具分享给大家吧。

先看效果:

接下来,我们介绍这个小工具的制作过程。

1. 核心功能设计

简单来说,我们希望这个小工具在绘制词云图的时候可以自定义删除不想要的词、显示一些特殊汉字组合词(自定义关键词),同时词云的形状和字体能自定义等等。

那么,拆解需求,我们大致梳理出核心功能如下:

  • 确定待绘制词云的文本,三种情况(必填,否则会提示需要先选择待绘制文本)
  • 通过选定文本文件(txt文件)
  • 通过手动输入或复制粘贴文本
  • 以上两种方式均采取的时候会自动合并文本内容
  • 确定停用词(停用词就是词云图中不会出现的词,选填)
  • 通过选定文本文件(txt文件,每行一个停用词)
  • 通过手动输入停用词(词之间用“/”分开)
  • 以上两种方式均采取的时候会自动合停用词
  • 确定自定义关键词(关键词就是希望出现在词云图中的词,由于本工具采用jieba库,某些汉字组合词不一定是常规的词组,需要手动添加)
  • 通过手动输入停用词(词之间用“/”分开)
  • 可选择词云字体
  • 我这里是windows环境,且主要用于中文字符的词云绘制,所以小工具里只选择了5种字体供选择
  • 可选择背景图
  • 词云绘制时候形状背景图这里设定的是选定背景图文件即可
  • 对图片要求是白色底 深色形状轮廓
  • 词云绘制
  • 点击按钮执行绘制程序

基本功能点确定后,我们开始进行GUI设计

2. GUI设计与实现

基于功能点,我们可以先在草稿本上进行简单的UE布局设计,然后再通过GUI开发库进行设计,这里依旧采用的是pysimplegui,主要是简单方便。

UE设计稿图

基于手稿设计,我们编码如下:

代码语言:javascript复制
# 布局设置
layout = [[sg.Text('选择待绘制文件:',font=("微软雅黑", 12)),sg.InputText('可以不选', key='file',size=(60,1),font=("微软雅黑", 10),enable_events=True) ,sg.FileBrowse('打开',file_types=(("Text Files", "*.txt"),),size=(10,1),font=("微软雅黑", 11))],
          [sg.Text('选择停用词文件:',font=("微软雅黑", 12)),sg.InputText('也可以不选',key='stop_file',size=(60,1),font=("微软雅黑", 10),enable_events=True) ,sg.FileBrowse('打开',file_types=(("Text Files", "*.txt"),),size=(10,1),font=("微软雅黑", 11))],
          [sg.Text('输入待绘制的文本(可以直接复制文本到本地,不需求选择文本文件):',justification='center')],
          [sg.Multiline(size=(92, 8),font=("微软雅黑", 10),key='text')], 
          [sg.Text('自n定n义n词',font=("微软雅黑", 12)),sg.Multiline(tooltip='词与词之间用“/”分开',size=(40, 5),font=("微软雅黑", 10),key='add_words'),
           sg.Text('停n用n词',font=("微软雅黑", 12)),sg.Multiline(tooltip='词与词之间用“/”分开',size=(40, 5),font=("微软雅黑", 10),key='add_stopwords')],
          [sg.Text('词云字体:',font=("微软雅黑", 12)),sg.Combo(['微软雅黑','宋体','仿宋','隶书','Times New Roman'],font=("微软雅黑", 10), default_value='微软雅黑',size=(15, 5),key='fonts'),
           sg.Text('背景图:',font=("微软雅黑", 12)),sg.InputText('也可以不选,选则只能选取.png图片',key='bg_file',size=(40,1),font=("微软雅黑", 10)) ,sg.FileBrowse('打开',file_types=(("Text Files", "*.png"),),size=(10,1),font=("微软雅黑", 11))],
          [sg.Text('程序操作记录:',justification='center')],
          [sg.Output(size=(92, 8),font=("微软雅黑", 10))],  
          [sg.Text('操作说明:',font=("微软雅黑", 12))],
          [sg.Text('①如果是从文本文件进行绘制,则需要先选择待绘制文件n②如果是一段文本需要进行绘制,将文本复制到待绘制文本框',font=("微软雅黑", 10)),
           sg.Text('',font=("微软雅黑", 12),size=(10, 1)),
           sg.Button('开始绘制',font=("微软雅黑", 12),button_color ='Orange'),
           sg.Button('关闭程序',font=("微软雅黑", 12),button_color ='red')],
          ]    

其包含的控件如下:

  • Text 文本
  • InputText 输入文本框
  • FileBrowse 文件浏览
  • Multiline 多行文本框
  • Combo 下拉框
  • Output 程序输出显示框
  • Button 按钮

除了主界面之外,我们在绘制完词云图之后希望能直接弹窗展示,因此也需要一个用于浏览图片的界面与功能,这部分整体放在后续功能实现模块讲解。

3. 功能实现

当我们明确功能点以及有了GUI布局后,就开始着手实现功能逻辑。

3.1. 词云绘制功能

关于词云绘制功能更详细的介绍大家可以参考之前的《【推荐收藏】介绍2种Python绘制词云的手法,你会偷偷pick谁呢?》。

这里我们调用的也是stylecloud库,编写一个词云绘制的函数,按照核心功能需求,这个函数接收的参数分别是:

  • 待绘制词云的文本内容data
  • 自定义关键词addWords
  • 停用词stopWords
  • 背景图bg
  • 字体font_path

函数编写如下:

代码语言:javascript复制
def ciYun(data,addWords,stopWords,bg,font_path):

    print('正在作图...')
    comment_data = data
    
    for addWord in addWords:
        jieba.add_word(addWord)

    comment_after_split = jieba.cut(str(comment_data), cut_all=False)
    words = ' '.join(comment_after_split)
    
    # 词云停用词 
    stopwords = STOPWORDS.copy()
    for stopWord in stopWords:
        stopwords.add(stopWord)
    
    # 就下面代码,即可获取满足类型要求的参数
    stylecloud.gen_stylecloud(
                              text=words,
                              size = 700,
                              palette='tableau.BlueRed_6', # 设置配色方案
                              icon_name='fas fa-cloud',# thumbs-up
                              custom_stopwords = stopwords,
                              bg = bg, 
                              font_path=font_path,  # 词云图 字体(中文需要设定为本机有的中文字体)
                             )
    
    print('词云已生成~')
    pic_path = os.getcwd()
    print(f'词云图文件已保存在 {pic_path}')

接着,我们编写GUI的交互逻辑。

3.2. GUI交互逻辑

我们在前面有提到,对于绘制好的词云图,希望可以弹出自动预览,这里实现这个功能,采用的是pysimpleguiImage控件,传递参数是图片的地址pic_path

代码语言:javascript复制
# 词云图预览
def image_view(pic_path): 
    layout = [[sg.Image(pic_path, key="image",background_color='white',size=(700, 700))]
              ]
    window = sg.Window("词云图预览,作者@微信公众号:可以叫我才哥",layout)
    while True:
        event, values = window.read()
        if event in (None,'关闭'):
            break
    window.close()

然后,我们再对主界面的交互逻辑进行实现:

注:以下部分功能其实也可以封装成函数调用,大家有兴趣自行处理哈。

代码语言:javascript复制
# 创建窗口
window = sg.Window('词云制作工具,作者@微信公众号:可以叫我才哥', layout,font=("微软雅黑", 12),default_element_size=(50,1))    

# 事件循环
while True:
    event, values = window.read()
    if event in (None, '关闭程序'):
        break

    if event == '开始绘制':
        fileName = values['file']              # 待绘制词云文本文件
        stop_fileName = values['stop_file']    # 停用词文本文件
        text = values['text']                  # 待绘制词云文本(自己复制粘贴的内容)
        add_words = values['add_words']        # 自定义关键词 
        add_stopwords = values['add_stopwords']# 补充的停用词
        bg_fileName = values['bg_file']        # 词云背景图文件
        fonts = values['fonts']                # 词云字体
        font_path = fonts_dict[fonts]
        # 判断文本文件存在与否
        if os.path.exists(fileName):
            with open(fileName, "r", encoding='utf-8') as f:    #打开文件
                data = f.read()   #读取文件
        else:
            data = ''
        # 判断文本文件存在与否(其实可以不用pandas,打包还会更小)
        if os.path.exists(stop_fileName):
            stoptxt = pd.read_table(stop_fileName,encoding='utf-8',header=None)
            stoptxt.drop_duplicates(inplace=True)
            stopWords = stoptxt[0].to_list()
        else:
            stopWords = []
        # 判断背景图存在与否
        if os.path.exists(bg_fileName):
            bg=np.array(Image.open(bg_fileName))
        else:
            bg = ''
        
        # 组合待绘制文本、停用词和自定义关键词
        data = data   text
        stopwords = add_stopwords.rstrip().split('/')
        stopWords.extend(stopwords)
        addWords = add_words.rstrip().split('/')
        
        if len(data)>1:
            ciYun(data,addWords,stopWords,bg,font_path)
            pic_path = os.getcwd() "stylecloud.png"
            image_view(pic_path)
        else:
            print('待绘制词云文本未选择')
            
window.close()

由于在选择字体的时候,我们提供的是名称下拉框,所以这里需要创建一个字体名称与文件名的字典表,根据我们选定的字体组,这里创建的字典如下:

代码语言:javascript复制
# 字体字典
fonts_dict ={
    '仿宋':'simfang.ttf',
    '微软雅黑':'msyh.ttc',
    '宋体':'simsun.ttc',    
    '隶书':'SIMLI.TTF',
    'Times New Roman':'times.ttf',       
    }

基于此,词云绘制小工具就编码完成啦。

词云绘制小工具启动页

2021年高考语文各卷话题作文热词:

4. 关于打包成exe

由于依赖库中存在一些依赖配置文件如jieba库的dict.txtidf.txt文件、stylecloud库的fontawesome.min.css文件和一些图标文件以及wordcloud库的stopwords文件,我们直接用常规的打包命令是无法将这些配置文件一并打包进去的,虽然能够成功打包成exe文件,但是启动会失败。

由于本案例中还存在一些动态调用的库方式,所以就算将依赖文件打进去也会有找不到模块的问题。整得来说就是,常规的打包方式不太奏效,但是一两句话也说不太情况。所以我们后续将针对pyinstaller打包做一些比较全面的介绍,敬请期待啦。

以上就是本文全部内容,如果你感兴趣,点个赞和在看支持一下呗。

关于小工具可以后台回复955获取,在看达到10个微信私聊才哥领取源码哈!

0 人点赞