如何用Python来理一理红楼梦里的那些关系


Posted in Python onAugust 14, 2019

前言

今天,一起用 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 过小,展示不美观,所以这里先做了一次缩放

最后得出的关系图

如何用Python来理一理红楼梦里的那些关系

所有代码已经上传至 Github

最后,我还准备了一份更加全面的红楼人物字典,可以在代码仓库中找到-“renwu_total”,感兴趣的小伙伴也可以尝试下,制作一个全人物的关系图。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python内置的字符串处理函数整理
Jan 29 Python
Python文件夹与文件的操作实现代码
Jul 13 Python
Python入门学习之字符串与比较运算符
Oct 12 Python
win系统下为Python3.5安装flask-mongoengine 库
Dec 20 Python
用TensorFlow实现lasso回归和岭回归算法的示例
May 02 Python
搞定这套Python爬虫面试题(面试会so easy)
Apr 03 Python
Python序列化与反序列化pickle用法实例
Nov 11 Python
Tensorflow累加的实现案例
Feb 05 Python
python实现控制台输出彩色字体
Apr 05 Python
Python Socket编程详解
Apr 25 Python
python opencv通过4坐标剪裁图片
Jun 05 Python
浅谈Python从全局与局部变量到装饰器的相关知识
Jun 21 Python
django之自定义软删除Model的方法
Aug 14 #Python
python实现登录密码重置简易操作代码
Aug 14 #Python
python 定时器每天就执行一次的实现代码
Aug 14 #Python
Django 项目重命名的实现步骤解析
Aug 14 #Python
Django如何实现网站注册用户邮箱验证功能
Aug 14 #Python
python 叠加等边三角形的绘制的实现
Aug 14 #Python
Django为窗体加上防机器人的验证码功能过程解析
Aug 14 #Python
You might like
ob_start(),ob_start('ob_gzhandler')使用
2006/12/25 PHP
php中ob(Output Buffer 输出缓冲)函数使用方法
2007/07/21 PHP
php中文乱码问题的终极解决方案汇总
2017/08/01 PHP
CakePHP框架Model函数定义方法示例
2017/08/04 PHP
JavaScript事件列表解说
2006/12/22 Javascript
理解Javascript_09_Function与Object
2010/10/16 Javascript
jQuery之折叠面板的深入解析
2013/06/19 Javascript
Javascript中的五种数据类型详解
2014/12/26 Javascript
jquery实现具有嵌套功能的选项卡
2016/02/12 Javascript
js类式继承与原型式继承详解
2016/04/07 Javascript
详解jQuery简单的表单应用
2016/12/16 Javascript
Bootstrap下拉菜单Dropdowns的实现代码
2017/03/17 Javascript
Vue表单验证插件Vue Validator使用方法详解
2017/04/07 Javascript
angularJs中datatable实现代码
2017/06/03 Javascript
Node.js学习教程之HTTP/2服务器推送【译】
2017/10/31 Javascript
jQuery HTML css()方法与css类实例详解
2020/05/20 jQuery
python的id()函数解密过程
2012/12/25 Python
pandas 将索引值相加的方法
2018/11/15 Python
在python中以相同顺序shuffle两个list的方法
2018/12/13 Python
Django框架模板的使用方法示例
2019/05/25 Python
深入学习python多线程与GIL
2019/08/26 Python
Pytorch GPU显存充足却显示out of memory的解决方式
2020/01/13 Python
jupyter lab文件导出/下载方式
2020/04/22 Python
Python第三方库安装缓慢的解决方法
2021/02/06 Python
Internet主要有哪些网络群组成
2015/12/24 面试题
消防应急演练方案
2014/02/12 职场文书
《挑山工》的教学反思
2014/02/16 职场文书
平安建设工作方案
2014/06/02 职场文书
2014年党员教师自我剖析材料
2014/09/30 职场文书
2014年组织部工作总结
2014/11/14 职场文书
庆祝教师节活动总结
2015/03/23 职场文书
自主招生自荐信格式范文
2015/03/25 职场文书
医院见习总结
2015/06/24 职场文书
Go语言-为什么返回值为接口类型,却返回结构体
2021/04/24 Golang
springcloud整合seata
2022/05/20 Java/Android
win server2012 r2服务器共享文件夹如何设置
2022/06/21 Servers