背景
人类在数字化浪潮中面临着怎样的抉择?如何把握数字时代的机遇和挑战?科技日新月异,人类生活日益便捷,你是愕然还是亢奋?机器人越来越人性化,你是恐惧焦虑还是心生欢喜?人类是否可以始终制霸选择权中的”最后一英里”?数据可以成为财富吗?大数据、算法、区块链、人工智能、物联网……
面对越来越繁杂的日常生活,每天人都要接受大量的文字信息。伴随着信息流,错综复杂,无休无止。如何准确且快速提取出事物的本质、物质的核心,从而领悟最终含义成了一个关键和问题。一天我灵机一动,于是运用所学知识编写了一款 Python 程序以实现了目标。
简介
这是一款生成词云图的程序。给定一段文章,经过该程序的智能运算,可以自动提取出该文章内的关键词,生成仅仅由文字和颜色组成的图片。图片里文字有大有小,在不同位置表示该词语出现的频率不同。字越大表明出现频率越高,那么也就越重要。 下面是使用该程序创建生成的词云图:
特点
- 界面简洁
- 操作简便
- 使用 Python Tkinter 原生编译而成,性能优良
- 全过程个性化制定操作
- 图片丰富多彩,内容充实
使用方法和步骤
输入背景颜色
从上面的示例图片可以看出,整个词云图的背景为单一色彩,文字颜色却丰富多彩。你可以在输入框内以十六进制的格式写上你想要的颜色以生成制定颜色背景(详细信息见下文附录)。
选择是否使用遮罩图片
右侧是一个单选选项。遮罩图片的意思是:词云图将依照遮罩图片主体图形的形状大小和颜色来生成相应的文字。比如遮罩图片(除了白色背景)是一朵红色的花:
那么最终图片上的文字颜色就是红色、黄色、绿色的(花瓣、花蕊、叶片上的颜色)。这是使用了《爱莲说》的赏析评价的文章生成的。
禁用遮罩图片
这意味着文字将不会按照图片的形状来生成,也没有那上面的颜色,由程序根据背景颜色自动生成。背景黑则文字白,背景白则文字黑。
启用遮罩图片
定制性更强。图片上的主体是什么,这一串文字就沿着它边缘填满(如上图)。
- 注意:遮罩图片背景必须是白色,不能是透明的!
读取词云图片
将需要处理的文本保存至 .txt 纯文本文件里。 然后点击按钮读取。
读取遮罩图片
如果禁用了遮罩图片,则不需要点击此按钮,直接点生成。启用才要。程序支持两种图片格式:.jpg 和 .png。再次重申,.png 图片不能为透明背景!
生成
直接点击生成按钮。处理时间较长,请耐心等待。处理完后,弹窗要求保存。找到目标文件夹后保存即可。
源码
import numpy
import math
import jieba
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
import webbrowser
from tkinter import *
from tkinter import messagebox, filedialog
from PIL import Image, ImageTk
import tkinter.filedialog
string = ""
img_info = ""
img_color = ""
is_mask_on = False
def open_url_cnblogs(event):
webbrowser.open("https://www.cnblogs.com/DawnNeon")
def open_url_csdn(event):
webbrowser.open("https://blog.csdn.net/Dawn_Neon")
def about():
wd_about = Toplevel()
wd_about.resizable(False, False)
wd_about.title("生成词云图")
wd_about.geometry("450x270")
Label(wd_about, width=100, font=("黑体", 40),
text="生成词云图").pack(pady=10)
Label(wd_about, font=("Times New Roman", 15),
text="Copyright © 2020-2022 DawnNeon").pack()
Label(wd_about, font=("Times New Roman", 15),
text="Version Beta 0.2, Aug 18 2022").pack()
Label(wd_about, font=("Times New Roman", 13),
wraplength=450, text="From the bottom of my heart, \
I thank all those who gives me much help like the brightest stars \
even in the darkest time!").pack()
lb_refrences1 = Label(wd_about,
text="帮助 & 支持: https://www.cnblogs.com/DawnNeon",
fg="blue",
cursor="star",
font=("微软雅黑", 9, "underline"))
lb_refrences2 = Label(wd_about, text="https://blog.csdn.net/Dawn_Neon",
fg="blue",
cursor="star",
font=("微软雅黑", 9, "underline"))
Label(wd_about, font=("宋体", 13), text="更新内容:\n1. 增加禁用遮罩图片时设定生成的词云图片尺寸", justify="center").pack()
lb_refrences1.pack()
lb_refrences2.pack()
lb_refrences1.bind("<Button-1>", open_url_cnblogs)
lb_refrences2.bind("<Button-1>", open_url_csdn)
def get_article_content():
try:
global string
file_name = filedialog.askopenfilename(
title="请选择一个 txt 文本文档",
filetypes=(("文本文档", "*.txt"),))
with open(file_name, "r", encoding="utf-8") as f:
content = f.read()
string = " ".join(jieba.lcut(content))
except:
messagebox.showerror("警告", "文件错误")
return
def is_mask():
try:
dic = {0:False, 1:True}
global is_mask_on
is_mask_on = dic.get(var.get())
if is_mask_on:
en_width["state"] = "disabled"
en_height["state"] = "disabled"
else:
en_width["state"] = "normal"
en_height["state"] = "normal"
except:
messagebox.showerror("警告", "操作失败")
def get_image():
try:
if is_mask_on:
img_name = filedialog.askopenfilename(
title="请选择一张遮罩图片",
filetypes=(("PNG图片,不透明", "*.png"), ("JPG图片", "*.jpg")))
img = Image.open(img_name)
global img_info, img_color
img_info = numpy.array(img)
img_color = ImageColorGenerator(img_info)
else:
messagebox.showinfo("提示", "无需读取遮罩图片!")
return
except:
messagebox.showerror("警告", "读取遮罩图片出错!")
return
def create_pic():
try:
with open("all_stopwords.txt", "r", encoding="utf-8") as f_all_sw:
raw_sw = f_all_sw.readlines()
except:
messagebox.showerror("警告", "读取停用词时出错!")
return
sw = set()
for i in raw_sw:
sw.add(i.strip())
bg_color = en_bg_color.get()
messagebox.showinfo("提示", "图片生成过程中可能有卡顿或假死,请稍等片刻!\n点击确定开始生成")
if is_mask_on:
obj_pic = WordCloud(
background_color=bg_color,
repeat=True,
max_words=500,
stopwords=sw,
font_path="msyh.ttc",
color_func=img_color,
mask=img_info)
else:
pic_width = int(en_width.get())
pic_height = int(en_height.get())
obj_pic = WordCloud(
width=pic_width,
height=pic_height,
background_color=bg_color,
repeat=True,
max_words=500,
stopwords=sw,
font_path="msyh.ttc")
obj_pic.generate(string)
# 选择词云图保存路径
try:
result_path = filedialog.asksaveasfilename(
title="请选择保存路径",
filetypes=(("PNG图片", "*.png"),))
result_name = result_path.split("/")
obj_pic.to_file(result_path + ".png")
except:
messagebox.showerror("警告", "保存词云图时出错!")
return
messagebox.showinfo("提示", "词云图大功告成!")
root = Tk()
root.title("生成词云图")
fm_1 = Frame()
fm_2 = Frame()
fm_3 = Frame()
fm_4 = Frame()
fm_5 = Frame()
fm_1.pack(fill="both", expand=True)
fm_2.pack(fill="both", expand=True)
fm_3.pack(fill="both", expand=True)
fm_5.pack(fill="both", expand=True)
Label(fm_1, text="背景颜色", font=("微软雅黑", 14)).pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
en_bg_color = Entry(fm_1, font=("微软雅黑", 14))
en_bg_color.pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
var = IntVar()
Radiobutton(fm_1, text="禁用遮罩图片", variable=var, value=0, command=is_mask).pack(fill="both",
expand=True,
side="left",
padx=5,
pady=5)
Radiobutton(fm_1, text="启用遮罩图片", variable=var, value=1, command=is_mask).pack(fill="both",
expand=True,
side="left",
padx=5,
pady=5)
Label(fm_2, text="图片尺寸(长×宽)", font=("微软雅黑", 14)).pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
en_width = Entry(fm_2, font=("微软雅黑", 14), width=5)
en_width.pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
Label(fm_2, text="×", font=("微软雅黑", 14)).pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
en_height = Entry(fm_2, font=("微软雅黑", 14), width=5)
en_height.pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
Button(fm_3, text="读取词云文章", font=("微软雅黑", 16), command=get_article_content).pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
Button(fm_3, text="读取遮罩图片", font=("微软雅黑", 16), command=get_image).pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
Button(fm_5, text="生成", font=("微软雅黑", 18), command=create_pic).pack(
fill="both",
expand=True,
side="left",
padx=5,
pady=5)
menubar = Menu(root)
menubar.add_command(label="关于", command=about)
root.config(menu=menubar)
root.mainloop()
附录:十六进制颜色码对照表
英文代码 | 颜色描述 | 十六进制 |
---|---|---|
LightPink | 浅粉红 | #FFB6C1 |
Pink | 粉红 | #FFC0CB |
Crimson | 猩红 | #DC143C |
LavenderBlush | 脸红的淡紫色 | #FFF0F5 |
PaleVioletRed | 苍白的紫罗兰红色 | #DB7093 |
HotPink | 热情的粉红 | #FF69B4 |
DeepPink | 深粉色 | #FF1493 |
MediumVioletRed | 适中的紫罗兰红色 | #C71585 |
Orchid | 兰花的紫色 | #DA70D6 |
Thistle | 蓟 | #D8BFD8 |
plum | 李子 | #DDA0DD |
Violet | 紫罗兰 | #EE82EE |
Magenta | 洋红 | #FF00FF |
Fuchsia | 灯笼海棠(紫红色) | #FF00FF |
DarkMagenta | 深洋红色 | #8B008B |
Purple | 紫色 | #800080 |
MediumOrchid | 适中的兰花紫 | #BA55D3 |
DarkVoilet | 深紫罗兰色 | #9400D3 |
DarkOrchid | 深兰花紫 | #9932CC |
Indigo | 靛青 | #4B0082 |
BlueViolet | 深紫罗兰的蓝色 | #8A2BE2 |
MediumPurple | 适中的紫色 | #9370DB |
MediumSlateBlue | 适中的板岩暗蓝灰色 | #7B68EE |
SlateBlue | 板岩暗蓝灰色 | #6A5ACD |
DarkSlateBlue | 深岩暗蓝灰色 | #483D8B |
Lavender | 熏衣草花的淡紫色 | #E6E6FA |
GhostWhite | 幽灵的白色 | #F8F8FF |
Blue | 纯蓝 | #0000FF |
MediumBlue | 适中的蓝色 | #0000CD |
MidnightBlue | 午夜的蓝色 | #191970 |
DarkBlue | 深蓝色 | #00008B |
Navy | 海军蓝 | #000080 |
RoyalBlue | 皇家蓝 | #4169E1 |
CornflowerBlue | 矢车菊的蓝色 | #6495ED |
LightSteelBlue | 淡钢蓝 | #B0C4DE |
LightSlateGray | 浅石板灰 | #778899 |
SlateGray | 石板灰 | #708090 |
DoderBlue | 道奇蓝 | #1E90FF |
AliceBlue | 爱丽丝蓝 | #F0F8FF |
SteelBlue | 钢蓝 | #4682B4 |
LightSkyBlue | 淡蓝色 | #87CEFA |
SkyBlue | 天蓝色 | #87CEEB |
DeepSkyBlue | 深天蓝 | #00BFFF |
LightBLue | 淡蓝 | #ADD8E6 |
PowDerBlue | 火药蓝 | #B0E0E6 |
CadetBlue | 军校蓝 | #5F9EA0 |
Azure | 蔚蓝色 | #F0FFFF |
LightCyan | 淡青色 | #E1FFFF |
PaleTurquoise | 苍白的绿宝石 | #AFEEEE |
Cyan | 青色 | #00FFFF |
Aqua | 水绿色 | #D4F2E7 |
DarkTurquoise | 深绿宝石 | #00CED1 |
DarkSlateGray | 深石板灰 | #2F4F4F |
DarkCyan | 深青色 | #008B8B |
Teal | 水鸭色 | #008080 |
MediumTurquoise | 适中的绿宝石 | #48D1CC |
LightSeaGreen | 浅海洋绿 | #20B2AA |
Turquoise | 绿宝石 | #40E0D0 |
Auqamarin | 绿玉\碧绿色 | #7FFFAA |
MediumAquamarine | 适中的碧绿色 | #00FA9A |
MediumSpringGreen | 适中的春天的绿色 | #00FF7F |
MintCream | 薄荷奶油 | #F5FFFA |
SpringGreen | 春天的绿色 | #3CB371 |
SeaGreen | 海洋绿 | #2E8B57 |
Honeydew | 蜂蜜 | #F0FFF0 |
LightGreen | 淡绿色 | #90EE90 |
PaleGreen | 苍白的绿色 | #98FB98 |
DarkSeaGreen | 深海洋绿 | #8FBC8F |
LimeGreen | 酸橙绿 | #32CD32 |
Lime | 酸橙色 | #00FF00 |
ForestGreen | 森林绿 | #228B22 |
Green | 纯绿 | #008000 |
DarkGreen | 深绿色 | #006400 |
Chartreuse | 查特酒绿 | #7FFF00 |
LawnGreen | 草坪绿 | #7CFC00 |
GreenYellow | 绿黄色 | #ADFF2F |
OliveDrab | 橄榄土褐色 | #556B2F |
Beige | 米色(浅褐色) | #F5F5DC |
LightGoldenrodYellow | 浅秋麒麟黄 | #FAFAD2 |
Ivory | 象牙 | #FFFFF0 |
LightYellow | 浅黄色 | #FFFFE0 |
Yellow | 纯黄 | #FFFF00 |
Olive | 橄榄 | #808000 |
DarkKhaki | 深卡其布 | #BDB76B |
LemonChiffon | 柠檬薄纱 | #FFFACD |
PaleGodenrod | 灰秋麒麟 | #EEE8AA |
Khaki | 卡其布 | #F0E68C |
Gold | 金 | #FFD700 |
Cornislk | 玉米色 | #FFF8DC |
GoldEnrod | 秋麒麟 | #DAA520 |
FloralWhite | 花的白色 | #FFFAF0 |
OldLace | 老饰带 | #FDF5E6 |
Wheat | 小麦色 | #F5DEB3 |
Moccasin | 鹿皮鞋 | #FFE4B5 |
Orange | 橙色 | #FFA500 |
PapayaWhip | 番木瓜 | #FFEFD5 |
BlanchedAlmond | 漂白的杏仁 | #FFEBCD |
NavajoWhite | 纳瓦霍白 | #FFDEAD |
AntiqueWhite | 古代的白色 | #FAEBD7 |
Tan | 晒黑 | #D2B48C |
BrulyWood | 结实的树 | #DEB887 |
Bisque | (浓汤)乳脂,番茄等 | #FFE4C4 |
DarkOrange | 深橙色 | #FF8C00 |
Linen | 亚麻布 | #FAF0E6 |
Peru | 秘鲁 | #CD853F |
PeachPuff | 桃色 | #FFDAB9 |
SandyBrown | 沙棕色 | #F4A460 |
Chocolate | 巧克力 | #D2691E |
SaddleBrown | 马鞍棕色 | #8B4513 |
SeaShell | 海贝壳 | #FFF5EE |
Sienna | 黄土赭色 | #A0522D |
LightSalmon | 浅鲜肉(鲑鱼)色 | #FFA07A |
Coral | 珊瑚 | #FF7F50 |
OrangeRed | 橙红色 | #FF4500 |
DarkSalmon | 深鲜肉(鲑鱼)色 | #E9967A |
Tomato | 番茄 | #FF6347 |
MistyRose | 薄雾玫瑰 | #FFE4E1 |
Salmon | 鲜肉(鲑鱼)色 | #FA8072 |
Snow | 雪 | #FFFAFA |
LightCoral | 淡珊瑚色 | #F08080 |
RosyBrown | 玫瑰棕色 | #BC8F8F |
IndianRed | 印度红 | #CD5C5C |
Red | 纯红 | #FF0000 |
Brown | 棕色 | #A52A2A |
FireBrick | 耐火砖 | #B22222 |
DarkRed | 深红色 | #8B0000 |
Maroon | 栗色 | #800000 |
White | 纯白 | #FFFFFF |
WhiteSmoke | 白烟 | #F5F5F5 |
Gainsboro | 亮灰色 | #DCDCDC |
LightGrey | 浅灰色 | #D3D3D3 |
Silver | 银白色 | #C0C0C0 |
DarkGray | 深灰色 | #A9A9A9 |
Gray | 灰色 | #808080 |
DimGray | 暗淡的灰色 | #696969 |
Black | 纯黑 | #000000 |
参考链接 & 来源:十六进制颜色码
2022年8月18日更新 · Beta 0.2
增加禁用遮罩图片时设定生成的词云图片尺寸。
图片尺寸(长×宽)
- 当选择禁用遮罩图片时,指定最后生成出来的的词云图片尺寸。有两个输入框。前者填长,后者填宽;
- 当选择启用遮罩图片时,该输入框无效(呈灰色状,无法输入)。
写在最后
作者:DawnNeon
若要转载请标明出处:https://blog.csdn.net/Dawn_Neon/article/details/126126184