Gephi 可视化 + NetworkX 网络分析——《釜山行》人物关系(三)
标签:
Gephi|NetworkX|Python3|matplotlib|网络可视化|人物关系
实验环境: 华为云 FlexusX / Ubuntu 24.04 / Python 3.12.3
分析节点: node-03(公网 124.70.105.142)
可视化节点: node-04(公网 120.46.44.194)
1. 本文目标
- 在
node-03用 NetworkX 构建无向图,计算常见网络指标; - 导出
.gexf/.graphml格式,供 Gephi 导入; - 在
node-04用 matplotlib 生成静态可视化图; - 演示 Gephi 安装和导入流程;
- 对结果进行解读。
2. NetworkX 网络分析(node-03)
2.1 代码(busan_network.py)
#!/usr/bin/env python3importnetworkxasnximportjson# 读取节点和边nodes=[]withopen("/root/nodes.csv","r",encoding="utf-8")asf:forlineinf.readlines()[1:]:parts=line.strip().split(",")nodes.append({"id":parts[0],"label":parts[1],"weight":int(parts[2])})edges=[]withopen("/root/edges.csv","r",encoding="utf-8")asf:forlineinf.readlines()[1:]:parts=line.strip().split(",")edges.append({"source":parts[0],"target":parts[1],"weight":int(parts[2])})# 构建无向图G=nx.Graph()fornodeinnodes:G.add_node(node["id"],label=node["label"],weight=node["weight"])foredgeinedges:G.add_edge(edge["source"],edge["target"],weight=edge["weight"])# 计算指标degree_centrality=nx.degree_centrality(G)betweenness_centrality=nx.betweenness_centrality(G)closeness_centrality=nx.closeness_centrality(G)eigenvector_centrality=nx.eigenvector_centrality(G,max_iter=1000)clustering=nx.clustering(G)density=nx.density(G)avg_path=nx.average_shortest_path_length(G)# 指标写入节点属性fornodeinG.nodes():G.nodes[node]["degree_centrality"]=round(degree_centrality[node],4)G.nodes[node]["betweenness_centrality"]=round(betweenness_centrality[node],4)G.nodes[node]["closeness_centrality"]=round(closeness_centrality[node],4)G.nodes[node]["eigenvector_centrality"]=round(eigenvector_centrality[node],4)G.nodes[node]["clustering"]=round(clustering[node],4)# 导出 Gephi 格式nx.write_gexf(G,"/root/busan_network.gexf")nx.write_graphml(G,"/root/busan_network.graphml")stats={"nodes":len(nodes),"edges":len(edges),"density":round(density,4),"avg_path_length":round(avg_path,4),"degree_centrality":{k:round(v,4)fork,vindegree_centrality.items()},"betweenness_centrality":{k:round(v,4)fork,vinbetweenness_centrality.items()},"closeness_centrality":{k:round(v,4)fork,vincloseness_centrality.items()},"eigenvector_centrality":{k:round(v,4)fork,vineigenvector_centrality.items()},}withopen("/root/network_stats.json","w",encoding="utf-8")asf:json.dump(stats,f,ensure_ascii=False,indent=2)2.2 真实服务器输出
root@ecs-11e6-0003:~# cd /root && python3 busan_network.py ============================================================ 步骤1: 读取节点和边数据 ============================================================ 节点数: 11 边数: 55 ============================================================ 步骤2: 构建NetworkX无向图 ============================================================ 图节点数: 11 图边数: 55 ============================================================ 步骤3: 计算网络拓扑指标 ============================================================ --- 度中心性 (Degree Centrality) --- 石宇: 1.0000 秀安: 1.0000 尚华: 1.0000 盛京: 1.0000 珍熙: 1.0000 英国: 1.0000 容国: 1.0000 老姐姐: 1.0000 老妹妹: 1.0000 乞丐: 1.0000 列车长: 1.0000 --- 介数中心性 (Betweenness Centrality) --- 石宇: 0.0000 ... 列车长: 0.0000 --- 接近中心性 (Closeness Centrality) --- 石宇: 1.0000 ... 列车长: 1.0000 --- 特征向量中心性 (Eigenvector Centrality) --- 石宇: 0.3015 ... 列车长: 0.3015 --- 聚类系数 (Clustering Coefficient) --- 石宇: 1.0000 ... 列车长: 1.0000 网络密度 (Density): 1.0000 平均最短路径长度: 1.00002.3 指标解释
| 指标 | 含义 | 本实验结果 | 说明 |
|---|---|---|---|
| 度中心性 | 节点直接连接数占总节点数的比例 | 1.0 | 完全图,每人都与其他 10 人相连 |
| 介数中心性 | 最短路径中经过该节点的比例 | 0.0 | 任意两点都直接相连,无“桥梁” |
| 接近中心性 | 到达其他节点的平均距离倒数 | 1.0 | 距离全为 1,最紧密 |
| 特征向量中心性 | 连接的邻居重要程度的综合 | 0.3015 | 完全图,所有节点相同 |
| 聚类系数 | 邻居之间两两相连的比例 | 1.0 | 邻居子图也是完全图 |
| 网络密度 | 实际边数 / 最大可能边数 | 1.0 | 完全图密度 |
| 平均最短路径 | 任意两节点最短距离平均 | 1.0 | 一步可达 |
可见,当文本较短、所有人物都相互共现时,NetworkX 的拓扑指标会全部拉满。因此真正有用的信息是边权重(共现次数),而非二值网络的拓扑结构。下面的可视化将突出边权重。
3. matplotlib 静态可视化(node-04)
3.1 全图可视化
busan_visualize.py读取busan_network.gexf,使用 Spring 布局渲染,得到:
节点大小 = 出现频次;节点颜色 = 出现频次;边宽度 = 共现次数;白色标签为边权重。
3.2 人物频次图
3.3 中心性指标对比图
从图中可见度中心性、接近中心性、聚类系数均为 1,介数中心性均为 0,再一次验证“完全图”结论。
3.4 过滤核心网络(权重 >= 7)
为了突出核心关系,新增busan_visualize_filtered.py,只保留共现次数 ≥ 7 的边:
THRESHOLD=7G=nx.Graph()fornode,attrinG_full.nodes(data=True):G.add_node(node,**attr)foru,v,attrinG_full.edges(data=True):ifattr.get("weight",0)>=THRESHOLD:G.add_edge(u,v,weight=attr["weight"])输出结果:
过滤阈值: >= 7 节点数: 11, 边数: 24过滤后,核心人物被聚成紧密社群,而老姐姐、老妹妹、列车长因共现次数低于阈值而孤立,直观说明她们在叙事中相对边缘。
3.5 核心关系表
Top 核心关系集中在:
- 石宇 ↔ 秀安(父女,12)
- 石宇 ↔ 盛京(共同保护秀安,11)
- 秀安 ↔ 盛京(被共同保护,11)
- 石宇 ↔ 尚华(并肩作战,9)
- 尚华 ↔ 盛京(夫妻,9)
- 珍熙 ↔ 容国(恋人,9)
这与电影剧情高度吻合。
4. Gephi 安装与导入流程
4.1 安装 OpenJDK 17
Gephi 是 Java 桌面程序,需要 JDK 17:
apt-getupdate-qqapt-getinstall-yopenjdk-17-jdk4.2 下载 Gephi
wgethttps://github.com/gephi/gephi/releases/download/v0.10.1/gephi-0.10.1-linux-x64.tar.gzsudotarxzf gephi-0.10.1-linux-x64.tar.gz-C/opt如果 GitHub 下载慢,可以先把安装包本地下载再 SCP 到服务器。
4.3 导入 GEXF
- 打开 Gephi →数据实验室→导入电子表格;
- 选择
nodes.csv,导入为节点表; - 选择
edges.csv,导入为边表; - 或直接文件 → 打开,选择
busan_network.gexf。
4.4 推荐布局与样式设置
| 设置项 | 推荐值 | 效果 |
|---|---|---|
| 布局算法 | Force Atlas 2 / Fruchterman-Reingold | 自动展开节点 |
| 节点大小 | Weight(出现频次) | 突出主角 |
| 节点颜色 | Modularity(社团检测) | 区分人物社群 |
| 边粗细 | Weight(共现次数) | 关系越强越粗 |
| 标签 | 显示 Label | 人物名称 |
5. 踩坑总结
| 问题 | 原因 | 解决 |
|---|---|---|
pip3 install失败 | Ubuntu 24.04 PEP 668 | 加--break-system-packages |
| 多 pip 进程死锁 | 批量安装并发 | 单节点nohup后台安装,安装完验证导入 |
| 中文乱码 | 无中文字体 | apt-get install fonts-noto-cjk |
| 介数中心性除零 | 完全图所有值为 0 | 改以节点频次作为颜色映射 |
| SSH banner 读取失败 | 连接过于频繁 | 加banner_timeout=60并间隔重试 |
6. 三篇完整输出文件
| 文件 | 说明 |
|---|---|
busan_text.txt | 电影文本 |
busan_dict.txt | 自定义人名词典 |
busan_segment.py | 分词与共现提取 |
busan_network.py | NetworkX 分析 |
busan_visualize.py | matplotlib 全图可视化 |
busan_visualize_filtered.py | 核心网络可视化 |
nodes.csv | Gephi 节点表 |
edges.csv | Gephi 边表 |
busan_network.gexf | Gephi 导入文件 |
network_stats.json | 网络指标统计 |
7. 总结
本项目通过 4 台服务器完整演示了:
- 共现网络的理论和构建方法;
- jieba分词与自定义词典;
- NetworkX网络指标计算;
- GEXF导出与Gephi导入流程;
- matplotlib静态可视化与权重过滤技巧。
从《釜山行》人物关系中提取到的核心社群与电影剧情一致,验证了共现网络方法在文本人物关系挖掘上的有效性。
8. 参考
- jieba:https://github.com/fxsjy/jieba
- NetworkX:https://networkx.org/documentation/stable/
- Gephi:https://gephi.org/
- matplotlib:https://matplotlib.org/