文章目录
- 函数封装
- UI设计
- 输出词云
热榜分析系列: CSDN热榜分析🔥 UI界面🔥 领域热榜
函数封装
词云图的绘制功能早在最开始做热榜分析的时候就已经实现了,但需要依赖matplotlib来画图,而并没有直接导出功能,而且所有代码写在脚本里,并没有封装成函数。
首先用jieba分词,并把所有长度大于2的单词输出。
import jieba
# 通过jieba
def getWords(blogs):text = ','.join([b[1] for b in blogs])words = jieba.lcut(text)w2 = [w for w in words if len(w)>1] # 取出长度大于1的词return [w for w in w2 if w not in STOP_LIST]
其中STOP_LIST是停用词列表,被做成了全局变量
STOP_LIST = ['项目', '使用', '实现', '模型', '数据', '系统', '平台', '原理', '自学', '博客', '推荐', '实践', '实战', '技术', '基于', '如何', '什么']
单词导出后,则使用WordCloud进行词云绘制。函数如下,其中to_file可以把词云图导出为图像。
from wordcloud import WordCloud
def saveCloud(words, path, width=800, height=450, font=None)if not font : font = r"C:\Windows\Fonts\simhei.ttf"cloud = WordCloud(width=width, height=height, font_path=font)cloud.generate(" ".join(words))cloud.to_file(path)
UI设计
由于词云图在保存时预留了较多的个性化选项,包括宽高之类的,所以词云绘制功能需要多加一些,故而更改setFrmHeat的布局代码如下
def setFrmHeat(self, frmHeat):# 省略。。。pack = dict(side=tk.LEFT, padx=3)ttk.Separator(frmHeat,orient=tk.VERTICAL).pack(fill=tk.Y, **pack)ttk.Button(frmHeat, width=8, text="导出词云",command = self.btnExportCloud).pack(**pack)ttk.Label(frmHeat, text=" 尺寸").pack(**pack)pSpinbox = dict(from_=100, to=2000, width=5, increment=10)self.sbCloudWidth = ttk.Spinbox(frmHeat, **pSpinbox)self.sbCloudWidth.pack(**pack)self.sbCloudWidth.set(800)ttk.Label(frmHeat, text="✖").pack(**pack)self.sbCloudHeight = ttk.Spinbox(frmHeat, **pSpinbox)self.sbCloudHeight.pack(**pack)self.sbCloudHeight.set(450)ttk.Button(frmHeat, width=8, text="设置字体",command = self.btnSetCloudFont).pack(**pack)def btnExportCloud(self):passdef btnSetCloudFont(self):self.cloudFont = askopenfilename(filetypes=[("字体文件", ".font")])
其中self.cloudFont是一个类成员,默认值是None,布局结果如下
btnExportCloud就是导出词云的用户逻辑,接下来就来实现它
输出词云
考虑到需要输入不同类型的词云,所以先创建一个成员方法,用于输出一种类型的词云,方法如下,其实就是简单地调用getWords和saveCloud函数,并给出反馈信息
def btnExportOneCloud(self, name, wsLst, path, w, h, font):words = getWords(wsLst)saveCloud(words, pJoin(path, f"{name}.png"), w, h, font)self.addLogs(f"{name}词云已输出")return words
我们至少要输出三种词云,首先是总榜的词云,然后是领域热榜的词云,最后还要把所有词云的单词作为一个整榜输出。这也就意味着需要调用三次btnExportOneCloud函数:总榜列表调用一次;领域热榜字典,需要在循环中调用一次;最后所有词汇再调用一次。
所以btnExportCloud需要设置一个存储所有单词的列表,每次词云输出后,都要将对应的词汇导入到这个列表中。最终其写法如下
def btnExportCloud(self):path = askdirectory()if path=="":self.infoCSDN.set(f"您未选择文件夹")return self.infoCSDN.set(f"词云图将存储在文件夹{path}中")allWords = []w = int(self.sbCloudWidth.get())h = int(self.sbCloudHeight.get())font = self.cloudFont# 总榜导出总榜if self.heatBlogs != []:words = self.btnExportOneCloud("总榜", self.heatBlogs, path, w, h, font)allWords.extend(words)if self.subHeats == {}:return # 如果没有领域热榜,那么总榜就是全榜,所以直接退出for k,v in self.subHeats.items():words = self.btnExportOneCloud(k, v, path, w, h, font)allWords.extend(words)saveCloud(allWords, pJoin(path, f"全榜.png"), w, h, font)self.addLogs(f"全榜词云已输出")
这个函数分为四个部分,第一部分是读取词云参数,包括存放文件夹、词云尺寸以及字体,并且创建列表allWords,用于存放所有词汇。
第二部分输出总榜词云。
第三部分循环subHeats,正式循环之前,判断一下是否为空,如果没有领域热榜,那么总榜就是全榜,所以直接退出。
最后输出全部榜单,由于已经得到了allWords,所以不必调用btnExportOneCloud,直接用外部函数saveCloud来保存词云。
最后的词云输出如下