恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

三国人物关系词频分析词云图:从文本到洞察的完整落地路径

  • 首页
  • 资讯中心
  • /
  • 三国人物关系词频分析词云图:从文本到洞察的完整落地路径

相关资讯

word2vec+SVM中文短文本情感分析实战:从预处理到调参 2026/10/12 13:34:44
C++左值与右值存储:拷贝、借用与托管三种方案 2026/10/12 13:34:44
BeanStore 中找不到属性 ‘oracle_install_RACInstall‘:从 db_install.rsp 响应文件到 TaoToken 的排查路径 2026/10/12 13:34:44

最新资讯

NanUI新版本实战:Chromium内核赋能.NET桌面应用开发
OPNET中LEACH协议仿真:从LANs.zip到能量优化实战
AI代码编辑器:塑造未来编程的新力量——深度解析Anysphere与Cursor的TaoToken接入实践
Node.js、Python、Java、Rust怎么选?hyperswitch-prism 支付SDK四语言安装与选型指南
NotePad功能扩展(2):用MyCursorAdapter与NoteEditor实现NoteColor换肤
可重构智能表面辅助多用户MIMO:无源波束成形与交替优化仿真解析

今日推荐

Debian新手入门:从部署到日常操作的完整指南
MongoDB复制集扩缩容实战:从rs.add到选主事故复盘
条形码目标检测数据集实战:从YOLOv8训练到部署

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

三国人物关系词频分析词云图:从文本到洞察的完整落地路径

