如何用Python來理一理紅樓夢裏的那些關係

這篇文章主要介紹了用Python來理一理紅樓夢裏的那些關係代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

前言

今天,一起用 Python 來理一理紅樓夢裏的那些關係

不要問我爲啥是紅樓夢,而不是水滸三國或西遊,因爲我也鑑定的認爲,紅樓纔是無可爭議的中國古典小說只巔峯,且不接受反駁!而紅樓夢也是我多次反覆品讀的爲數不多的小說,對它的感情也是最深的。

好了,不酸了,開幹。

數據準備

紅樓夢 TXT 文件一份

金陵十二釵 + 賈寶玉 人物名稱列表

人物列表內容如下:

寶玉 nr
黛玉 nr
寶釵 nr
湘雲 nr
鳳姐 nr
李紈 nr
元春 nr
迎春 nr
探春 nr
惜春 nr
妙玉 nr
巧姐 nr
秦氏 nr

這份列表,同時也是爲了做分詞時使用,後面的 nr 就是人名的意思。

數據處理

讀取數據並加載詞典

  with open("紅樓夢.txt", encoding='gb18030') as f:
    honglou = f.readlines()
  jieba.load_userdict("renwu_forcut")
  renwu_data = pd.read_csv("renwu_forcut", header=-1)
  mylist = [k[0].split(" ")[0] for k in renwu_data.values.tolist()]

這樣,我們就把紅樓夢讀取到了 honglou 這個變量當中,同時也通過 load_userdict 將我們自定義的詞典加載到了 jieba 庫中。

對文本進行分詞處理並提取

tmpNames = []
  names = {}
  relationships = {}
  for h in honglou:
    h.replace("賈妃", "元春")
    h.replace("李宮裁", "李紈")
    poss = pseg.cut(h)
    tmpNames.append([])
    for w in poss:
      if w.flag != 'nr' or len(w.word) != 2 or w.word not in mylist:
        continue
      tmpNames[-1].append(w.word)
      if names.get(w.word) is None:
        names[w.word] = 0
      relationships[w.word] = {}
      names[w.word] += 1
  • 首先,因爲文中"賈妃", "元春","李宮裁", "李紈" 混用嚴重,所以這裏直接做替換處理。
  • 然後使用 jieba 庫提供的 pseg 工具來做分詞處理,會返回每個分詞的詞性。
  • 之後做判斷,只有符合要求且在我們提供的字典列表裏的分詞,纔會保留。
  • 一個人每出現一次,就會增加一,方便後面畫關係圖時,人物 node 大小的確定。
  • 對於存在於我們自定義詞典的人名,保存到一個臨時變量當中 tmpNames。

處理人物關係

  for name in tmpNames:
    for name1 in name:
      for name2 in name:
        if name1 == name2:
          continue
        if relationships[name1].get(name2) is None:
          relationships[name1][name2] = 1
        else:
          relationships[name1][name2] += 1

對於出現在同一個段落中的人物,我們認爲他們是關係緊密的,每同時出現一次,關係增加1.

保存到文件

  with open("relationship.csv", "w", encoding='utf-8') as f:
    f.write("Source,Target,Weight\n")
    for name, edges in relationships.items():
      for v, w in edges.items():
        f.write(name + "," + v + "," + str(w) + "\n")

  with open("NameNode.csv", "w", encoding='utf-8') as f:
    f.write("ID,Label,Weight\n")
    for name, times in names.items():
      f.write(name + "," + name + "," + str(times) + "\n")
  • 文件1:人物關係表,包含首先出現的人物、之後出現的人物和一同出現次數
  • 文件2:人物比重表,包含該人物總體出現次數,出現次數越多,認爲所佔比重越大。

製作關係圖表

使用 pyecharts 作圖

def deal_graph():
  relationship_data = pd.read_csv('relationship.csv')
  namenode_data = pd.read_csv('NameNode.csv')
  relationship_data_list = relationship_data.values.tolist()
  namenode_data_list = namenode_data.values.tolist()

  nodes = []
  for node in namenode_data_list:
    if node[0] == "寶玉":
      node[2] = node[2]/3
    nodes.append({"name": node[0], "symbolSize": node[2]/30})
  links = []
  for link in relationship_data_list:
    links.append({"source": link[0], "target": link[1], "value": link[2]})

  g = (
    Graph()
    .add("", nodes, links, repulsion=8000)
    .set_global_opts(title_opts=opts.TitleOpts(title="紅樓人物關係"))
  )
  return g

首先把兩個文件讀取成列表形式

對於“寶玉”,由於其佔比過大,如果統一進行縮放,會導致其他人物的 node 過小,展示不美觀,所以這裏先做了一次縮放

最後得出的關係圖

所有代碼已經上傳至 Github

最後,我還準備了一份更加全面的紅樓人物字典,可以在代碼倉庫中找到-“renwu_total”,感興趣的小夥伴也可以嘗試下,製作一個全人物的關係圖。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持神馬文庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章