专栏名称: 达观数据
达观数据是全球领先的文本智能处理专家,为企业提供完善的文本挖掘、知识图谱、搜索引擎和个性化推荐等大数据服务,是国内唯一一家将自动语义分析技术应用于企业数据化运营的人工智能公司。
目录
相关文章推荐
超级数学建模  ·  这是不花钱可以看的吗? ·  3 天前  
超级数学建模  ·  华为离职 “天才少年” 官宣刷屏 ·  3 天前  
51好读  ›  专栏  ›  达观数据

文本挖掘,带你看金庸笔下不一样的恩怨情仇

达观数据  · 公众号  ·  · 2018-11-20 18:06

正文



提起中国武侠小说,金庸先生是绕不开的名字,十余年间 以汪洋恣肆的想象力,写下15部作品。可用"飞雪连天射白鹿,笑书神侠倚碧鸳"来形容。


这些作品分别是《飞狐外传》(1960年)、《雪山飞狐》(1959年)、《连城诀》(1963年)、《天龙八部》(1963年)、《射雕英雄传》(1957年)、《白马啸西风》(1961年)、《鹿鼎记》(1969年)、《笑傲江湖》(1967年)、《书剑恩仇录》(1955年)、《神雕侠侣》(1959年)、《侠客行》(1965年)、《倚天屠龙记》(1961年)、《碧血剑》(1956年)《鸳鸯刀》(1961年)、《越女剑》(短篇小说)(1970年)。


本文使用Python对其15部小说展开分析,通过文本挖掘,为大家展示别样的江湖恩怨情仇。


数据获取

编写简单的爬虫程序获取金庸15本小说,并写入本地txt文件中。爬虫函数不在此展示。

文本处理

分别将小说的人物(names)、功夫(kungfu)、派别(bangs)写入txt文件中,并与小说放在同一个文件夹中。

file='D:/CuteHand/jr_novels/names.txt'   
#本地文件夹,根据需要修改
#可以使用os模块的添加路径
with open(file) as f:
    # 去掉结尾的换行符
    data = [line.strip() for line in 
             f.readlines()]
novels = data[::2]
names = data[1::2]
novel_names = {k: v.split() for k, v 
            in zip(novels, names)}

金庸小说充满恩怨情仇,其中,《倚天屠龙记》中张无忌一生遇到很多女人,如赵敏、周芷若、小昭、蛛儿、朱九真、杨不悔等,到底谁是女主角呢?我们来看下这几位美女在小说中分别出现的次数。

file='D:/CuteHand/jr_novels/倚天屠龙记.txt'
with open(file) as f:
        data = f.read()

Actress=['赵敏','周芷若','小昭','蛛儿',
        '朱九真','杨不悔']
for name in Actress:
    print("%s"% name,data.count(name))
赵敏 1240
周芷若 819
小昭 352
蛛儿 231
朱九真 141
杨不悔 190

将这几位美女在小说中出现的次数进行可视化,可以更直观地看出哪位才是张无忌的归属:

