如何用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计算牛顿迭代多项式实例分析
May 07 Python
总结用Pdb库调试Python的方式及常用的命令
Aug 18 Python
python通过getopt模块如何获取执行的命令参数详解
Dec 29 Python
Python中enumerate()函数编写更Pythonic的循环
Mar 06 Python
python+selenium实现QQ邮箱自动发送功能
Jan 23 Python
python实现比较类的两个instance(对象)是否相等的方法分析
Jun 26 Python
python统计指定目录内文件的代码行数
Sep 19 Python
Python生成验证码、计算具体日期是一年中的第几天实例代码详解
Oct 16 Python
python打印直角三角形与等腰三角形实例代码
Oct 20 Python
python退出循环的方法
Jun 18 Python
Python 抓取数据存储到Redis中的操作
Jul 16 Python
python 装饰器的使用示例
Oct 10 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获得文件大小和文件创建时间的方法
2015/03/13 PHP
启用Csrf后POST数据时出现的400错误
2015/07/05 PHP
AJAX的使用方法详解
2017/04/29 PHP
PHP反射基础知识回顾
2020/09/10 PHP
jQuery动态设置form表单的enctype值(实现代码)
2013/07/04 Javascript
Ajax同步与异步传输的示例代码
2013/11/21 Javascript
jQuery实现列表自动滚动循环滚动展示新闻
2014/08/22 Javascript
jQuery中:empty选择器用法实例
2014/12/30 Javascript
jQuery表单域选择器用法分析
2015/02/10 Javascript
在JavaScript中使用对数Math.log()方法的教程
2015/06/15 Javascript
getElementById().innerHTML与getElementById().value的区别
2016/10/27 Javascript
JavaScript触发onScroll事件的函数节流详解
2016/12/14 Javascript
JavaScript注册时密码强度校验代码
2017/06/30 Javascript
Angular17之Angular自定义指令详解
2018/01/21 Javascript
React Native自定义控件底部抽屉菜单的示例
2018/02/08 Javascript
泛谈JS逻辑判断选择器 || &&
2019/05/24 Javascript
vue实现购物车案例
2020/05/30 Javascript
python OpenCV学习笔记直方图反向投影的实现
2018/02/07 Python
详解django+django-celery+celery的整合实战
2019/03/19 Python
Python OS模块实例详解
2019/04/15 Python
PyQt5实现简易电子词典
2019/06/25 Python
Python生态圈图像格式转换问题(推荐)
2019/12/02 Python
html5实现微信打飞机游戏
2014/03/27 HTML / CSS
移动HTML5前端框架—MUI的使用
2017/12/18 HTML / CSS
Europcar葡萄牙:葡萄牙汽车和货车租赁
2017/10/13 全球购物
英国独特的时尚和生活方式品牌:JOY
2018/03/17 全球购物
美国最大的在线水培用品商店:GrowersHouse.com
2018/08/14 全球购物
全球高级音频和视频专家:HiDef Lifestyle
2019/08/02 全球购物
MATCHESFASHION澳大利亚/亚太地区:英国时尚奢侈品电商
2020/01/14 全球购物
集中整治工作方案
2014/05/01 职场文书
销售员岗位职责
2014/06/09 职场文书
2014年超市员工工作总结
2014/11/18 职场文书
2015年禁毒宣传活动总结
2015/03/25 职场文书
2015暑期社会实践调查报告
2015/07/14 职场文书
2016年六一儿童节开幕词
2016/03/04 职场文书
Redis持久化与主从复制的实践
2021/04/27 Redis