Python爬虫之九阴真经

Python058

Python爬虫之九阴真经,第1张

用Python 探索 金庸笔下的江湖!

带你用python看小说, 娱乐 学习两不误。

涉及的知识点有:

本文从传统匹配逻辑分析过渡到机器学习的词向量,全方位进行文本分析,值得学习,干货满满。( 文末点击阅读原文 )

以前金庸小说的网站有很多,但大部分已经无法访问,但由于很多金庸迷的存在,新站也是源源不断出现。我近期通过百度找到的一个还可以访问的金庸小说网址是: aHR0cDovL2ppbnlvbmcxMjMuY29tLw==

不过我已经准备好已经采集完成的数据,大家可以直接下载数据,跳过本章的内容。

数据源下载地址:https://gitcode.net/as604049322/blog_data

下面首先获取这15部作品的名称、创作年份和对应的链接。从开发者工具可以看到每行的a标签很多,我们需要的节点的特征在于后续临近节点紧接着一个创作日期的字符串:

那么我们就可以通过遍历所有的a标签并判断其后续一个临近节点的内容是否符合日期格式,最终完整下载代码为:

可以按照创作日期排序查看:

名称创作时间网址 书剑恩仇录1955年/shujianenchoulu/ 碧血剑1956年/bixuejian/ 射雕英雄传1957—1959年/shediaoyingxiongzhuan/ 神雕侠侣1959—1961年/shendiaoxialv/ 雪山飞狐1959年/xueshanfeihu/ 飞狐外传1960—1961年/feihuwaizhuan/ 白马啸西风1961年/baimaxiaoxifeng/ 倚天屠龙记1961年/yitiantulongji/ 鸳鸯刀1961年/yuanyangdao/ 天龙八部1963—1966年/tianlongbabu/ 连城诀1963年/lianchengjue/ 侠客行1965年/xiakexing/ 笑傲江湖1967年/xiaoaojianghu/ 鹿鼎记1969—1972年/ludingji/ 越女剑1970年/yuenvjian/

下面看看章节页节点的分布情况,以《雪山飞狐》为例:

同时可以看到部分小说的节点出现了倒序的情况,我们需要在识别出倒序时将其正序,完整代码:

测试一下:

可以看到章节已经顺利的正序排列。

小说每一章的详细页最后一行的数据我们不需要:

下载每章内容的代码:

然后我们就可以批量下载全部小说了:

为了更好分析金庸小说,我们还需要采集金庸小说的人物、武功门派,个人并没有找到还可以访问相关数据的网站,于是自行收集整理了相关数据:

相关数据都以如下格式存储,例如金庸小说的人物:

武功:

数据源下载地址:https://gitcode.net/as604049322/blog_data

定义一个加载小说的方法:

首先我们加载人物数据:

可以预览一下天龙八部中的人物:

下面我们寻找一下每部小说的主角,统计每个人物的出场次数,显然次数越多主角光环越强,下面我们看看每部小说,出现次数最多的前十个人物:

上述结果用文本展示了每部小说的前5个主角,但是不够直观,下面我用pyecharts的树图展示一下:

显然,《神雕侠侣》中的杨过和小龙女,《天龙八部》中的萧(乔)峰,段誉,虚竹,《射雕英雄传》的郭靖和黄蓉,《倚天屠龙记》的张无忌和赵敏 都是主角光环最强的角色。

使用上述相同的方法,分析各种武功的出现频次,首先加载武功数据:

定义计数方法:

每部小说频次前5的武功可视化:

门派分析

加载数据并获取每部小说前10的门派:

可视化:

还可以测试一下树形图:

综合统计

下面我们编写一个函数,输入一部小说名,可以输出其最高频的主角、武功和门派:

例如查看天龙八部:

词云图分析

可以先添加所有的人物、武功和门派作为自定义词汇:

这里我们仅提取词长度不小于4的成语、俗语和短语进行分析,以天龙八部这部小说为例:

修改上述代码,查看《射雕英雄传》:

神雕侠侣:

主角相关剧情词云

我们知道《神雕侠侣》这部小说最重要的主角是杨过和小龙女,我们可能会对于杨过和小龙女之间所发生的故事很感兴趣。如果通过程序快速了解呢?

我们考虑把《神雕侠侣》这部小说每一段中出现杨过及小龙女的段落进行jieba分词并制作词云。

同样我们只看4个字以上的词:

这里的每一个词都能联想到发生在杨过和小龙女背后的一个故事。

同样的思路看看郭靖和黄蓉:

最后我们看看天龙八部的三兄弟相关的词云:

关系图分析

金庸小说15部小说中预计出现了1400个以上的角色,下面我们将遍历小说的每一段,在一段中出现的任意两个角色,都计数1。最终我们取出现频次最高的前200个关系对进行可视化。

