文章目录
- 函数封装
- 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):
pass
def 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来保存词云。
最后的词云输出如下