1. 程式人生 > >Python實現《人民的名義》關係視覺化

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學習筆記

結果展示

這裡寫圖片描述