NLP分析小说人物关系,找找主人公的真爱。

思路
基于共现来挖掘人物之间的关系。
准备好三个存储器

  1. names 存放的是人物出现次数,用来后面刻画节点的大小。names类似’叶三姐’: 8, ‘马鞍’: 6,
  2. relationships 存放人物关系 {‘钱塘江’: {‘牛家村’: 1}, ‘牛家村’: {‘钱塘江’: 1, ‘武功’: 1, ‘王道乾’: 1, ‘郭啸天’: 1,}} 嵌套字典。
  3. lineNames 共现词 类似[[‘钱塘江’, ‘牛家村’], [‘柏树’, ‘叶子’], [], [‘萧索’, ‘松树’]]

思路不解释,自己看代码,这也是我学习之后写的。
看别人文字思路,不如看代码。毕竟文字思路多啦一道转换。

步骤1

import jieba.posseg as pseg
from  tqdm import tqdm#设置一个进度条
# 姓名字典
names = {}
# 关系字典
relationships = {}
# 每段内人物关系
lineNames = []
#打开文件
with open('射雕英雄传.txt', 'r',encoding='utf-8') as fp:
    for line in tqdm(fp):
        line = line.strip('\n')#去除换行
        poss = pseg.cut(line)# 分词返回词性

        # 为新读取的一段添加人物关系
        lineNames.append([])
        for w in poss:#遍历每一个
           # print("%s:%s" % (w.word, w.flag))
           # 分词长度小于2 或词性不为nr时则与影片所需分析人物无关
           if w.flag != "nr" or len(w.word) < 2:
               continue
           lineNames[-1].append(w.word)#当前段存放人物名

           if names.get(w.word) is None:#如果姓名未出现过
               names[w.word] = 0#当前姓名添加进names字典里
               relationships[w.word] = {}#初始化该姓名关系图
               # 人物出现次数+1
           names[w.word] += 1

print('names\n',names)
print('relationships\n',relationships)
print('lineNames\n',lineNames)

步骤2

#分析人物关系
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:
                    # 两个人物共同出现 关系+1
                    relationships[name1][name2] += 1

步骤3

# 写csv文件 用于网络图使用
def generate_gephi():
    # 人物权重(节点)
    with open("earth_node.csv", "w", encoding='utf-8') as f:
        f.write("Id Label Weight\r\n")
        for name, times in names.items():
            f.write(name + " " + name + " " + str(times) + "\r\n")

    # 人物关系边(边)
    with open("earth_edge.csv", "w", encoding='utf-8') as f:
        f.write("Source Target Weight\r\n")
        for name, edge in relationships.items():
            for v, w in edge.items():
                if w > 3:
                    f.write(name + " " + v + " " + str(w) + "\r\n")

generate_gephi()


得到的数据 是一列的

需要应用excel 技术将一列分成多列
如结果

画图

import pandas as pd



file1=pd.read_csv('earth_edge.csv',encoding='gbk')#人物关系
file1=file1.dropna()



import networkx as nx
from pylab import *
import matplotlib.pyplot as plt
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False

def painting(): #绘制人物亲密度图
    G = nx.Graph()  # 绘制个人物之间的亲密关系

    for index, row in file1.iterrows():
        G.add_node(row['Source'])#添加节点
    for index, row in file1.iterrows():
        G.add_weighted_edges_from([(row['Source'],row['Target'],row['Weight'])])
    pos = nx.shell_layout(G)
    print('画出网络图像:')
    nx.draw(G, pos, with_labels=True, node_color='white', edge_color='red', node_size=400, alpha=0.5)
    plt.show()



painting()

人太多 ,图炸啦。

接下来我只绘制重要人物的图

import pandas as pd
import numpy as np
file=pd.read_csv('earth_node.csv',encoding='gbk')#人物权重文件
file=file.dropna()

file1=pd.read_csv('earth_edge.csv',encoding='gbk')#人物关系文件
file1=file1.dropna()#去空白

#主要人物
namelist = ['郭啸天','杨铁心','冷笑','武功','包惜弱','那道人','郭靖','杨康','李萍','段天德','完颜洪烈',
                '柯镇恶','朱聪','韩宝驹','韩小莹','铁木真','梅超风','黄药师','尹志平','马钰','沙通天',
                '黄蓉','穆念慈','洪七公','周伯通','欧阳锋','裘千仞']
#人物权重
node_size=[]#no人物权重

for name in namelist :
    node_size.append(np.array(file.loc[file['Id'] == name, 'Weight'])[0])




import networkx as nx
from pylab import *
import matplotlib.pyplot as plt
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False

def painting(): #绘制人物亲密度图
    G = nx.Graph()  # 绘制个人物之间的亲密关系

    for index, row in file1.iterrows():
        if row['Source']  in namelist:
            G.add_node(row['Source'])  # 添加节点# 将当前人物添加进节点

    for index, row in file1.iterrows():
        if (row['Source']  in namelist) & (row['Target']  in namelist):
            #G.add_node(row['Source'], row['Target'])
            G.add_weighted_edges_from([(row['Source'], row['Target'], 10*np.array(row['Weight']))])#添加权重



    pos = nx.shell_layout(G)
    print('画出网络图像:')
    nx.draw(G, pos, with_labels=True, node_color=range(27), edge_color='red', node_size=node_size, alpha=0.5,width=[float(d['weight']*0.01) for (u,v,d) in G.edges(data=True)])

    plt.show()



painting()

郭靖和黄蓉果然是真爱。

分析
本次 还有些缺陷。
如郭靖和黄蓉之间还有些昵称。如靖哥哥,蓉儿,未统计进来。(主要是我懒,懒得写多余代码,使他们都映射到同一个名字。如把靖哥哥、郭大哥、郭靖 全部映射到郭靖。)
在这里插入图片描述
作者:电气余登武

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

总裁余(余登武)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值