news 2026/5/28 19:15:42

用Python给《三国演义》做一次“CT扫描”:手把手教你生成人物关系图与词云(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Python给《三国演义》做一次“CT扫描”:手把手教你生成人物关系图与词云(附完整代码)

用Python透视《三国演义》:从文本挖掘到可视化叙事的技术实践

翻开《三国演义》的纸质书页,我们看到的是一行行墨色文字;而打开它的数字文本,我们面对的则是可被算法解析的字符序列。这种视角转换正是现代文本分析的有趣之处——当古典文学遇上Python代码,章回小说便成了待挖掘的数据金矿。本文将带你用NLP技术给这部名著做一次深度"体检",不仅生成词云和关系图,更重要的是理解如何将文学文本转化为结构化洞察。

1. 环境准备与数据清洗

任何数据分析项目的第一步都是搭建合适的工作环境。这里我们需要一个支持中文处理的Python栈:

pip install jieba networkx wordcloud pyecharts matplotlib imageio

注意:建议使用Python 3.7+环境,某些库的最新版本可能存在兼容性问题。若安装失败,可尝试指定版本号,如pip install pyecharts==1.9.0

1.1 文本预处理要点

原始文本需要经过多道清洗工序才能用于分析:

  1. 字符集转换:确保UTF-8编码避免乱码
  2. 特殊符号处理:删除章节标记、标点等噪声
  3. 别名归一化(关键步骤):
alias_mapping = { '孔明': '诸葛亮', '云长': '关羽', '玄德': '刘备', '孟德': '曹操', # 其他别名对应关系... }

这种映射解决了文学作品中人物多称谓的核心挑战。实际操作中,建议建立完整的别名词典文件(如JSON格式),方便复用至其他作品分析。

2. 人物影响力量化分析

2.1 词频统计的进阶处理

简单的分词统计可能包含大量干扰项,我们需要:

  • 使用jieba的词性标注功能过滤非人名
  • 应用停用词表排除通用称谓
  • 设置最小词长阈值
import jieba.posseg as pseg def count_character_mentions(text): counts = {} words = pseg.cut(text) for word, flag in words: if flag == 'nr' and len(word) > 1 and word not in stopwords: normalized_name = alias_mapping.get(word, word) counts[normalized_name] = counts.get(normalized_name, 0) + 1 return counts

2.2 可视化呈现方案对比

不同可视化工具各有优劣:

工具库适合场景交互性美观度学习曲线
Matplotlib静态图表中等平缓
Pyecharts网页交互较陡
Plotly动态展示中等

对于人物出场频次,推荐使用Pyecharts生成可交互柱状图:

from pyecharts.charts import Bar def create_interactive_bar(counts, top_n=20): sorted_counts = sorted(counts.items(), key=lambda x: x[1], reverse=True) names = [x[0] for x in sorted_counts[:top_n]] values = [x[1] for x in sorted_counts[:top_n]] bar = ( Bar() .add_xaxis(names) .add_yaxis("出场次数", values) .set_global_opts(title_opts={"text": "三国人物出场频次TOP20"}) ) return bar

3. 社交网络关系挖掘

3.1 共现关系算法设计

人物关系的核心是共现分析,我们采用段落级共现策略:

  1. 按换行符分割文本段落
  2. 在每段中检测人物共同出现情况
  3. 构建加权无向图
import networkx as nx def build_cooccurrence_network(text, characters, min_cooccur=3): G = nx.Graph() paragraphs = text.split('\n') for para in paragraphs: present_chars = [char for char in characters if char in para] # 为所有共现组合添加边权重 for i in range(len(present_chars)): for j in range(i+1, len(present_chars)): if G.has_edge(present_chars[i], present_chars[j]): G[present_chars[i]][present_chars[j]]['weight'] += 1 else: G.add_edge(present_chars[i], present_chars[j], weight=1) # 过滤低频共现 to_remove = [(u, v) for u, v, d in G.edges(data=True) if d['weight'] < min_cooccur] G.remove_edges_from(to_remove) return G

3.2 网络可视化技巧

使用NetworkX结合Matplotlib绘图时,几个美化技巧:

  • 节点布局:尝试spring_layout, circular_layout或kamada_kawai_layout
  • 边权重映射:用线条粗细和透明度表示关系强度
  • 社区发现:使用Louvain算法染色节点群体
def draw_network(G): pos = nx.spring_layout(G, k=0.15, iterations=50) plt.figure(figsize=(16, 12)) # 按度数计算节点大小 node_sizes = [2000 * G.degree(n) for n in G.nodes()] nx.draw_networkx_nodes(G, pos, node_size=node_sizes, alpha=0.8) nx.draw_networkx_labels(G, pos, font_size=10) # 绘制不同权重的边 for (u, v, d) in G.edges(data=True): width = d['weight'] * 0.5 nx.draw_networkx_edges(G, pos, edgelist=[(u, v)], width=width, alpha=0.5) plt.axis('off') plt.tight_layout()

4. 多维叙事可视化

4.1 动态词云生成

传统词云只展示频率,我们可以增加时间维度:

  1. 按章回分割文本
  2. 计算各时期词频变化
  3. 生成动态GIF展示演变
from wordcloud import WordCloud import imageio def generate_chapter_wordclouds(text, output_folder): chapters = text.split('第')[1:] # 简单章回分割 images = [] for i, chapter in enumerate(chapters[:10]): # 示例取前10章 wc = WordCloud(font_path="simhei.ttf", width=800, height=600) wc.generate(chapter) path = f"{output_folder}/chapter_{i}.png" wc.to_file(path) images.append(imageio.imread(path)) imageio.mimsave('evolution.gif', images, duration=0.5)

4.2 时空轨迹可视化

结合地理信息可展示人物活动轨迹(需额外地理数据):

from pyecharts.charts import Geo def create_character_route(character, events): geo = ( Geo() .add_schema(maptype="china") .add( character, [((lon, lat), count) for (place, lon, lat), count in events.items()], type_="lines", ) .set_global_opts(title_opts={"text": f"{character}活动轨迹"}) ) return geo

5. 分析框架的通用化改造

为使本方案适用于其他文学作品,需要建立可配置的管道:

  1. 参数配置文件(config.yaml):
aliases: 宝玉: 贾宝玉 颦儿: 林黛玉 stopwords: - 姑娘 - 老爷 chapter_markers: - "第" - "回"
  1. 模块化处理流程
class TextAnalyzer: def __init__(self, config_path): self.load_config(config_path) def analyze(self, text_path): text = self.preprocess(text_path) stats = self.calculate_stats(text) visuals = self.generate_visuals(stats) return visuals

这种架构设计使得分析《红楼梦》只需更换配置文件和文本即可。

6. 性能优化与大规模处理

当处理超长文本(如全套金庸小说)时,需要考虑:

  • 内存优化:使用生成器逐段处理
  • 并行计算:多进程处理不同章节
  • 增量处理:保存中间结果避免重复计算
from multiprocessing import Pool def parallel_analyze(text_chunks): with Pool(4) as p: # 4进程 results = p.map(process_chunk, text_chunks) return merge_results(results)

7. 从分析到叙事:技术的人文解读

纯技术输出只是第一步,更重要的是如何解读:

  • 人物关系异常检测:发现非典型密切关系
  • 词频趋势分析:识别关键事件转折点
  • 风格对比:不同作者或时期的写作特征

例如,诸葛亮出场频率在赤壁之战前后形成明显高峰,这种模式识别正是文本挖掘的价值所在。

在完成《三国演义》分析后,这套方法可无缝迁移至:

  • 《红楼梦》家族关系图谱构建
  • 金庸武侠小说门派势力分析
  • 网络小说写作模式研究

文本分析项目常见的坑包括编码问题、别名识别不全、停用词过滤过度等。建议从简单版本开始迭代,先用小样本测试流程,再扩展到全文处理。保存中间结果能大幅降低调试成本——毕竟没人想为了一个标点错误重新跑八小时的全书处理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 19:11:07

如何摆脱AutoCAD束缚?开源DWG处理库LibreDWG实战指南

如何摆脱AutoCAD束缚&#xff1f;开源DWG处理库LibreDWG实战指南 【免费下载链接】libredwg Official mirror of libredwg. With CI hooks and nightly releases. PRs ok 项目地址: https://gitcode.com/gh_mirrors/li/libredwg 你是不是经常遇到这样的困境&#xff1a;…

作者头像 李华
网站建设 2026/5/28 19:08:23

如何高效使用BG3ModManager:博德之门3模组管理终极教程

如何高效使用BG3ModManager&#xff1a;博德之门3模组管理终极教程 【免费下载链接】BG3ModManager A mod manager for Baldurs Gate 3. This is the only official source! 项目地址: https://gitcode.com/gh_mirrors/bg/BG3ModManager 你是否在为《博德之门3》的模组管…

作者头像 李华
网站建设 2026/5/28 19:05:52

基于555定时器的电子圣诞树:模拟电路实现LED闪烁与PCB艺术设计

1. 项目概述与核心思路又到了年底&#xff0c;是时候给工作台添点节日气氛了。作为一个电子爱好者&#xff0c;总觉得市面上的装饰灯少了点“硬核”的味道。这次&#xff0c;我决定自己动手&#xff0c;用最经典的555定时器芯片&#xff0c;搭配一块定制PCB&#xff0c;做一棵能…

作者头像 李华
网站建设 2026/5/28 19:05:26

Dism++终极指南:免费开源的Windows系统优化神器

Dism终极指南&#xff1a;免费开源的Windows系统优化神器 【免费下载链接】Dism-Multi-language Dism Multi-language Support & BUG Report 项目地址: https://gitcode.com/gh_mirrors/di/Dism-Multi-language 还在为Windows系统卡顿、C盘爆满、更新失败而烦恼吗&a…

作者头像 李华