如何用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中的闭包
Aug 11 Python
python定时利用QQ邮件发送天气预报的实例
Nov 17 Python
tensorflow输出权重值和偏差的方法
Feb 10 Python
Python用for循环实现九九乘法表
May 31 Python
Python3中lambda表达式与函数式编程讲解
Jan 14 Python
django框架CSRF防护原理与用法分析
Jul 22 Python
python中bs4.BeautifulSoup的基本用法
Jul 27 Python
python中自带的三个装饰器的实现
Nov 08 Python
Python 词典(Dict) 加载与保存示例
Dec 06 Python
Python使用matplotlib绘制圆形代码实例
May 27 Python
python 如何用urllib与服务端交互(发送和接收数据)
Mar 04 Python
2021年最新用于图像处理的Python库总结
Jun 15 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
星际争霸教主Flash的ID由来:你永远不会知道他之前的ID是www!
2019/01/18 星际争霸
解决phpmyadmin中缺少mysqli扩展问题的方法
2013/05/06 PHP
destoon公司主页模板风格的添加方法
2014/06/20 PHP
smarty内部日期函数html_select_date()用法实例分析
2015/07/08 PHP
整理php防注入和XSS攻击通用过滤
2015/09/13 PHP
php上传图片并压缩的实现方法
2015/12/22 PHP
PHP获取不了React Native Fecth参数的解决办法
2016/08/26 PHP
js 分页全选或反选标识实现代码
2011/08/09 Javascript
JS获取地址栏参数的几种方法小结
2014/02/28 Javascript
JS获取单击按钮单元格所在行的信息
2014/06/17 Javascript
JS简单封装的图片无缝滚动效果示例【测试可用】
2017/03/22 Javascript
JavaScript之underscore_动力节点Java学院整理
2017/07/03 Javascript
详解小程序退出页面时清除定时器
2019/04/28 Javascript
JS前端知识点offset,scroll,client,冒泡,事件对象的应用整理总结
2019/06/27 Javascript
[02:39]我与DAC之Newbee.Moogy:从论坛到TI
2018/03/26 DOTA
[00:32]2018DOTA2亚洲邀请赛Secret出场
2018/04/03 DOTA
Python中模拟enum枚举类型的5种方法分享
2014/11/22 Python
python计算圆周率pi的方法
2015/07/11 Python
Python 利用pydub库操作音频文件的方法
2019/01/09 Python
在Pycharm中调试Django项目程序的操作方法
2019/07/17 Python
Pytorch中accuracy和loss的计算知识点总结
2019/09/10 Python
python 单线程和异步协程工作方式解析
2019/09/28 Python
keras多显卡训练方式
2020/06/10 Python
英国虚拟主机服务商:eUKhost
2016/08/16 全球购物
ASP.NET中的身份验证有那些
2012/07/13 面试题
员工考核管理制度
2014/02/02 职场文书
读书活动实施方案
2014/03/10 职场文书
仓库规划计划书
2014/04/28 职场文书
局火灾防控工作方案
2014/05/25 职场文书
青年文明号汇报材料
2014/12/23 职场文书
2015年学校体育工作总结
2015/04/22 职场文书
2015国庆节宣传语
2015/07/14 职场文书
2016大学生诚信考试承诺书
2016/03/25 职场文书
python 实现体质指数BMI计算
2021/05/26 Python
python实现简易自习室座位预约系统
2021/06/30 Python
java泛型通配符详解
2021/07/25 Java/Android