完整代码如下:

这次我们生成了HTML文件是为了更方便的查看结果,前200个人物的关系情况如下:

门派关系分析

按照相同的方法分析所有小说的门派关系:

Word2Vec分析

Word2Vec 是一款将词表征为实数值向量的高效工具,接下来,我们将使用它来处理这些小说。

gensim 包提供了一个 Python 版的实现。

之前我有使用 gensim 包进行了相似文本的匹配,有兴趣可查阅:《批量模糊匹配的三种方法》

首先我要将所有小说的段落分词后添加到组织到一起(前面的程序可以重启):

接下面我们使用Word2Vec训练模型:

我这边模型训练耗时15秒,若训练耗时较长可以把训练好的模型存到本地:

以后可以直接从本地磁盘读取模型:

有了模型,我们可以进行一些简单而有趣的测试。

首先看与乔(萧)峰相似的角色:

再看看与阿朱相似的角色:

除了角色,我们还可以看看门派:

还可以看看与降龙十八掌相似的武功秘籍:

在 Word2Vec 的模型里,有过“中国-北京=法国-巴黎”的例子,我们看看"段誉"和"段公子"类似于乔峰和什么的关系呢?

类似的还有:

查看韦小宝相关的关系:

门派武功之间的关系:

之前我们使用 Word2Vec 将每个词映射到了一个向量空间,因此,我们可以利用这个向量表示的空间,对这些词进行聚类分析。

首先取出所有角色对应的向量空间:

聚类算法有很多,这里我们使用基本的Kmeans算法进行聚类,如果只分成3类,那么很明显地可以将众人分成主角,配角,跑龙套的三类:

我们可以根据每个类别的角色数量的相对大小,判断该类别的角色是属于主角,配角还是跑龙套。

下面我们过滤掉众龙套角色之后,重新聚合成四类:

每次运行结果都不一样,大家可以调整类别数量继续测试。从结果可以看到,反派更倾向于被聚合到一起,非正常姓名的人物更倾向于被聚合在一起,主角更倾向于被聚合在一起。

现在我们采用层级聚类的方式,查看人物间的层次关系,这里同样龙套角色不再参与聚类。

层级聚类调用 scipy.cluster.hierarchy 中层级聚类的包,在此之前先解决matplotlib中文乱码问题:

接下来调用代码为:

然后我们可以得到金庸小说宇宙的人物层次关系地图,结果较长仅展示一部分结果:

当然所有小说混合产生的平行宇宙中,人物关系变得有些混乱,读者有兴趣可以拿单本小说作层次分析,就可以得到较为准确的人物层次关系。

对各种武功作与人物层次聚类相同的操作:

结果较长,仅展示部分结果:

可以看到,比较少的黄色部分明显是主角比较厉害的武功,而绿色比较多的部分基本都是配角的武功。

最后我们对门派进行层次聚类:

比较少的这一类,基本都是在某几部小说中出现的主要门派,而大多数门派都是打酱油的。

本文从金庸小说数据的采集,到普通的频次分析、剧情分析、关系分析,再到使用词向量空间分析相似关系,最后使用scipy进行所有小说的各种层次聚类。

前几文主要讲的是如何处理Xarray中的DataArray和DataSet,现在分享一下如何从nc文件或其他文件中读取数据,以及如何将处理好的数据输出成一个nc文件。

首先还是要再强调DataArray和DataSet的区别,DataArray是一个带标签结构的数组,DataSet是一个数据集,这意味着,从一个nc文件中读取到的全部信息构成了一个DataSet,而nc文件中的某一个变量是一个DataArray。

反之,我们要将一个数据写成nc文件,那么就是要创建一个DataSet。

这个数据结构有点像站点数据,对xy维设定了两层,分别是经纬度,还有一维时间维(whatever,反正是随便创建一个DataSet)。

就可以输出成nc文件了。

当然还可以更懒一点,

直接将abc这个DataArray转成DataSet,DataArray的标签和纬度信息会自动转换。

之后使用to_netcdf即可。

读取的语句也十分简单。

函数只需要基本的路径及文件名,无需像NCL一样声明状态'r'。

Xarray读取多文件也提供了相应函数(我目前没有使用过,我通常都是使用CDO提前处理,大家可以自行尝试)。

根据官方的介绍,Xarray也支持grib文件的读取。

前提是需要一个解码库"eccodes"

或者利用Xarray借助PYNIO去读。

官方文档中还有一部分是关于画图的,然而画图部分个人认为使用matplotlib+cartopy的组合更加灵活,因此Xarray系列到这里应该就完结了。

下一步的计划是按照魏凤英老师的统计方法一书,试着将常用的气象统计方法利用python去实现,但是水平实在有限。