如何用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实现的批量下载RFC文档
Mar 10 Python
简单了解python模块概念
Jan 11 Python
django文档学习之applications使用详解
Jan 29 Python
pandas 根据列的值选取所有行的示例
Nov 07 Python
python将处理好的图像保存到指定目录下的方法
Jan 10 Python
Python从文件中读取数据的方法讲解
Feb 14 Python
Python批量查询关键词微信指数实例方法
Jun 27 Python
Python 、Pycharm、Anaconda三者的区别与联系、安装过程及注意事项
Oct 11 Python
python为什么会环境变量设置不成功
Jun 23 Python
Python分类测试代码实例汇总
Jul 23 Python
python使用matplotlib:subplot绘制多个子图的示例
Sep 24 Python
python如何将mat文件转为png
Jul 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
PHP内置过滤器FILTER使用实例
2014/06/25 PHP
PHP+Ajax实现验证码的实时验证
2016/07/20 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
2018/06/16 PHP
js 获取中文拼音,Select自动匹配字母获取值的代码
2009/09/23 Javascript
jQuery 选择器、DOM操作、事件、动画
2010/11/25 Javascript
js制作的鼠标悬浮时产生的下拉框效果
2012/10/27 Javascript
jquery ztree实现下拉树形框使用到了json数据
2014/05/14 Javascript
webpack中引用jquery的简单实现
2016/06/08 Javascript
巧方法 JavaScript获取超链接的绝对URL地址
2016/06/14 Javascript
jQuery仿IOS弹出框插件
2017/02/18 Javascript
JavaScript登录记住密码操作(超简单代码)
2017/03/22 Javascript
解决bootstrap中使用modal加载kindeditor时弹出层文本框不能输入的问题
2017/06/05 Javascript
分享Bootstrap简单表格、表单、登录页面
2017/08/04 Javascript
详解Nuxt.js Vue服务端渲染摸索
2018/02/08 Javascript
详解webpack运行Babel教程
2018/06/13 Javascript
Django+Vue跨域环境配置详解
2018/07/06 Javascript
vue src动态加载请求获取图片的方法
2018/10/17 Javascript
详解Node.js 中使用 ECDSA 签名遇到的坑
2018/11/26 Javascript
JavaScript学习笔记之数组基本操作示例
2019/01/09 Javascript
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
2019/04/26 Javascript
JS中使用react-tooltip插件实现鼠标悬浮显示框
2019/05/15 Javascript
Vue项目总结之webpack常规打包优化方案
2019/06/06 Javascript
一文看懂如何简单实现节流函数和防抖函数
2019/09/05 Javascript
js编写简易的计算器
2020/07/29 Javascript
[40:50]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第四场
2014/05/24 DOTA
[51:26]VP vs VG 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python类定义和类继承详解
2015/05/08 Python
用Eclipse写python程序
2018/02/10 Python
解决Ubuntu pip 安装 mysql-python包出错的问题
2018/06/11 Python
将Dataframe数据转化为ndarry数据的方法
2018/06/28 Python
浅谈python图片处理Image和skimage的区别
2019/08/04 Python
Python unittest单元测试openpyxl实现过程解析
2020/05/27 Python
NBA欧洲商店(西班牙):NBA Europe Store ES
2019/04/16 全球购物
2014购房个人委托书范本
2014/10/12 职场文书
单位提档介绍信
2015/10/22 职场文书
如何书写邀请函?
2019/06/24 职场文书