#可视化,重点在于学习使用matplotlib库画图
#导入需要的包  
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
%matplotlib inline
#画图正常显示中文
from pylab import mpl  
mpl.rcParams['font.sans-serif'] = ['SimHei'
# 用来正常显示中文标签 
mpl.rcParams['axes.unicode_minus']=False  
# 用来正常显示负号
actress_data = {'赵敏':1240,'周芷若'819,
                '小昭'352 ,'蛛儿'231
                '朱九真'141,'杨不悔'190}  
for a, b in actress_data.items():
    plt.text(a, b + 0.05'%.0f' % b, 
    ha='center', va='bottom', fontsize=12)  
    #ha 文字指定在柱体中间, 
    #va指定文字位置 
    #fontsize指定文字体大小
# 设置X轴Y轴数据,两者都可以是list或者tuple
x_axis = tuple(actress_data.keys())
y_axis = tuple(actress_data.values())
plt.bar(x_axis, y_axis, color='rgbyck')  
# 如果不指定color,所有的柱体都会是一个颜色
#b: blue g: green r: red c: cyan
#m: magenta y: yellow k: black w: white
plt.xlabel("女角名")  # 指定x轴描述信息
plt.ylabel("小说中出现次数")  # 指定y轴描述信息
plt.title("谁是女主角?")  # 指定图表描述信息
plt.ylim(01400)  # 指定Y轴的高度
plt.show()

众所周知,张无忌最终和赵敏在一起了,而与周芷若之间很是坎坷…;小昭挺喜欢的角色,可惜被不可抗拒的外力给分开了;蛛儿,暂且说是女方单恋吧;朱九真只是过客,不过也算是张无忌情窦初开喜欢的一个;杨不悔只能说是玩伴。

文本挖掘

接下来,通过分析小说人物的出场次数来判断小说的主要人物。

#继续挖掘下倚天屠龙记里面人物出现次数排名
namelist=[name.strip() for name in 
         novel_names['倚天屠龙记']]
namelist=''.join(namelist)
namelist=namelist.split('、')
count = []
num=10 #统计前10名

for name in namelist:
    count.append([name, data.count(name)])
count.sort(key=lambda x: x[1])
_, ax = plt.subplots()
numbers = [x[1for x in count[-num:]]
names = [x[0for x in count[-num:]]
ax.barh(range(num), numbers, align='center')
ax.set_title('倚天屠龙记', fontsize=14)
ax.set_yticks(range(num))
ax.set_yticklabels(names, fontsize=10)
plt.show()

网上收集了下金庸小说的功夫和门派种类,分别写入kungfu.txt和bangs.txt中,其中武功246种,门派120个。

#加入功夫和门派数据
file='D:/CuteHand/jr_novels/'
with open(file+"kungfu.txt"as f:
    kungfu_names = [line.strip() 
        for line in f.readlines()]
with open(file+"bangs.txt"as f:
    bang_names = [line.strip() 
        for line in f.readlines()]

#编写文本挖掘可视化函数
#寻找小说出现最多的十大人物
def find_main_characters(novel):
    file='D:/CuteHand/jr_novels/'
    with open(file+'names.txt'as f:
        df = [line.strip() for 
              line in f.readlines()]
    novels = df[::2]
    names = df[1::2]
    novel_names = {k: v.split() for 
          k, v in zip(novels, names)}
    with  open(file+'{}.txt'.format(novel)) as f:
        data = f.read()
    count = []
    namelist=[name.strip() for name 
         in novel_names[novel]]
    namelist=''.join(namelist)
    namelist=namelist.split('、')
    for name in namelist:
        count.append([name, data.count(name)])
    count.sort(key=lambda x: x[1])
    _, ax = plt.subplots()
    num=10
    numbers = [x[1for x in count[-num:]]
    names = [x[0for x in count[-num:]]
    ax.barh(range(num), numbers, align='center'
    ax.set_title(novel+"出现最多的十大人物",
            fontsize=16)
    ax.set_yticks(range(num))
    ax.set_yticklabels(names, fontsize=14)
#寻找小说出现最多的十大武功
def kungfu(novel):
    file='D:/CuteHand/jr_novels/'
    with open(file+'{}.txt'.format(novel)) as f:
        df = f.read()
    namelist=kungfu_names
    count = []
    num=10 #统计前10名

    for name in namelist:
        count.append([name, df.count(name)])
    count.sort(key=lambda x: x[1])
    _, ax = plt.subplots()
    numbers = [x[1for x in count[-num:]]
    names = [x[0for x in count[-num:]]
    ax.barh(range(num), numbers, align='center')
    ax.set_title(novel+"出现最多的十大武功"
           fontsize=16)
    ax.set_yticks(range(num))
    ax.set_yticklabels(names, fontsize=14)
#寻找小说出现最多的十大门派
def bang(novel):
    file='D:/CuteHand/jr_novels/'
    with open(file+'{}.txt'.format(novel)) as f:
        df = f.read()
    namelist=bang_names
    count = []
    num=10 #统计前10名

    for name in namelist:
        count.append([name, df.count(name)])
    count.sort(key=lambda x: x[1])
    _, ax = plt.subplots()
    numbers = [x[1for x in count[-num:]]
    names = [x[0for x in count[-num:]]
    ax.barh(range(num), numbers, align='center')
    ax.set_title(novel+"出现最多的十大门派"
            fontsize=16)
    ax.set_yticks(range(num))
    ax.set_yticklabels(names, fontsize=14)
#将三个函数合成一个主函数
def main(novel):
    find_main_characters(novel)
    bang(novel)
    kungfu(novel)
main('倚天屠龙记')

main('天龙八部')




main('神雕侠侣')


main('笑傲江湖')


寻找人物关系

使用gensim和jieba包对文本做进一步挖掘,寻找人物之间的关系。一般要先安装相应的包,只要在Anaconda Prompt上输入pip install gensim和pip install jieba进行安装即可。

import gensim
import warnings
warnings.filterwarnings(action='ignore',
  category=UserWarning,module='gensim')
warnings.filterwarnings(action='ignore',
  category=FutureWarning,module='gensim')
import jieba
for _, names in novel_names.items():
    for name in names:
        jieba.add_word(name)
file='D:/CuteHand/jr_novels/'
with open(file+"kungfu.txt"as f:
    kungfu_names = [line.strip() 
         for line in f.readlines()]
with open(file+"bangs.txt"as f:
    bang_names = [line.strip() 
         for line in f.readlines()]

for name in kungfu_names:
    jieba.add_word(name)

for name in bang_names:
    jieba.add_word(name)
books = ['天龙八部','鹿鼎记','神雕侠侣','笑傲江湖',
     '碧血剑','倚天屠龙记','飞狐外传'






请到「今天看啥」查看全文