本文的灵感来源于李金同学的一篇关于金庸武侠小说的自然语言处理的文章,大家有兴趣可以在
GitHub
上关注他。地址
在上一篇文章中,我们使用Python来收集网络数据。这个可以复用的Python小程序,可以抓取任意电影的海报以及剧照。当你想要找一张《加勒比海盗5》的电影海报作为电脑桌面的时候,这个小程序就可以轻松帮到你了!上一篇文章的链接
你可能还是没有下定决心学习Python,那么今天的教程将和大家一起用Python做一点有趣的事情。相信大家可以在这个小项目中体验到Python的强大!
我们将在今天用Python来分析一本热门的网络小说《择天记》,在这个项目中,我们可以做到以下几件很有意思的事:
先在网络上下载一本择天记小说的txt版本,保存在项目目录中。我下载的小说保存下来就是64565.txt。使用Python读取整个文本,并构建列表。
In [17]:
# 读取择天记小说
with open('64565.txt',encoding='utf-8') as f:
cont = [line.strip() for line in f.readlines() if line.strip()]
# 尝试在控制台打印一段文本
for line in cont[105:107]:
print(line)
In [3]:
#读取人物名字
with open('names.txt') as f:
names = [name.strip() for name in f.readlines()]
print(names)
In [4]:
# 统计人物出场次数
def find_main_charecters(num = 10):
novel = ''.join(cont)
count = []
for name in names:
count.append([name,novel.count(name)])
count.sort(key = lambda v : v[1],reverse=True)
return count[:num]
find_main_charecters()
Out[4]:
我们使用echarts做数据可视化的工作
In [4]:
from IPython.display import HTML
chart_header_html = """
<div id="main_charecters" style="width: 800px;height: 600px;" class="chart"></div>
<script>
require.config({
paths:{
echarts: '//cdn.bootcss.com/echarts/3.2.3/echarts.min',
}
});
require(['echarts'],function(ec){
var charectersNames = ['陈长生', '唐三十六', '徐有容', '苏离', '落落', '折袖', '苟寒食', '轩辕破', '魔君', '王破', '商行舟', '周通', '南客', '莫雨', '秋山君', '黑袍', '天海圣后', '王之策', '朱洛', '肖张']
var charectersCount = [15673, 3609, 3262, 1889, 1877, 1656, 1183, 1158, 1146, 1134, 1110, 945, 874, 746, 624, 589, 554, 532, 513, 476]
var charectersCountChart = ec.init(document.getElementById('main_charecters'))
charectersCountChart.setOption({
title:{
text: '择天记人物出场次数统计图'
},
tooltip:{},
xAxis:{
type: 'value',
data: ['出场次数']
},
yAxis:{
type: 'category',
data: charectersNames.reverse()
},
series:{
name: '主要人物',
type: 'bar',
data: charectersCount.reverse()
}
})
});
</script>
"""
# 我本地的浏览器可以渲染出来,放到git上就不行了...所以拿图片代替了
我们可以清楚的看到,《择天记》的主角为陈长生共出场接近16000次,紧随其后的是唐三十六(男性)和徐有容(有容奶大是女性)。仅从这个简单的数据,我们就可以推测唐三十六是主角陈长生的好基友,徐有容很有可能和陈长生是恋人关系。
另外,我们看到其他出场率比较相似的人物中,女性角色明显不多。我们可以大致推断《择天记》这本小说是一个单女主的小说。更进一步的说,徐有容和陈长生在整部小说中可能都很专情。
出场次数前20的人物中,可以看出一个明显的规律——主要人物的人名都非常奇葩,一看就不是普通人能叫的名字!在现实生活中不可能有人叫唐三十六,折袖,苟寒食,商行舟,南客这样的名字。所以,《择天记》的作者多半是一个很中二的人。
另外还有一个有趣的事情,就是这些人物的姓氏明显都不相同,只有王之策和王破都姓王。这一点我们可以推断,《择天记》中的故事很有可能不是关于家族之间的纷争,或者说着墨不多。我们看到魔君的出场次数达到700多次,这种名字一看就是反派,无一例外。
统计人物出场次数显然是Python中最最基础的操作,那我们现在来使用更高级的算法来尝试分析《择天记》这本小说。
我们使用gensim
库对《择天记》进行 Word2Vec
的操作,这种操作可以将小说中的词映射到向量空间中,从而分析出不同词汇之间的关系。另外值得一提的是,由于中文和英文不同,中文词语之间没有空格,所以我们需要使用Python第三方库结巴分词对文本进行分词。我们为了提高分词的准确性,我们需要将小说中一些专属名词添加到词库中。
In [8]:
import jieba
# 读取门派、境界、招式等名词
with open('novelitems.txt') as f:
items = [item.strip() for item in f.readlines()]
for i in items[10:20]:
print(i)
我们需要将这些名词添加到结巴分词的词库中。
In [10]:
for name in names:
jieba.add_word(name)
for item in items:
jieba.add_word(item)
我们现在就可以开始使用机器学习来训练模型了。
In [33]:
novel_sentences = []
# 对小说进行分词,这里只是任选了一句
# for line in cont:
for line in cont[:6]:
words = list(jieba.cut(line))
novel_sentences.append(words)
novel_sentences[4]
Out[33]:
In [ ]:
# 按照默认参数进行训练
model = gensim.models.Word2Vec(sentences, size=100, window=5, min_count=5, workers=4)
# 把训练好的模型存下来
model.save("zetianjied.model")
# 训练模型需要大概20分钟左右的时间,因性能而异。由于模型太大了就不放在github上面了。
In [35]:
import gensim
# 读取模型
model = gensim.models.Word2Vec.load("zetianjied.model")
In [36]:
# 寻找相似境界
for s in model.most_similar(positive=["坐照"]):
print(s)
In [37]:
for s in model.most_similar(positive=["魔君"])[:7]:
print(s)
我们可以看到结果中出现了与魔君实力水平相似的前七个人物,这些人物可以与反派BOSS相提并论,肯定是站在《择天记》实力巅峰的大人物。事实上这些人物在原著中都是从圣境。
In [41]:
d = model.most_similar(positive=['无穷碧', '陈长生'], negative=['徐有容'])[0]
d
Out[41]:
我们随便找一个人物,比如:折袖。运行程序,看一看机器眼中折袖与谁是情侣?
In [46]:
d = model.most_similar(positive=['折袖', '无穷碧'], negative=['别样红'])[0]
d
Out[46]:
因为之前看过一点《择天记》,并且看到了折袖和七间登场。可是明明折袖和七间都是男性角色,所以可能程序出错了?但我百度了一下,才知道原来七间是女伴男装,最后真的和折袖在一起了!!!妹的,竟然被机器给剧透了!