04python实现笑傲江湖人物关系网
准备工作
jieba中文分词库的安装(Anaconda没有集成)
win + r 运行cmd 输入 pip install jieba 这个命令可能会安装失败
用国内镜像就行:cmd 命令输入: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba
人物字典dict.txt
林震南
林平之
王夫人
史镖头
郑镖头
方人智
余观主
宛儿
陈七
白二
崔镖头
季镖头
高镖头
褚镖头
林福
黄夫子
狄镖头
霍镖头
于人豪
贾人达
笑傲江湖 TXT 文件
脚本文件简介
relationship.py 是人物关系的生成,会自动生成 xiaoao_edge.txt 和 xiaoao_node.txt 两个文件
test.py 是生成人物关系网的主要部分
实现功能
1、读入小数数据和角色词典后,对数据分词后生成角色关系数据(有向关系数据)
2、无需gephi绘图即可制作绚丽角色关系网络图。
代码
1.relationship.py
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 22 21:45:01 2020
@author: 陈建兵
"""
# -*- coding: utf-8 -*-
import jieba, codecs
import jieba.posseg as pseg
#返回人物列表
def node_ren() :
#================================================================
ren_list=[]
# 打开文件
fo = open("dict.txt", "r", encoding='utf-8-sig')
print ("文件名为: ", fo.name)
for line in fo.readlines(): #依次读取每行
line = line.strip() #去掉每行头尾空白
#line = line.split(" ")
ren_list.append(line)
#print ("读取的数据为: %s" % (line))
return ren_list
# 关闭文件
fo.close()
names = {} # 姓名字典
relationships = {} # 关系字典
lineNames = [] # 每段内人物关系
myList = node_ren()
#print(myList)
# count names
jieba.load_userdict("dict.txt") # 加载字典
with codecs.open("笑傲江湖.txt", "r", "utf8") as f:
for line in f.readlines():
poss = pseg.cut(line) # 分词并返回该词词性
lineNames.append([]) # 为新读入的一段添加人物名称列表
for w in poss:
# 当分词长度小于2或该词词性不为nr时或不在我们提供的字典列表里的分词认为该词不为人名
if w.flag != "nr" or len(w.word) < 2 or w.word not in myList:
continue
lineNames[-1].append(w.word) # 为当前段的环境增加一个人物
if names.get(w.word) is None:
names[w.word] = 0
relationships[w.word] = {}
names[w.word] += 1 # 该人物出现次数加 1
# explore relationships
for line in lineNames: # 对于每一段
for name1 in line:
for name2 in line: # 每段中的任意两个人
if name1 == name2:
continue
if relationships[name1].get(name2) is None: # 若两人尚未同时出现则新建项
relationships[name1][name2]= 1
else:
relationships[name1][name2] = relationships[name1][name2]+ 1 # 两人共同出现次数加 1
# output
with codecs.open("xiaoao_node.txt", "w", "gbk") as f:
#f.write("Id Label Weight\r\n")
for name, times in names.items():
f.write(name + " " + "\r\n")
with codecs.open("xiaoao_edge.txt", "w", "gbk") as f:
#f.write("Source Target Weight\r\n")
for name, edges in relationships.items():
for v, w in edges.items():
if w > 3:
f.write(name + " " + v + "\r\n")
2.test.py
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 22 21:54:45 2020
@author: 陈建兵
"""
#导入networkx,matplotlib包
import networkx as nx
import matplotlib.pyplot as plt
#导入random包
import random
#==============================================================
#统计文件行数
def countLine(filePath):
count = -1
for count,line in enumerate(open(filePath,'r')):
pass
count += 1
return count
#================================================================
#返回人物节点列表
def node() :
node_list=[]
# 打开文件
fo = open("xiaoao_node.txt", "r")
print ("文件名为: ", fo.name)
for line in fo.readlines(): #依次读取每行
line = line.strip() #去掉每行头尾空白
node_list.append(line)
#print ("读取的数据为: %s" % (line))
return node_list
# 关闭文件
fo.close()
#========================================================================
#返回人物节点关系
def edge() :
#================================================================
edge_list=[]
# 打开文件
fo = open("xiaoao_edge.txt", "r")
print ("文件名为: ", fo.name)
for line in fo.readlines(): #依次读取每行
line = line.strip() #去掉每行头尾空白
line_tup = tuple(line.split(" "))
edge_list.append(line_tup)
#print ("读取的数据为: %s" % (line))
return edge_list
# 关闭文件
fo.close()
#=====================================================================
#颜色生成
colorNum = countLine('xiaoao_node.txt')
print('颜色数',colorNum)
def randomcolor():
colorArr = ['1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
color = ""
for i in range(6):
color += colorArr[random.randint(0,14)]
return "#"+color
def color_list():
colorList = []
for i in range(colorNum):
colorList.append(randomcolor())
return colorList
#========================画图开始=================================
colors = color_list()
#有向图
DG = nx.DiGraph()
#一次性添加多节点,输入的格式为列表
DG.add_nodes_from(node())
#添加边,数据格式为列表
DG.add_edges_from(edge())
#作图,设置节点名显示,节点大小,节点颜色
nx.draw(DG,with_labels=True, node_size=900, node_color = colors, font_family ='YouYuan')
#保存图表
plt.savefig('笑傲江湖人物关系网.png',bbox_inches='tight')
plt.show()