python:wordcloud
pip install wordcloud pip install jieba pip install palettable pip install numpy pip install pillow pip install cairosvg pip install fontawesome pip install requests pip install pandas
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author : geovindu,Geovin Du 涂聚文.
# IDE : PyCharm 2024.3.6 python 3.11
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/7/28 22:10
# User : geovindu
# Product : PyCharm
# Project : Pysimple
# File : stylecloud_full.py
import os
import re
import random
import numpy as np
import jieba
import pandas as pd
from io import BytesIO
from PIL import Image
from cairosvg import svg2png
from wordcloud import WordCloud
from palettable import palette as palettable_palette
from fa6_icons import svgs
DEFAULT_FONT_PATH = None
# ===================== FontAwesome 图标处理 =====================
def _get_fa_svg(icon_name: str) -> str:
parts = icon_name.strip().split()
if len(parts) != 2:
raise ValueError('icon_name格式示例: "fas fa-heart"')
style, name = parts
style_map = {"fas": "solid", "far": "regular", "fab": "brands"}
if style not in style_map:
raise ValueError(f"不支持的样式: {style}")
style_name = style_map[style]
name = name.replace("fa-", "").replace("-", "_")
try:
svg_data = str(getattr(svgs, name).get(style_name))
if not svg_data:
raise ValueError(f"图标 {icon_name} 不存在")
return svg_data
except Exception as e:
raise RuntimeError(f"图标 {icon_name} 获取失败,请检查名称") from e
def _fa_icon_to_mask(icon_name: str, size: int = 512) -> np.ndarray:
svg_text = _get_fa_svg(icon_name)
svg_text = re.sub(r'width="\d+"', f'width="{size}"', svg_text)
svg_text = re.sub(r'height="\d+"', f'height="{size}"', svg_text)
png_bytes = svg2png(bytestring=svg_text.encode(), output_width=size, output_height=size)
img = Image.open(BytesIO(png_bytes)).convert("L")
arr = np.array(img)
mask = np.where(arr > 128, 255, 0).astype(np.uint8)
return mask
# ===================== 停用词 & 脏数据清理 =====================
def _load_stopwords(filepath: str = None) -> set:
stopwords = set()
if filepath and os.path.exists(filepath):
with open(filepath, "r", encoding="utf-8") as f:
for line in f:
w = line.strip()
if w:
stopwords.add(w)
return stopwords
def _is_useless_single_char(word: str) -> bool:
"""自动清理无意义单字、标点、数字"""
if len(word) != 1:
return False
# 单字黑名单:标点、数字、常见无意义单字
useless_chars = r",。!?;:""''()【】{}、·~`!@#$%^&*()_+-=|\/<>0123456789"
return word in useless_chars
def _filter_stopwords(word_list: list, stopwords: set) -> list:
result = []
for w in word_list:
w = w.strip()
if not w:
continue
if w in stopwords:
continue
if _is_useless_single_char(w):
continue
result.append(w)
return result
# ===================== CSV词频读取接口 新增 =====================
def load_wordfreq_from_csv(csv_path: str, word_col="word", freq_col="freq") -> dict:
"""
读取csv词频文件
:param csv_path: csv路径
:param word_col: 词汇列名
:param freq_col: 频次列名
:return: {词汇:频次}
"""
df = pd.read_csv(csv_path, encoding="utf-8")
df = df.dropna(subset=[word_col, freq_col])
word_freq = {}
for _, row in df.iterrows():
word = str(row[word_col]).strip()
freq = int(row[freq_col])
if not _is_useless_single_char(word):
word_freq[word] = freq
return word_freq
# ===================== 配色函数 =====================
def _get_palette_color_func(palette_name: str, random_state):
import palettable
parts = palette_name.split('.')
obj = palettable
for part in parts:
obj = getattr(obj, part)
colors_rgb = obj.colors
def color_func(word, font_size, position, orientation, random_state=random_state, **kwargs):
idx = random_state.randint(len(colors_rgb))
r, g, b = colors_rgb[idx]
return f"rgb({r},{g},{b})"
return color_func
# ===================== 文本预处理 =====================
def _process_text(
text: str = None,
text_path: str = None,
word_freq: dict = None,
csv_path: str = None,
stopwords: set = None,
is_chinese: bool = True
) -> str | dict:
# 优先读取CSV词频
if csv_path is not None:
word_freq = load_wordfreq_from_csv(csv_path)
if stopwords:
word_freq = {k: v for k, v in word_freq.items() if k not in stopwords}
return word_freq
if word_freq is not None:
if stopwords:
word_freq = {k: v for k, v in word_freq.items() if k not in stopwords}
return word_freq
if text_path and os.path.exists(text_path):
with open(text_path, "r", encoding="utf-8") as f:
raw = f.read()
elif text:
raw = text
else:
raise ValueError("text / text_path / word_freq / csv_path 必须传入其一")
if is_chinese:
words = jieba.lcut(raw)
else:
words = raw.split()
if stopwords:
words = _filter_stopwords(words, stopwords)
return " ".join(words)
# ===================== 核心API gen_stylecloud =====================
def gen_stylecloud(
text: str = None,
text_path: str = None,
word_freq: dict = None,
csv_path: str = None, # 新增:csv词频文件
icon_name: str = None,
mask_img: np.ndarray = None,
palette: str = None,
background_color: str = "white",
transparent_bg: bool = False, # 新增:开启透明背景PNG
font_path: str = DEFAULT_FONT_PATH,
output_name: str = "stylecloud.png",
size: tuple = (512, 512),
max_font_size: int = 200,
scale: float = 2,
prefer_horizontal: float = 0.7,
random_state: int = 42,
contour_width: float = 0,
contour_color: str = "#333333",
is_chinese: bool = True,
stopwords_path: str = None,
):
rng = np.random.RandomState(random_state)
stopwords = _load_stopwords(stopwords_path) if stopwords_path else None
mask = mask_img
if mask is None and icon_name is not None:
mask = _fa_icon_to_mask(icon_name, size=size[0])
processed_data = _process_text(
text=text,
text_path=text_path,
word_freq=word_freq,
csv_path=csv_path,
stopwords=stopwords,
is_chinese=is_chinese
)
# 透明背景时强制背景为None
bg_color = None if transparent_bg else background_color
wc = WordCloud(
width=size[0],
height=size[1],
font_path=font_path,
background_color=bg_color,
mask=mask,
max_font_size=max_font_size,
scale=scale,
prefer_horizontal=prefer_horizontal,
contour_width=contour_width,
contour_color=contour_color,
random_state=rng
)
if isinstance(processed_data, dict):
wc.generate_from_frequencies(processed_data)
else:
wc.generate(processed_data)
if palette is not None:
color_func = _get_palette_color_func(palette, rng)
wc.recolor(color_func=color_func, random_state=rng)
# 保存
wc.to_file(output_name)
print(f"✅ 生成完成: {output_name}")
return wc
# =====================【批量生成脚本】主入口 =====================
if __name__ == "__main__":
# ========= 配置区域 =========
FONT = r"C:\Windows\Fonts\STXIHEI.TTF"
OUTPUT_DIR = "./batch_output"
os.makedirs(OUTPUT_DIR, exist_ok=True)
test_text = """
人工智能 大模型 Python 数据分析 词云 机器学习
深度学习 NLP 计算机视觉 向量数据库 Agent RAG
云计算 大数据 算法 开发 编程 架构
"""
# 批量循环配置
# 1. 多种FontAwesome图标
icon_list = [
"fas fa-heart",
"fas fa-code",
"fas fa-star",
"fas fa-globe",
"fas fa-lightbulb"
]
# 2. 多种配色方案
palette_list = [
"cartocolors.diverging.TealRose_7",
"colorbrewer.qualitative.Set2_8",
"colorbrewer.qualitative.Dark2_8",
"matplotlib.Viridis_10"
]
# 批量循环生成
idx = 1
for icon in icon_list:
for palette in palette_list:
out_file = os.path.join(OUTPUT_DIR, f"cloud_{idx}_{icon.split()[-1]}_{palette.split('.')[-1]}.png")
gen_stylecloud(
text=test_text,
font_path=FONT,
icon_name=icon,
palette=palette,
background_color="black",
transparent_bg=False,
output_name=out_file,
is_chinese=True,
prefer_horizontal=0.6
)
idx += 1
# ========= 独立测试示例 =========
# 示例1:CSV词频文件读取
# gen_stylecloud(
# csv_path="word_freq.csv",
# font_path=FONT,
# icon_name="fas fa-star",
# transparent_bg=True,
# output_name="transparent_cloud.png"
# )
# 示例2:透明背景PNG
# gen_stylecloud(
# text=test_text,
# font_path=FONT,
# icon_name="fas fa-heart",
# transparent_bg=True,
# palette="colorbrewer.qualitative.Set2_8",
# output_name="transparent_heart.png"
# )
输出:

# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author : geovindu,Geovin Du 涂聚文.
# IDE : PyCharm 2024.3.6 python 3.11
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/7/28 23:19
# User : geovindu
# Product : PyCharm
# Project : Pysimple
# File : wordcloudchinesemask.py
from os import path
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import os
import jieba # 新增:中文分词库
from wordcloud import WordCloud, STOPWORDS
from matplotlib import font_manager
def list_all_fonts():
font_dir = r"C:\Windows\Fonts"
ext = (".ttf", ".ttc")
for filename in os.listdir(font_dir):
if filename.lower().endswith(ext):
full_path = os.path.join(font_dir, filename)
print(f"{filename:<20} {full_path}")
# list_all_fonts()
# get data directory
d = path.dirname(__file__) if "__file__" in locals() else os.getcwd()
# ========== 1.读取中文文本 ==========
# 把 alice.txt 替换成你的中文文本文件
text_raw = open(path.join(d, 'alice2.txt'), encoding="utf-8").read()
# ========== 2.中文分词,拼接空格(wordcloud要求词语用空格隔开) ==========
word_list = jieba.lcut(text_raw)
text = " ".join(word_list)
# ========== 3.蒙版图片不变(依然可以使用alice_mask.png) ==========
alice_mask = np.array(Image.open(path.join(d, "alice_mask.png")))
# 停用词,中英文都可以加
stopwords = set(STOPWORDS)
stopwords.update(["工作", "就是", "个人", "没有", "村民委员会", "said"])
# ========== 4.关键:增加 font_path 指定中文字体 ==========
# Windows 黑体:r"C:\Windows\Fonts\simhei.ttf"
# Windows 宋体:r"C:\Windows\Fonts\simsun.ttc"
# Mac:"/System/Library/Fonts/PingFang.ttc"
# Linux:"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
wc = WordCloud(
background_color="white",
max_words=2000,
mask=alice_mask,
stopwords=stopwords,
contour_width=3,
contour_color='steelblue',
font_path=r"C:\Users\geovindu\AppData\Local\Microsoft\Windows\Fonts\方正小篆体.ttf" # 必须配置中文路径! 方 STXIHEI.TTF FZSTK FZYTK
)
# generate word cloud
wc.generate(text)
# store to file
wc.to_file(path.join(d, "chinese_wordcloud2.png"))
# show
plt.imshow(wc, interpolation='bilinear')
plt.axis("off")
plt.figure()
plt.imshow(alice_mask, cmap=plt.cm.gray, interpolation='bilinear')
plt.axis("off")
plt.show()

哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号