Python实现《人民的名义》关系可视化

流程概述

  1. 在网上找到《人民的名义》剧本并下载
  2. 在网上查询《人民的名义》的一些主要人物,做一个人物字典
  3. 基于共现原理寻找人物关系
  4. 使用软件Gephi绘制关系图,将关系可视化

人物字典

在结巴分词中,人物姓名以标记”nr”来标志。

侯亮平 nr
李达康 nr 
达康  nr
沙瑞金 nr
沙书记 nr
高育良 nr
育良  nr
老师  nr
祁同伟 nr
陆亦可 nr
钟小艾 nr
高小琴 nr
吴惠芬 nr
欧阳菁 nr
赵瑞龙 nr
郑西坡 nr
赵东来 nr
梁璐  nr
季昌明 nr
程度  nr
丁义珍 nr
陈海  nr
赵德汉 nr
林华华 nr
周正  nr
陈岩石 nr
陈老 nr
刘新建 nr
蔡成功 nr
王馥真 nr
易学习 nr
田国福 nr
陈清泉 nr
刘姗  nr
陈群芳 nr
田杏枝 nr
张宝宝 nr
郑胜利 nr
孙连城 nr
肖钢玉 nr
吴心怡 nr
王大路 nr
秦局长 nr
周桂春 nr
王文革 nr
白处长 nr
孙海平 nr
毛娅  nr
张树立 nr
吴春林 nr
马文明 nr
金秘书 nr
侯浩然 nr
常成虎 nr
小皮球 nr
汤成兰 nr
李梁  nr
毕敬业 nr
何阿三 nr
张天峰 nr
尤瑞星 nr
陈文强 nr
杜伯仲 nr
美女老总 nr
老程 nr

基于人物共现的人物关系挖掘

我们假设两个人物在某一长度的文本中同时出现就认为这两个人物有关系,在这里我们选取这个长度为段落。即在同一段落中出现了两个不同的文本,即认为这两个人物有关系。

处理过程中的一些问题

  • 一些词汇如“林城”、“白云”、“吕州”等,它们的属性被归到了”nr”,而且出现次数较多,和一些人物共现次数较多,如果不做处理的话,它们将会出现在绘制的关系图中。在这里可以将这些词作为停用词梳理。
  • 一些人物之间常常会以亲密的词汇称呼对方,而且出现次数非常多,如果将这些词汇忽略,关系刻画可能会出现很大的偏差,如陈海和侯亮平之间的“猴子”,高育良和侯亮平、祁同伟之前的师生称呼。所以在分词之后,我们可以判断一下如果出现了这些亲密称呼,将其替代为他的姓名。

最终代码展示

# -*- encoding:utf-8 -*-
import jieba
import jieba.posseg as pseg
import codecs
import csv
stopwords=['吕州','林城','银行卡','明白','白云','嗡嗡嘤嘤',
           '阴云密布','雷声','陈大','谢谢您','安置费','任重道远',
           '孤鹰岭','阿庆嫂','岳飞','师生','养老院','段子','老总']
replace_words={'师母':'吴慧芬','陈老':'陈岩石','老赵':'赵德汉','达康':'李达康','高总':'高小琴',
              '猴子':'侯亮平','老郑':'郑西坡','小艾':'钟小艾','老师':'高育良','同伟':'祁同伟',
              '赵公子':'赵瑞龙','郑乾':'郑胜利','孙书记':'孙连城','赵总':'赵瑞龙','昌明':'季昌明',
               '沙书记':'沙瑞金','郑董':'郑胜利','宝宝':'张宝宝','小高':'高小凤','老高':'高育良',
               '伯仲':'杜伯仲','老杜':'杜伯仲','老肖':'肖钢玉','刘总':'刘新建',"美女老总":"高小琴"}
names={} #姓名字典
relationships ={} #关系字典
lineNames =[] #每段内人物的关系
node=[] #存放处理后的人物
def read_txt(path): #读取剧作并分词
    jieba.load_userdict("person.txt") #加载人物字典(注意这个文件要用utf-8编码,可以使用sublime进行转换为utf-8编码)
    f=codecs.open(path,'r') #读取剧作,并将其转换为utf-8编码
    for line in f.readlines():
        poss=pseg.cut(line)  #分词并返回该词词形
        lineNames.append([])  #为新读入的一段添加人物名称列表
        for w in poss:
            if w.word in stopwords:  #去掉某些停用词
                continue
            if w.flag != "nr" or len(w.word) <2 : 
                if w.word not in replace_words: 
                    continue
            if w.word in replace_words: #将某些在文中人物的昵称替换成正式的名字
                w.word=replace_words[w.word]
            lineNames[-1].append(w.word)  #为当前段增加一个人物
            if names.get(w.word) is None: #如果这个名字从来没出现过,初始化这个名字
                names[w.word] =0
                relationships[w.word] ={}
            names[w.word] +=1 #该人物出现次数加1
    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] +=1 #如果两个人已经出现过,则亲密度加1
def write_csv():
    # 在windows这种使用\r\n的系统里,不用newline=‘’的话
    # 会自动在行尾多添加个\r,导致多出一个空行,即行尾为\r\r\n
    csv_edge_file = open("edge.csv", "w", newline="")
    writer = csv.writer(csv_edge_file)
    writer.writerow(["source", "target", "weight","type"])  # 先写入列名,"type"为生成无向图做准备
    for name,edges in relationships.items():
        for v,w in edges.items():
            if w>20:
                node.append(name)
                writer.writerow((name,v,str(w),"undirected"))  # 按行写入数据
    csv_edge_file.close()
    #生成node文件
    s=set(node)
    csv_node_file =open("node.csv","w",newline="")
    wnode =csv.writer(csv_node_file)
    wnode.writerow(["ID","Label","Weight"])
    for name,times in names.items():
        if name in s:
            wnode.writerow((name,name,str(times) ) )
    csv_node_file.close()

if __name__=='__main__':
    file = "renmindemingyi.txt"
    edge_file="edge.txt"
    read_txt(file)
    write_csv()

绘制图片

将生成的文件导入软件Gephi,简单的操作方法可以参考下面的链接
gephi学习笔记

结果展示

Python实现《人民的名义》关系可视化_第1张图片

你可能感兴趣的:(python练习)