整合Tkinter GUI界面的古诗词词云生成

news/2024/11/18 4:28:49/

         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


http://www.ppmy.cn/news/7604.html

相关文章

为远程MySQL数据库配置固定的公网TCP地址【内网穿透】

在上篇文章中, 我们成功实现了在公网环境下远程连接内网MySQL数据库。但由于使用的免费的cpolar内网穿透,其所生成的公网地址为随机临时地址,24小时内会发生变化,对于需要长期远程访问的用户来讲非常不方便。因此,本篇…

Qt+C++ TCP发送接收信息客户端与服务端窗体

程序示例精选 QtC TCP发送接收信息客户端与服务端窗体 如需安装运行环境或远程调试&#xff0c;见文章底部微信名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<QtC TCP发送接收信息客户端与服务端窗体>>编写代码&#xff0c;代码整洁&am…

java比较器

一、说明: Java中的对象&#xff0c;正常情况下&#xff0c;只能进行比较: 或 ! 。不能使用 >或 如何实现? 使用两个接口中的任何一个: Comparable 或 Comparator 二、Comparable的使用(自然排序) 1.Comparable接口的使用举例: 1.像string、包装类等实现了Comparable接口…

无信息变量消除法研究及实现(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 波长变量筛选的方法主要有相关系数法&#xff0c;逐步回归法&#xff0c;无信息变量消除法(UVE)&#xff0c;遗传算法(genetic …

点云 3D 目标检测 - SECOND(Sensors 2018)

点云 3D 目标检测 - SECOND&#xff08;Sensors 2018&#xff09;摘要1. 引言2. 相关工作2.1 基于前视图和图像的方法2.2 基于鸟瞰图的方法2.3 基于3D的方法2.4 基于融合的方法3. SECOND检测器3.1 网络架构3.1.1 点云分组3.1.2 Voxelwise特征提取器3.1.3 稀疏卷积中间提取器3.1…

科创板智能家居第一股,萤石网络昨日上市

2022年12月28日&#xff0c;杭州萤石网络股份有限公司(以下简称“萤石网络”)成功登陆上海证券交易所科创板&#xff0c;证券代码为688475。值得一提的是&#xff0c;萤石网络是登陆科创板的第500家企业。 在上市仪式上&#xff0c;萤石网络董事长、总经理蒋海青表示&#xff0…

Linux信号:signal函数、pause函数、alarm函数

一、信号 1.什么是信号&#xff1f; 系统为了响应某些状况而产生的事件。进程收到信号后采取相应的动作。 2.哪些情况下会产生信号&#xff1f; ①键盘事件&#xff0c;如&#xff1a;ctl c 、ctl \ ②访问非法内存 ③硬件出现故障 ④用户态到内核态的切换 3.如何查看信号&…

【SpringMVC】SpringMVC整合Mybatis

1.整合思路 第一步&#xff1a;整合dao层 mybatis和spring整合&#xff0c;通过spring管理mapper接口使用mapper的扫描自动扫描mapper接口在spring中进行注册 第二步&#xff1a;整合service层 通过spring管理service接口使用配置方式将service接口配置在spring配置文件中实现…