整合Tkinter GUI界面的古诗词词云生成
创始人
2024-05-02 12:54:25
0

         Python语言提供的wordcloud词云功能,使文本数据的可视化,简单而美丽。但网上的大多数词云生成功能,多半没有可交互的GUI界面,使用起来稍觉不便。笔者结合网上的中文词云功能,以唐诗三百首,宋词三百首,宋诗三百首和元曲三百首为数据源,把展示的词云整合到Python语言的Tkinter GUI界面中,可以随时在唐诗宋词元曲间切换词云的数据来源,也可选择某一个作者的作品生成词云,为古诗词的文本分析,提供了方便的可视化工具。

           如下是应用的界面,缺省显示唐诗三百首的词云:

            切换作品,选择宋词三百首,点击生成词云:

            从词云可以明显看出,唐诗和宋词的风格不一,主要的语词也不尽相同,但也有一定的相同之处,比如月,比如人,都是比较重要的词语。

         也可以切换不同的作者,查看生成的词云。唐诗三百首,选李白:

       李白喜欢月亮,经常邀月同饮;李白也自许甚高,所有我字也比较突出。

       看看杜甫:

       

       虽然也经常有月入诗,但已经没有李白那么突出了;而杜甫心忧天下,浑然忘我,词云中看不到我字。

        上面演示了功能, 下面讲一下代码如何实现的。从网上找到唐诗三百首,宋词三百首,宋诗三百首及元曲三百首的文本,然后读入到Python的list中,list中的元素为自定义PoetryWork类:

class PoetryWork(object):
    def __init__(self, num, title, author, content):
        self.num = num
        self.title = title
        self.author = author
        self.content = content
    def get_num(self):
        return self.num
    
    def get_author(self):
        return self.author
    
    def get_title(self):
        return self.title
    
    def get_content(self):
        return self.content

如下为加载唐诗三百首的代码:

#加载唐诗三百首
def load_tang_shi():
    tang_poet_list = {}
    num = ''
    title = ''
    author = ''
    content = []
    pattern = r'\d{3}'
    with open('唐诗三百首.txt', 'r', encoding= 'utf-8') as f:
        for line in f.readlines():
            if line:
                if re.match(pattern, line):
                    #内容不空
                    if content:
                        tang_poetry_list.append(PoetryWork(num, title, author, content))
                    pos = line.index(':')
                    num = line[:3]
                    author = line[3:pos]
                    if author in tang_poet_list:
                        tang_poet_list[author] += 1
                    else:
                        tang_poet_list[author] = 1
                        
                    title = line[pos+1:]
                    content = []
                    #print('num:{},author:{},title:{}'.format(num, author, title))
                else:
                    if line.strip():
                        content.append(line.strip())
                    
    tang_poetry_list.append(PoetryWork(num, title, author, content))    
    tang_poet_list = dict(sorted(tang_poet_list.items(),key=lambda x:x[1], reverse=True))
    poet_list = [x for x in tang_poet_list.keys()]  
    poet_list.insert(0,'all')
    
    return poet_list

       在加载过程中对唐诗按作者进行了统计,最后按作品数量倒序输出返回作者列表,填充界面上作者的下拉框。

       加载宋词宋诗和元曲的代码大体类似。

       通常的词云展示都是用Matplotlib的控件方法,那样的化就没法整合到Tkinter的GUI界面中了,也不方便与用户进行交互。笔者参考网上代码,采用matplotlib的FigureCanvasTkAgg canvas画布功能,把生成的云图嵌入。

         首先是声明matplotlib绘图的Figure和canvas画布对象:

curRow = 2
fig = Figure(figsize=(5, 4), dpi=100)
canvas = FigureCanvasTkAgg(fig, master=win)  # A tk.DrawingArea.
canvas.get_tk_widget().pack(side=tkinter.BOTTOM, fill=tkinter.BOTH, expand=1)

        然后在生成词云后,把词云嵌入进去:

def generateCloud(*args):
    """清除原有图表,生成新的图表"""
    global fig,canvas
    fig.clear()

    ax = fig.add_subplot(111)
    content = []
    cur_author = poetList.get()
    if workList.get() == '唐诗三百首':
        for work in tang_poetry_list:
            if cur_author == 'all' or cur_author == work.get_author():
                content.extend(work.get_content())
    elif workList.get() == '宋诗三百首':
        for work in song_poetry_list:
            if cur_author == 'all' or cur_author == work.get_author():
                content.extend(work.get_content())
    elif workList.get() == '宋词三百首':
        for work in song_poem_list:
            if cur_author == 'all' or cur_author == work.get_author():
                content.extend(work.get_content())
    elif workList.get() == '元曲三百首':
        for work in yuan_verse_list:
            if cur_author == 'all' or cur_author == work.get_author():
                content.extend(work.get_content())   
    else: #佛诗三百首
        for work in buddhist_poetry_list:
            if cur_author == 'all' or cur_author == work.get_author():
                content.extend(work.get_content())  
                
    res = jieba.lcut(" ".join(content))  # 中文分词
    text = " ".join(res)  # 用空格连接所有的词
    mask = np.array(Image.open("chinamap.png"))  # 指定词云图效果
    # 创建词云对象
    wc = WordCloud(width=800, height=600, mask=mask).generate(text)
    ax.imshow(wc) # 显示词云图
    ax.axis("off")
 
    wc.to_file("{}_{}_wordcloud.png".format(workList.get(), cur_author))  # 保存成图片
    
    canvas.draw()

重点是这两行代码:

   # 创建词云对象
    wc = WordCloud(width=800, height=600, mask=mask).generate(text)
    ax.imshow(wc) # 显示词云图

最后是canvas.draw().

要显示中文词云,还需要解决中文字体的问题。按网上的方法,可以在生成词云时,加入参数:font_path="simhei.ttf"。我这里使用的Miniconda3,加入字体路径报错,改成绝对路径还是报错。就采用了另一种方法,直接修改词云源码wordcloud.py里面的缺省字体设置:(全局搜wordcloud.py文件):

FONT_PATH = os.environ.get('FONT_PATH', os.path.join(FILE, 'DroidSansMono.ttf'))

将系统的缺省英文字体DroidSansMono.tff修改为别的中文字体即可。

我按照网上的建议先是改成simhei.ttf,乱码依旧。后来改成msyh.ttc微软雅黑字体,就好了。但是simhei.ttf这种字体在我的电脑上是正常安装了的,不知道为啥wordcloud找不着。

本文所有代码及资源文件都已上传github:GitHub - yangdanbo/PoetryCloud

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...