发布时间:2026/10/12 13:39:44
三国人物关系词频分析词云图:从文本到洞察的完整落地路径 简介这是一份面向Python文本分析与数据可视化学习者的实战资源包围绕三国人物关系与词频展开适合想掌握中文分词、词频统计与词云图生成的中级学习者练手。包内共16个文件以txt文本、xml配置、png图片为主另含py脚本、ttf字体、doc报告等压缩包约6.73MB涵盖原始语料、停用词表、词频结果与可视化成品。资源完整呈现了从TXT读取、jieba分词、去停用词与标点、Counter词频统计到wordcloud词云图生成的流程并附人物社交关系网络图与设计报告便于对照理解文本预处理与可视化参数设置。目前已有959人学习下载读者可借此掌握中文文本清洗、词频排序与词云定制方法并参考报告梳理三国主要人物互动格局快速复现一套可迁移的文本分析小项目。1. 三国人物关系词频分析词云图从文本到洞察的完整落地路径拿到「三国人物关系词频分析词云图.zip」这个标题很多人第一反应是不就是把三国文本扔进词云工具跑一张图吗但真正动手就会发现事情远没那么简单。人物关系词频分析的核心难点不在词云生成而在于如何从非结构化的三国文本中准确提取人物共现关系并把关系强度量化成可比较的数值。词云图只是最终的可视化呈现前面的分词、人名识别、共现统计、权重计算才是决定成败的关键环节。这套方案适合有基础 Python 能力、想做文本挖掘实战的开发者也适合需要快速产出人物关系图谱的内容分析人员。接下来我会把整个流程拆开从数据准备到词云定制每一步都给出可复现的代码和参数说明。2. 数据准备与人物词典构建别让分词毁在第一步2.1 三国文本的获取与清洗策略做人物关系词频分析第一步不是写代码而是搞定文本。三国相关文本来源主要有三类一是《三国演义》原文约 64 万字二是《三国志》史书文本三是各类三国题材的评论、弹幕或同人文本。我一般优先用《三国演义》原文因为人物对话密集、关系描述丰富共现信号强。文本获取后要做的清洗包括去除章节标题中的「第X回」格式标记、统一全角半角标点、去掉空白行和页眉页脚残留。清洗脚本不复杂但漏掉一步就会在分词阶段引入噪声。import re def clean_sanguo_text(raw_text): # 去除章节标题行如「第一回 宴桃园豪杰三结义」 text re.sub(r第[一二三四五六七八九十百千]回.*?\n, \n, raw_text) # 全角标点转半角 text text.replace(, ,).replace(。, .).replace(, !) # 去除多余空白 text re.sub(r\s, , text) # 去除括号内注释性内容 text re.sub(r[\(].*?[\)], , text) return text.strip() with open(sanguo.txt, r, encodingutf-8) as f: raw f.read() cleaned clean_sanguo_text(raw) print(f清洗后文本长度: {len(cleaned)} 字符)这段代码的逻辑很直接先用正则干掉回目标题因为标题里的人物名会和正文重复计数然后统一标点避免分词器把「」和「,」当成不同 token最后压缩空白。参数方面正则里的[一二三四五六七八九十百千]覆盖了三国演义全部回目编号如果你的文本是《三国志》或其他版本需要根据实际标题格式调整。清洗后建议打印字符数做 sanity check正常《三国演义》清洗后应该在 60 万字符左右偏差超过 10% 说明清洗规则有问题。2.2 人物词典的构建与分词器配置通用分词器如 jieba 默认模式会把「诸葛亮」切成「诸葛」和「亮」把「司马懿」切成「司马」和「懿」这对人物关系分析是致命的。解决办法是构建自定义人物词典强制分词器把人名当作完整 token。三国核心人物大约 100-150 个我一般从三个来源汇总一是维基百科三国人物列表二是原文中高频出现的二字、三字名词三是手动补充的别名如「孔明」对应「诸葛亮」「孟德」对应「曹操」。词典格式是每行一个词后面可以跟词频和词性标签。import jieba # 构建人物词典 person_dict [ 诸葛亮, 司马懿, 曹操, 刘备, 孙权, 关羽, 张飞, 赵云, 周瑜, 吕布, 貂蝉, 袁绍, 董卓, 黄忠, 马超, 姜维, 孔明, 孟德, 玄德, 仲谋, 云长, 翼德, 子龙, 公瑾, 奉先, 本初, 仲颖, 汉升, 孟起, 伯约 ] # 加载自定义词典 for name in person_dict: jieba.add_word(name, freq1000, tagnr) # 别名映射表 alias_map { 孔明: 诸葛亮, 孟德: 曹操, 玄德: 刘备, 仲谋: 孙权, 云长: 关羽, 翼德: 张飞, 子龙: 赵云, 公瑾: 周瑜, 奉先: 吕布, 本初: 袁绍, 仲颖: 董卓, 汉升: 黄忠, 孟起: 马超, 伯约: 姜维 } def segment_with_person(text): words jieba.lcut(text) # 别名归一化 normalized [alias_map.get(w, w) for w in words] return normalized tokens segment_with_person(cleaned) print(f分词后 token 数: {len(tokens)})这里的关键参数是jieba.add_word的freq设为 1000这个值要足够高才能覆盖默认词典里的拆分倾向。tagnr是人名标记方便后续过滤。别名映射表必须手动维护因为「孔明」和「诸葛亮」在原文中交替出现不归一化会导致同一个人被统计成两个实体。分词后建议抽样检查前 200 个 token确认没有明显的人名被切碎。如果发现「诸葛」和「亮」还是分开的说明词典加载顺序有问题要在jieba.lcut之前完成所有add_word调用。3. 人物共现关系提取从句子窗口到关系矩阵3.1 共现窗口的设定与滑动统计人物关系的核心假设是如果两个人名在同一个句子或同一个段落窗口内频繁出现他们之间就存在较强的关系。这里有两个关键参数窗口类型句子级 vs 段落级和窗口大小固定 token 数 vs 自然句边界。我的经验是句子级窗口适合捕捉直接互动如对话、对战段落级窗口适合捕捉间接关联如同时被提及。实际操作中我一般用「句子级 5 token 滑动窗口」的组合先按句号、问号、感叹号切分句子再在每个句子内用大小为 5 的滑动窗口统计共现。from collections import defaultdict import math def extract_cooccurrence(tokens, person_set, window_size5): # 按标点切分句子 sentences [] current [] for t in tokens: if t in .!?;: if current: sentences.append(current) current [] else: current.append(t) if current: sentences.append(current) cooc defaultdict(int) person_freq defaultdict(int) for sent in sentences: # 统计单人物频次 for t in sent: if t in person_set: person_freq[t] 1 # 滑动窗口共现 for i in range(len(sent)): if sent[i] not in person_set: continue for j in range(i1, min(iwindow_size, len(sent))): if sent[j] in person_set and sent[j] ! sent[i]: pair tuple(sorted([sent[i], sent[j]])) cooc[pair] 1 return cooc, person_freq person_set set(person_dict) - set(alias_map.keys()) cooc_matrix, freq extract_cooccurrence(tokens, person_set, window_size5) print(f共现对数量: {len(cooc_matrix)}) print(f人物频次 top10: {sorted(freq.items(), keylambda x: -x[1])[:10]})这段代码的逻辑分三层先按标点切句保证共现不会跨句误统计然后在每个句子内统计单人物频次最后用滑动窗口统计共现对。window_size5意味着两个人名之间最多隔 4 个其他 token 就算共现。这个值调大关系网络会更密集但噪声也多调小则可能漏掉长句中的关联。我试过 3、5、8 三档5 在三国文本上平衡最好。pair tuple(sorted(...))保证 (A,B) 和 (B,A) 被统计为同一对。输出后要检查 top10 人物频次正常应该是曹操、刘备、诸葛亮、关羽、孙权这个量级如果出现「将军」「丞相」这类官职词说明词典还需要补充过滤。3.2 关系强度量化PMI 与归一化共现原始共现次数有个问题高频人物如曹操和任何人共现次数都高但这不代表关系强。需要用 PMI点互信息或归一化共现来修正。PMI 的公式是log(P(A,B) / (P(A)*P(B)))值越高说明两人关联越超出随机预期。但 PMI 对低频对不友好容易给出虚高分数。我一般用「归一化共现 最小频次阈值」的组合先过滤掉共现次数小于 3 的对再用cooc(A,B) / sqrt(freq(A)*freq(B))计算关系强度。def compute_relation_strength(cooc, freq, min_cooc3): strength {} for (a, b), c in cooc.items(): if c min_cooc: continue # 归一化共现强度 score c / math.sqrt(freq[a] * freq[b]) strength[(a, b)] { cooc: c, score: round(score, 4), freq_a: freq[a], freq_b: freq[b] } return strength relations compute_relation_strength(cooc_matrix, freq, min_cooc3) # 按强度排序输出 top20 top_relations sorted(relations.items(), keylambda x: -x[1][score])[:20] for (a, b), info in top_relations: print(f{a} - {b}: 共现{info[cooc]}次, 强度{info[score]})min_cooc3是经验阈值低于 3 次的共现大概率是偶然同句不值得分析。归一化公式里sqrt(freq[a]*freq[b])是几何平均比算术平均更能抑制高频人物的影响。输出结果里正常应该看到「刘备-诸葛亮」「曹操-关羽」「孙权-周瑜」这类强关联对排在前列。如果出现「曹操-刘备」强度异常高要检查是不是把「曹刘」这种并称当成了共现需要在分词阶段把并称也加入词典或做特殊处理。这个矩阵可以直接导出成 CSV后续词云和网络图都用它作为输入。4. 词云图生成与人物关系可视化参数调优与避坑指南4.1 词云图生成的完整代码与参数详解词云图的核心参数有三个字体、蒙版形状、词频权重。中文字体必须显式指定否则会显示成方块。蒙版形状决定词云的轮廓常见做法是用三国地图或人物剪影。词频权重直接用上一步的关系强度或人物频次。我一般用wordcloud库配合matplotlib输出。from wordcloud import WordCloud import matplotlib.pyplot as plt from PIL import Image import numpy as np # 准备词频字典用人物频次作为权重 word_freq {name: count for name, count in freq.items() if count 5} # 加载蒙版图片需为黑白二值图白色区域不填充 mask np.array(Image.open(sanguo_mask.png)) wc WordCloud( font_pathSimHei.ttf, # 中文字体路径 width1200, height800, # 输出尺寸 background_colorwhite, # 背景色 maskmask, # 蒙版 max_words100, # 最多显示词数 max_font_size150, # 最大字号 min_font_size10, # 最小字号 colormapviridis, # 配色方案 random_state42, # 随机种子保证可复现 prefer_horizontal0.7 # 水平排列比例 ) wc.generate_from_frequencies(word_freq) plt.figure(figsize(15, 10)) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.savefig(sanguo_wordcloud.png, dpi200, bbox_inchestight) plt.show()font_path必须指向系统中实际存在的中文字体文件Windows 一般在C:/Windows/Fonts/下Linux 需要手动安装。mask参数要求图片是黑白二值图白色区域会被忽略黑色区域填充文字。max_words100控制显示词数太多会拥挤太少信息量不足。random_state42保证每次生成的布局一致方便调试。prefer_horizontal0.7让 70% 的词水平排列剩余垂直排列视觉上更自然。如果输出图片里人物名大小差异不明显说明词频区分度不够可以考虑对频次取对数后再传入。4.2 人物关系网络图的补充可视化词云图擅长展示人物频次但关系强度用网络图更直观。我一般用networkx配合matplotlib画关系网络节点大小对应人物频次边粗细对应关系强度。这样一张图就能同时看到「谁重要」和「谁和谁关系近」。import networkx as nx G nx.Graph() # 添加节点大小按频次 for name, count in freq.items(): if count 5: G.add_node(name, sizecount) # 添加边权重按关系强度 for (a, b), info in relations.items(): if info[score] 0.1: # 过滤弱关系 G.add_edge(a, b, weightinfo[score]) pos nx.spring_layout(G, k2, seed42) node_sizes [G.nodes[n][size] * 20 for n in G.nodes()] edge_widths [G[u][v][weight] * 5 for u, v in G.edges()] plt.figure(figsize(16, 12)) nx.draw_networkx_nodes(G, pos, node_sizenode_sizes, node_colorlightblue, alpha0.8) nx.draw_networkx_edges(G, pos, widthedge_widths, alpha0.5, edge_colorgray) nx.draw_networkx_labels(G, pos, font_size10, font_familySimHei) plt.axis(off) plt.savefig(sanguo_network.png, dpi200, bbox_inchestight) plt.show()spring_layout的k参数控制节点间距调大更分散调小更紧凑。seed42同样是为了可复现。边过滤阈值score 0.1需要根据实际数据分布调整可以先画全量图再决定砍在哪里。节点大小乘以 20 是缩放因子避免频次差异导致节点过大或过小。这张图配合词云图一起看基本能把三国人物关系的核心结构呈现出来。5. 避坑与常见问题排查那些让我翻车的细节5.1 人名识别不全导致关系遗漏现象关系网络图里只有曹操、刘备几个核心人物大量次要人物如「张辽」「徐晃」完全没出现。原因自定义词典只覆盖了主角分词器把次要人名切碎导致共现统计时这些人物被忽略。解决从原文中提取所有二字、三字高频名词人工筛选出人名补充进词典。我一般用jieba.analyse.extract_tags先跑一遍关键词再对照三国人物列表补全。词典至少覆盖 100 人以上否则关系网络会严重失真。5.2 共现窗口过大引入虚假关系现象曹操和貂蝉的关系强度异常高但原文中两人几乎没有直接互动。原因滑动窗口设成了 10导致同一段落里相隔很远的两个人名也被统计为共现。解决把window_size降到 5 以内并优先用句子边界切分。如果必须用段落级窗口建议加一个「中间不能有其他人名」的约束避免 A-C-B 被误判为 A-B 共现。5.3 词云图中文显示为方块现象生成的词云图里所有中文都是方框英文和数字正常。原因font_path指向的字体文件不存在或者字体本身不包含中文字形。解决确认字体文件路径正确Windows 用C:/Windows/Fonts/simhei.ttfLinux 用fc-list :langzh查找可用中文字体。如果还是不行换用SourceHanSansCN或NotoSansCJK这类开源中文字体。5.4 关系强度分数区分度低现象所有人物对的强度分数都在 0.3-0.5 之间看不出明显差异。原因归一化公式对高频人物的抑制不够或者共现次数本身分布太均匀。解决改用 TF-IDF 思路对共现次数取对数后再归一化或者直接对分数做 min-max 标准化拉到 0-1 区间。另一个办法是只保留每个节点的 top3 强关系砍掉长尾边让核心结构更突出。5.5 蒙版图片导致词云布局异常现象词云图里文字全部挤在角落或者大量空白区域。原因蒙版图片不是二值图或者白色区域和黑色区域搞反了。解决用 PIL 把蒙版转成灰度图再用阈值二值化确保白色是背景、黑色是填充区。如果蒙版太复杂如精细地图轮廓建议先做形态学膨胀让填充区域更连续。6. 进阶技巧用 TF-IDF 加权和动态阈值提升关系识别精度前面用的归一化共现有个局限它只考虑全局频次不考虑人物在不同章节的分布差异。如果两个人只在某一回集中出现他们的关系可能被高估。进阶做法是引入 TF-IDF 思路把每个人物看作一个「文档」共现对看作「词」计算共现对在人物上下文中的重要性。具体来说对每个人物 A统计它与其他所有人物的共现分布然后对每个共现对 (A,B) 计算TF(A,B) * IDF(B)其中 TF 是 A 视角下 B 的共现占比IDF 是 B 的全局稀有度。这样能抑制「曹操-刘备」这种高频但泛泛的关系突出「关羽-颜良」这种低频但关键的对决关系。def tfidf_relation(cooc, freq, person_set): # 构建每个人物的共现分布 person_cooc defaultdict(dict) for (a, b), c in cooc.items(): person_cooc[a][b] c person_cooc[b][a] c total_pairs len(cooc) tfidf_scores {} for person, neighbors in person_cooc.items(): total sum(neighbors.values()) for other, c in neighbors.items(): tf c / total # IDF: 包含 other 的共现对越少IDF 越高 idf math.log(total_pairs / (1 sum(1 for (x, y) in cooc if other in (x, y)))) tfidf_scores[(person, other)] tf * idf return tfidf_scores tfidf_rel tfidf_relation(cooc_matrix, freq, person_set) # 对每个节点取 top3 关系 top_per_person defaultdict(list) for (a, b), score in tfidf_rel.items(): top_per_person[a].append((b, score)) for person in top_per_person: top_per_person[person] sorted(top_per_person[person], keylambda x: -x[1])[:3] # 输出示例 for person, rels in list(top_per_person.items())[:5]: print(f{person}: {[(r[0], round(r[1], 3)) for r in rels]})这段代码的核心是tf和idf的计算。tf c / total表示在人物 A 的所有共现中与 B 的共现占比。idf用log(total_pairs / (1 包含 other 的对数))包含 other 的对越少IDF 越高说明这个关系越独特。最后对每个人物只保留 top3 关系避免网络图过于密集。实际跑下来「关羽-颜良」「张飞-严颜」这类特定对手关系会明显浮上来而「曹操-刘备」这种泛泛之交会被压下去。这个技巧在分析人物关系时特别有用因为它能区分「经常一起出现」和「关系真正紧密」。最后说个习惯我每次跑完词云和网络图都会把 top20 关系对导出来人工过一遍看看有没有明显违背常识的。有一次发现「诸葛亮-司马懿」强度排到了第一检查后发现是原文中「诸葛」和「司马」被当成了两个人名分别统计修正词典后才恢复正常。数据挖掘的坑一半在代码一半在词典。希望帮到你。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号