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()

运行结果



代码下载

posted @ 2021-10-10 17:42  暗恋花香  阅读(221)  评论(0编辑  收藏  举报