如何用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多线程同步Lock、RLock、Semaphore、Event实例
Nov 21 Python
Python中用函数作为返回值和实现闭包的教程
Apr 27 Python
浅谈使用Python内置函数getattr实现分发模式
Jan 22 Python
python中使用xlrd读excel使用xlwt写excel的实例代码
Jan 31 Python
Python学习小技巧总结
Jun 10 Python
Python中利用aiohttp制作异步爬虫及简单应用
Nov 29 Python
Python写捕鱼达人的游戏实现
Mar 31 Python
学python最电脑配置有要求么
Jul 05 Python
Python如何合并多个字典或映射
Jul 24 Python
Python爬虫抓取论坛关键字过程解析
Oct 19 Python
python爬虫中抓取指数的实例讲解
Dec 01 Python
Opencv 图片的OCR识别的实战示例
Mar 02 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
什么是调频(FM)、调幅(AM)、短波(SW)、长波(LW)
2021/03/01 无线电
PHP编码转换
2012/11/05 PHP
修改Laravel5.3中的路由文件与路径
2016/08/10 PHP
PHP标准库 (SPL)――Countable用法示例
2020/06/05 PHP
JavaScript监测ActiveX控件是否已经安装过的代码
2008/09/02 Javascript
Javascript学习笔记2 函数
2010/01/11 Javascript
IE6-8中Date不支持toISOString的修复方法
2014/05/04 Javascript
node.js中的fs.exists方法使用说明
2014/12/17 Javascript
jquery中one()方法的用法实例
2015/01/16 Javascript
js由下向上不断上升冒气泡效果实例
2015/05/07 Javascript
js实现微信分享代码
2020/10/11 Javascript
基于jquery实现表格无刷新分页
2016/01/07 Javascript
Javascript Function.prototype.bind详细分析
2016/12/29 Javascript
JS异步文件上传(兼容IE8+)
2017/04/02 Javascript
详解node+express+ejs+bootstrap构建项目
2017/09/27 Javascript
详解webpack之scss和postcss-loader的配置
2018/01/09 Javascript
JavaScript 有用的代码片段和 trick
2018/02/22 Javascript
Element Input输入框的使用方法
2020/07/26 Javascript
vue 将多个过滤器封装到一个文件中的代码详解
2020/09/05 Javascript
使用Python编写提取日志中的中文的脚本的方法
2015/04/30 Python
python命令行解析之parse_known_args()函数和parse_args()使用区别介绍
2018/01/24 Python
python合并同类型excel表格的方法
2018/04/01 Python
Python图像处理之图像的读取、显示与保存操作【测试可用】
2019/01/04 Python
python绘制地震散点图
2019/06/18 Python
浅谈CSS3特性查询(Feature Query: @supports)功能简介
2017/07/31 HTML / CSS
蔻驰美国官网:COACH美国
2016/08/18 全球购物
世界上最大的糖果店:Dylan’s Candy Bar
2017/11/07 全球购物
Java的for语句中break, continue和return的区别
2013/12/19 面试题
中秋节超市促销方案
2014/01/30 职场文书
财务负责人任命书
2014/06/06 职场文书
2015年行政工作总结范文
2015/04/09 职场文书
英语导游欢迎词
2015/09/30 职场文书
浪漫婚礼主持词开场白
2015/11/24 职场文书
学前班教学反思
2016/02/24 职场文书
2016年学校党支部公开承诺书
2016/03/25 职场文书
Python可变集合和不可变集合的构造方法大全
2021/12/06 Python