Python词云实战:jieba分词、蒙版取色与TF-IDF权重
发布时间:2026/11/6 7:06:28 锦皓数字建站

简介Python 词云完整教程 PDF 面向文本挖掘与数据可视化初学者及中级用户围绕 wordcloud 与 matplotlib 两库系统讲解从文本预处理、权重计算到词云生成、展示与保存的完整流程并给出 PyCharm、Python 3.7 及对应库版本的环境配置参考。内容以7个递进案例展开既包含最简调用也覆盖中文不分词、中文分词、蒙版形状、自定义配色以及按关键词和权重定制词云等进阶用法可服务于项目报告、数据分析、社交媒体监控与教学演示等场景。资源包共1个PDF文件大小约2.07MB单文件便于通读与按案例检索代码示例和运行结果可辅助对照练习。已有109人学习适合希望快速掌握词云制作思路并积累可视化实践的读者。1. 从一份纯文本到一张能进报告的图这套词云方案先解决什么做文本分析类课设的人常常卡在同一个地方词频统计跑完了结论也有了最后要放进报告手里却只有一张 Excel 截图或者一段控制台输出。评审要的是“扫一眼就知道这批文本在讲什么”的图不是一串数字。这套 Python 词云方案处理的正是最后这一步拿一份纯文本进去从最简的一次调用开始依次叠加中文分词、蒙版形状、蒙版取色、自定义颜色函数最后落到按关键词权重生成。七个案例层层递进每一层只增加一个变量出问题能立刻定位到是哪一层引入的。它适合正在做文本挖掘、舆情观察、课程报告的在校生也适合需要把分析结论放进汇报材料的从业者。整套流程只依赖 wordcloud、matplotlib、jieba 三个库环境是 Python 3.7 wordcloud 1.9.3 matplotlib 3.5.3换一份文本、改几个参数就能直接跑自己的数据。2. 环境与工程骨架Python 3.7 wordcloud 1.9.3 的最小可运行结构2.1 依赖清单与版本约束词云这条链路上的库不算多但每个位置都有明确分工少一个环节就出不了图。先把它们列清楚后面看代码时才知道每一行在跟谁打交道。库版本在流程里负责什么wordcloud1.9.3词汇排布、按权重决定字号、生成图像对象matplotlib3.5.3显示画布、关闭坐标轴、交互式预览jieba用当前稳定版即可中文分词以及后面案例 07 的关键词权重抽取Pillow随 wordcloud 一起装上读取蒙版图片、把像素转成数组numpy随 matplotlib 一起装上把图片转成 mask 需要的 ndarray安装命令按教程给的版本号固定下来这一步不要图省事直接pip install wordcloud。原因很简单wordcloud 在 1.x 早期版本和 1.9.x 之间对mask、background_colorNone的处理细节有差异而网上能搜到的绝大部分报错帖写的又不是同一个版本版本一漂你照着帖子改反而越改越乱。# 三个核心库版本按教程固定避免接口行为漂移 pip install wordcloud1.9.3 pip install matplotlib3.5.3 pip install jieba # 装完自检确认版本和教程一致再往下走 python -c import wordcloud, matplotlib; print(wordcloud.__version__, matplotlib.__version__)这里有一个大多数人都会遇到的麻烦wordcloud 带 C 扩展在 Windows 上如果没匹配到现成的 wheel 包pip 会退回去做源码编译然后报一串Microsoft Visual C 14.0 is required。遇到这种情况不要装编译器先确认 Python 是 3.7 的 64 位版本再升级 pip 让它能拉到对应的 wheel实在拉不到就退到 32 位 Python 或者换一个 prebuilt wheel 装。这一步解决不了后面七个案例一行都跑不起来。2.2 目录结构与七个案例的分层七个案例如果全塞进一个.py文件变量名会互相污染改一个地方要重新确认另外六段还对不对调试体验很差。我一般按“一个案例一个入口文件”来摆把读文本、分词、字体路径这三件重复出现的活抽到common.py里。wordcloud_demo/ ├── data/ │ ├── sample.txt # 无分词场景的纯文本 │ └── book.txt # 中文长文本utf-8 编码 ├── fonts/ │ └── cn_font.ttf # 中文字体ttf 或 otf 都可以 ├── masks/ │ ├── black_mask.png # 纯形状蒙版黑白二值 │ └── color_mask.png # 带颜色的蒙版用于取色 ├── outputs/ # 生成的 png 统一落这里 ├── common.py # 读文本、分词、字体路径 ├── case01_minimal.py ├── case02_cn_nocut.py ├── case03_cn_cut.py ├── case04_mask.py ├── case05_mask_color.py ├── case06_color_func.py └── case07_tfidf.py这么分层的好处是每个案例只改一件事案例 02 只换字体和画布参数案例 03 只插入分词案例 04 只加 mask。跑出来效果不对时把上一个案例再跑一次两边一对比问题范围立刻被限制在新增的那几行里。这也是整套方案能当“模板”复用的关键——你以后接了新数据只需要动data/和common.py七个入口文件基本不用改。2.3 文本入口与字体路径的统一约定词云代码里最常见的柔性问题其实是路径和编码脚本在 PyCharm 里点运行能出图换到命令行python case03_cn_cut.py就报FileNotFoundError因为相对路径是跟着当前工作目录走的。把路径统一在common.py里基于脚本自身位置拼出来这一类问题就一次性消掉了。# common.py import os import jieba # 以 common.py 所在目录为基准避免工作目录不同导致的找不到文件 BASE os.path.dirname(os.path.abspath(__file__)) def read_text(rel_path, encodingutf-8): 按 utf-8 读文本遇到 gbk 文本时把 encoding 换成 gbk 再调一次 path os.path.join(BASE, rel_path) with open(path, r, encodingencoding) as f: return f.read() def cut(text, stop_wordsNone): jieba 精确模式分词过滤单字和停用词后拼回空格分隔的字符串 tokens [] for w in jieba.cut(text): w w.strip() if len(w) 2: # 单字多数是虚词先丢掉 continue if stop_words and w in stop_words: continue tokens.append(w) return .join(tokens) # 字体路径同样基于脚本位置Windows 可换成 C:/Windows/Fonts/simhei.ttf 的绝对路径 FONT os.path.join(BASE, fonts, cn_font.ttf)read_text里显式写encodingutf-8不是可选动作。中文文本在 Windows 上默认按 GBK 解码遇到 utf-8 内容会抛UnicodeDecodeError而报错行号往往落在f.read()上看起来像文件坏了其实只是编码没对上。cut里过滤掉长度为 1 的词是因为中文分词结果里“的、了、是、在”这类单字占比很高不滤掉它们会占满画布上最好的位置。停用词表我一般单独放一个stopwords.txt按行读取成 set 传进来官方库自带的停用词只对英文有效中文这块必须自己补。提示字体文件不要用系统里随便找一个的 ttf优先选字重完整的中文字体。缺字的字体不会报错只会在画布上留下一排方块排查起来很绕。3. 七个案例的递进设计从三行调用到权重驱动3.1 案例 01-02先跑通默认调用再解决中文直出案例 01 的作用不是出效果图而是验证环境。它把所有可调项都用默认值只要这张图能出来就说明 wordcloud 和 matplotlib 装对了、文本能读到、画布能渲染后面所有问题都可以排除掉环境因素。# case01_minimal.py # -*- coding: utf-8 -*- from wordcloud import WordCloud import matplotlib.pyplot as plt from common import read_text # 读入文本默认英文/无空格分隔场景 text read_text(data/sample.txt) # 全部用默认参数画布 400x200白色背景按空格切词 wc WordCloud().generate(text) # 显示bilinear 让缩放更平滑axis off 去掉坐标轴 plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() # 落盘后续所有案例都统一输出到 outputs/ wc.to_file(outputs/case01.png)generate(text)内部做了三件事按空格切词、统计词频、按词频分配字号并把词排进画布。默认画布只有 400x200词一多就会显得挤interpolationbilinear解决的是显示时的插值锯齿跟导出图片的清晰度无关这一点很多人会混淆。案例 02 把中文文本直接丢进去只增加三个参数font_path指定中文字体、width/height把画布放大到 800x600、modeRGBA加background_colorNone得到透明背景。# case02_cn_nocut.py from wordcloud import WordCloud import matplotlib.pyplot as plt from common import read_text, FONT text read_text(data/book.txt) wc WordCloud( font_pathFONT, # 中文字体缺了它整张图都是方块 width800, height600, # 画布放大避免词挤成一团 modeRGBA, # 带透明通道 background_colorNone, # 背景透明方便贴到 PPT 或海报上 ).generate(text)这个案例故意不做分词是为了让你亲眼看到不分词的后果整段中文因为中间没有空格会被 WordCloud 当成一个超长“单词”画布上只出现几个巨大的词块或者干脆一片空白。这个“错误示范”很有价值它把分词的必需性从一句结论变成了你亲眼见过的现象后面答辩被问到“为什么要用 jieba”时这就是最好的回答素材。3.2 案例 03jieba 分词接入把长句拆成可统计的词中文没有空格分隔WordCloud 拿到的必须是用空格隔开的词序列中间这一层就由 jieba 补上。改动只有一行但它是整条链路的分水岭。# case03_cn_cut.py from wordcloud import WordCloud import matplotlib.pyplot as plt import jieba from common import read_text, FONT text read_text(data/book.txt) # 精确模式切词再用空格拼回去交给 WordCloud text .join(jieba.cut(text)) print(text[:100]) # 打印前 100 字符肉眼确认切得对不对 wc WordCloud( font_pathFONT, width800, height600, modeRGBA, background_colorNone, ).generate(text) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(outputs/case03.png)jieba.cut(text)返回的是生成器不是列表所以必须用 .join()消费掉再传给 WordCloud直接传生成器进去会触发类型错误。jieba.cut默认是精确模式另有全模式和搜索引擎模式全模式把句子里所有可能成词的部分都切出来速度快但歧义多词云上会冒出大量碎片词搜索引擎模式在精确模式基础上对长词再切一次召回率更高。词云场景我一般只用精确模式因为画布空间有限宁可少几个词也不要一堆切碎的半截词把版面撑乱。打印前 100 个字符这一步别省。分词切错比如人名被拆成两个字、专业术语被拦腰截断在图上不一定看得出来但在文本层面一眼就能发现。真遇到专有名词被切碎jieba.load_userdict(dict.txt)加载一份自定义词典一行一个词效果立竿见影。3.3 案例 04-05蒙版形状与蒙版取色把方图变成图形默认词云永远是矩形放进设计稿里很突兀。案例 04 用 mask 把词的排布限制在一个形状内案例 05 再让词的颜色从一张彩色图上取两步合起来就是“形状 配色”都跟着素材走。# case04_mask.py from wordcloud import WordCloud from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba from common import read_text, FONT text .join(jieba.cut(read_text(data/book.txt))) # 蒙版必须是 ndarray形状决定词的落点分布 mask np.array(Image.open(masks/black_mask.png)) wc WordCloud( maskmask, # 传了 mask 后width/height 会被忽略 font_pathFONT, modeRGBA, background_colorNone, ).generate(text) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(outputs/case04.png)关键点在 mask 的像素语义WordCloud 把 mask 里接近白色255的区域当作不绘制区非白区域才是词的落点。所以做蒙版图时想要出词的地方涂黑、不要的地方留白这跟多数人凭直觉画的“白色是主体”正好相反也是后面避坑章节要重点讲的一条。另外一旦传了mask代码里再写width800是不会生效的画布尺寸直接由蒙版图片的像素尺寸决定蒙版太大比如 4000px 宽会让排布慢到几十秒。案例 05 在案例 04 基础上多一个取色步骤ImageColorGenerator读取蒙版的颜色分布recolor把词的颜色替换成对应位置的颜色。# case05_mask_color.py from wordcloud import WordCloud, ImageColorGenerator from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba from common import read_text, FONT text .join(jieba.cut(read_text(data/book.txt))) mask np.array(Image.open(masks/color_mask.png)) wc WordCloud(maskmask, font_pathFONT, modeRGBA, background_colorNone).generate(text) # 从彩色蒙版里提取颜色再重新着色顺序不能反必须在 generate 之后 image_colors ImageColorGenerator(mask) wc.recolor(color_funcimage_colors) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.show() wc.to_file(outputs/case05.png)recolor的调用时机是硬约束它改的是已经排好版的词的字体颜色如果放在generate之前词还没生成改了也是白改。这一条在排查颜色失效时排第一位。3.4 案例 06-07自定义颜色函数与权重驱动案例 06 把取色逻辑从“跟着图片走”换成“自己算”。color_func接收一个回调参数里有词、字号、位置、方向等返回一个颜色字符串HSL 写法在控制亮度上比 RGB 更直观。# case06_color_func.py import random from wordcloud import WordCloud from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba from common import read_text, FONT text .join(jieba.cut(read_text(data/book.txt))) mask np.array(Image.open(masks/color_mask.png)) def random_color(word, font_size, position, orientation, font_path, random_state): 固定饱和度与亮度区间只让色相随机整张图不会花掉 return hsl(0, %d%%, %d%%) % ( random.randint(60, 80), # 饱和度 60%~80% random.randint(60, 80), # 亮度 60%~80% ) wc WordCloud( color_funcrandom_color, maskmask, font_pathFONT, modeRGBA, background_colorNone, ).generate(text) wc.to_file(outputs/case06.png)这个函数的签名是 WordCloud 规定的六个参数顺序不能改但你不一定全用。案例里色相固定为 0红系只让饱和度和亮度抖动得到的是同一色系的深浅变化想换色系就把第一个 0 改成 200蓝系或 120绿系。如果三个通道全随机图会变得像打翻的调色盘正式报告里不建议这么做。案例 07 是全篇的收口不再按词频定字号而是先用 TF-IDF 抽出关键词和权重再把字典直接喂给词云。# case07_tfidf.py from wordcloud import WordCloud, ImageColorGenerator from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba.analyse from common import read_text, FONT text read_text(data/book.txt) # topK 控制取前多少个词withWeight 让返回值带上权重 freq jieba.analyse.extract_tags(text, topK200, withWeightTrue) print(freq[:20]) # 先看前 20 个词合不合理 freq {i[0]: i[1] for i in freq} # 转成 {词: 权重} 字典 mask np.array(Image.open(masks/color_mask.png)) wc WordCloud( maskmask, font_pathFONT, modeRGBA, background_colorNone, ).generate_from_frequencies(freq) # 注意这里不用 generate image_colors ImageColorGenerator(mask) wc.recolor(color_funcimage_colors) wc.to_file(outputs/case07.png)这里换成了generate_from_frequencies它接收的是字典而不是原始文本意味着分词、去停用词、算权重全在外部完成WordCloud 只负责排版。topK200是个经验值太少图会稀疏太多小词挤在一起看不清200 上下通常能兼顾信息量和观感。extract_tags默认用 TF-IDF词在本文档里出现得多、在整个语料里出现得少权重就高比单纯数词频更能反映主题词。4. 关键参数与数据流WordCloud 对象内部到底发生了什么4.1 画布参数width、height、mode、background_color 怎么配这几个参数经常被当成“随便填填”实际上它们互相牵制。传了mask之后width/height失效modeRGBA只有在background_colorNone时才有意义两者要一起写才能拿到透明背景如果只写background_colorNone但 mode 还是默认的RGB导出的图背景会是黑的。参数默认值作用常见改法width / height400 / 200无 mask 时的画布像素尺寸800x600兼顾清晰度和排布速度maskNone词的可绘制区域传 ndarray尺寸别超过 2000pxmodeRGB输出色彩模式要透明背景时改 RGBAbackground_colorblack背景色与 modeRGBA 搭配时写 Nonefont_pathNone字体文件路径中文必填指向 ttf/otfmax_words200最多显示多少个词长文本可提到 300~500stopwordsNone要排除的词集合中文需自备停用词表max_words值得单独说一句。它限制的是进入排版的词的种类数不是出现次数。文本很长时把max_words从 200 提到 500图会明显变密但排布耗时也会上去如果只是想让人看清主题200 完全够用堆得太满反而没人愿意看。4.2 generate 与 generate_from_frequencies 的分工这两个方法是最容易被混用的一对。generate(text)接收一段用空格分好词的字符串内部自己统计词频generate_from_frequencies(dict)接收一个现成的{词: 权重}字典跳过分词和统计。# 两条路径的输入形态完全不同混用会直接报错 wc.generate(词1 词2 词3) # 输入空格分隔的字符串 wc.generate_from_frequencies({词1: 0.8, 词2: 0.3}) # 输入字典选择依据很简单数据源已经做过分词、或者权重来自 TF-IDF 这类外部算法就用generate_from_frequencies只是想把一段文本快速可视化就用generate。前者的可控性明显更强——你可以手动往字典里加词、调权重、剔除不想出现的词而generate里的停用词过滤只能靠stopwords参数粒度粗得多。做正式交付时我更倾向后者因为图上的每一个词都是自己确认过的。4.3 颜色链路mask 取色、color_func、recolor 三者的执行顺序颜色这条链上有三个角色顺序错了就出不来效果。正确的执行次序是先generate或generate_from_frequencies把词排好再决定颜色最后to_file落盘。wc.generate(text) # 第一步排词 image_colors ImageColorGenerator(mask) # 第二步准备取色器 wc.recolor(color_funcimage_colors) # 第三步着色 wc.to_file(outputs/final.png) # 第四步落盘ImageColorGenerator取的是蒙版对应像素位置的 RGB 值所以它要求蒙版必须是彩色的三通道图。如果蒙版是一张灰度图mode 为L取出来全是灰阶效果会非常寡淡如果蒙版带 alpha 通道np.array出来是四通道部分版本的 wordcloud 会直接抛形状异常。稳妥做法是读进来后统一Image.open(...).convert(RGB)再转数组。color_func和recolor是同一件事的两种写法构造时传color_func等价于生成后调recolor(color_func...)。前者写起来更紧凑后者在需要“先生成再决定配色”的场景里更灵活我一般用后者因为改配色时不用重跑排布。4.4 输出落盘to_file、尺寸与清晰度的关系wc.to_file()直接按对象内部的画布尺寸出图没有额外的 DPI 参数可调。想要更清晰的成品图只有两条路把width/height调大或者把蒙版图本身做大。这不是玄学是 wordcloud 的输出机制决定的——它输出的是像素图画布多大图就多大。# 想要 2 倍清晰度把画布和蒙版一起放大字体同步变细 wc WordCloud(maskmask, font_pathFONT, width1600, height1200, modeRGBA, background_colorNone, max_font_size200) wc.generate(text) wc.to_file(outputs/hd.png) # 尺寸随之变成 1600x1200 左右放大画布后要同步调max_font_size否则最大的词会顶满画布边缘被裁掉一部分。outputs/目录记得先在脚本里建好to_file不会自动创建父目录路径不存在时报的是FileNotFoundError看起来像 wordcloud 的问题其实是路径问题。5. 避坑与排查中文乱码、蒙版全黑、颜色失效的处理顺序5.1 中文全是方块或者整段文本糊成一坨现象图上确实有词但每个字都是空心方块或者只有寥寥几个巨大到看不清的词块。原因前者是font_path没生效——要么路径写错但没报错部分环境下会静默回退到默认字体要么字体文件本身不含中文。后者是中文没做分词整段话被当成一个“词”字号被撑到极大。解决先在代码里print(os.path.exists(FONT))确认字体文件真的在再print(text[:100])确认分词输出里带空格。两条都过了还出方块换一个确定含中文字形的 ttf 再试。中文场景下core的两步字体 分词缺一不可只补其中一步是没用的。5.2 蒙版出来一片空白或者背景全是黑的现象传了 mask 之后图上要么只剩零星几个词要么整个背景被填成黑色。原因一是 mask 的像素语义反了WordCloud 把接近白色的区域当作不可绘制区很多人凭直觉把主体画成白色结果主体位置一个词都没有。二是background_colorNone和mode没配套默认RGB模式下给None会得到黑底。解决把蒙版重新导出主体涂成纯黑或深色背景纯白存成不带 alpha 的 PNG。背景透明则固定写成modeRGBA, background_colorNone这两行一起。判断蒙版有没有问题最快的方式是plt.imshow(mask)先把蒙版本身显示出来看一眼别靠猜。5.3 取色完全没效果词还是单色现象调了ImageColorGenerator但图上的词颜色和蒙版对不上或者干脆全是同一种颜色。原因八成是recolor写在了generate之前剩下两成是蒙版是灰度图或四通道图取不到有效的 RGB 值。解决把顺序固定成“先生成、再 recolor、最后 to_file”蒙版读入时统一.convert(RGB)。另外ImageColorGenerator的取色是基于词的落点位置去采蒙版对应像素蒙版尺寸和画布差距太大时颜色会很集中把蒙版裁到和预期画布接近的比例效果会自然很多。5.4 词云里全是“的、了、是”关键词被挤没了现象图很大、词很多但最显眼的都是虚词真正想突出的名词反而很小。原因中文分词后高频虚词天然占据词频榜首stopwords参数默认只对英文有效中文停用词不会自动过滤。解决自备一份停用词表按行读取成 set在分词阶段和stopwords参数里各过一遍。更彻底的做法是走案例 07 的 TF-IDF 路线虚词虽然词频高但在文档间的区分度低权重自然被压下去这一步比手工剔除停用词更稳。5.5 脚本跑了几分钟还不出图现象命令行卡住不动CPU 占满内存缓慢上涨。原因蒙版尺寸太大比如 4000x3000或者max_words设到了上千排布算法要在有限区域内为每个词找不重叠的位置词越多、空间越大耗时增长非常快。解决蒙版宽度控制在 2000px 以内max_words控制在 200~500。真要出高清大图先用小尺寸参数调好效果确认无误后再放大跑一次别在小尺寸上反复试错的同时还扛着大画布的耗时。5.6 一份从上到下的排查顺序出问题时不要同时改三处按下面的顺序单点推进每次只改一个变量先跑案例 01确认环境和库版本没问题换成中文文本确认字体路径生效看是否出方块加分词打印前 100 字符肉眼检查切词质量加 mask先imshow(mask)看蒙版本身对不对加取色确认recolor在generate之后最后调max_words和画布尺寸优化观感。这个顺序的价值在于任何一步出错问题一定出在刚加的那一步不会跟前面的环节混在一起。血泪经验是多数人出问题后的第一反应是同时改字体、改分词、改蒙版改完发现好了但不知道为什么好下次遇到同类问题还是不会。6. 验收与答辩用一张对照表证明词云不是随手跑的词云这类可视化最容易在答辩现场被问倒的一句话是“这张图好看但它说明了什么”如果答不上来前面所有的参数调试都会被判定成“调包”。我在交这类作业前会强制自己走一遍下面这张对照表六个检查项全部能回答才允许自己导出最终图。检查项合格标准现场怎么答分词质量抽前 20 个词没有明显被切断的专名展示自定义词典或cut的过滤逻辑停用词图上找不到“的、了、是”这类虚词说明停用词表来源和过滤位置权重口径字号大小有明确依据词频或 TF-IDF指出用的是generate还是generate_from_frequencies蒙版语义主体区域有色背景干净现场imshow(mask)展示原始蒙版配色依据颜色来自蒙版取色或自定义函数不是随机打开color_func或ImageColorGenerator那段可复现性换机器、换目录能跑出同一张图路径基于脚本位置字体随项目走这六项里最容易被忽略的是最后一项。评审老师如果当场让你换一个目录跑一遍路径写死成绝对路径的脚本会立刻露馅而这一条恰恰是“能不能当模板复用”的分水岭。我的习惯是把data/、fonts/、masks/三个目录跟代码一起打包common.py里所有路径都基于os.path.dirname(os.path.abspath(__file__))拼出来交付时整个目录拷走就能跑。另一个高频追问是“为什么不用现成的在线词云工具”。这个问题的答案不在工具本身而在可控性在线工具拿不到分词这一层也没法按 TF-IDF 权重出图做舆情或报告时你想剔除某几个词、想突出某几个词它做不到。案例 07 的字典输入方式才是能写进方案的形态——权重从哪来、词表怎么定全在代码里每一步都能被追问、被复现。答辩现场还有一个小技巧不要只展示最终那张图把案例 01 到 07 的七张图并排放在一页 PPT 上从“最简调用”讲到“权重驱动”每一张对应一个新变量。这比讲十分钟原理更有说服力因为它直接证明了整个过程是可控的、每一步都有据可查。从那以后我每次交这类可视化作业都强制自己先把这七张图按顺序跑一遍再动手写报告因为图上任何一个不自然的细节都会在答辩时变成第一个被问到的问题。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。