【射雕英雄传】文本分析初步(姓名,丹药,秘籍,招式)[scrapy, jieba, matplotlib]
大三上学期选了学校高瓴开的大数据分析导论,最后的final分为两个部分,本文讲述第一部分的完成步骤。大致可以描述为:爬取文章,从本文本构造user_dict,利用jieba分词,分门别类统计词频并绘图。
在此做个小预告,final第二部分是绘制词云、主题抽取、利用word_embedding进行相关性分析以及自主探索,后面做完作业再更新,放在一个主题下方便查找。
文章目录
- 内容的爬取
- user dict的构造
- user dict
- 概述
- 核心思想【以姓名提取为例】
- 丹药与秘籍提取
- 地点提取
- 绘图
内容的爬取
感觉爬虫这个玩意儿其实挺简单的,不过只学习了静态网页的爬取所以也有点以偏概全的意思,但是这里不解释爬虫相关的细节与东西。
import scrapy
class NovelSpider(scrapy.Spider):name = "info"def start_requests(self):urls = [ # 'http://www.jinyongshuwu.com/nshe/index.html']for url in urls:yield scrapy.Request(url=url, callback=self.parse)def parse(self, response):prefix = 'http://www.jinyongshuwu.com/nshe/'for url in response.css('ul.mlist li a::attr(href)').extract():url = prefix + urlyield scrapy.Request(url=url, callback=self.parseDetails)def parseDetails(self, response):title = response.css('h1.title::text').extract_first()content = [s.strip() for s in response.css('div.vcon p::text').extract()]with open('射雕英雄传\\原文 换源\\' + title + '.txt', 'w', encoding='utf-8') as fout:fout.write(title)for para in content:fout.write('\n' + para)
唯一需要解释一嘴的是parse
函数里面在进行详情页的爬取的时候,需要加上prefix
这个东西,因为发现直接拿到的url并不是链接的完全体,而是最后的一部分,比如1000.html。所以如果想正常访问,必须和prefix
粘在一起。
user dict的构造
先小小解释一下user_dict这玩意是个啥一遍没什么基础的同学们看得舒服一些。
user dict
这玩意儿是我们在调用中文分词模块jieba
的时候有时需要自定义的一个词典。为啥需要这么个东西?我们来想象jieba
可能的应用场景,老师让你帮他做一个领导讲话的文本分析。你拿到手之后发现领导的文笔属实nb,其中用到了很多人的举例论证,所以难免会有很多的人名在里面。但是jieba
这个东西很难对中文名字进行合适的分割,比如一段文本“刘欢笑道”,可以有两种理解方式,要么这哥们是刘欢,要么叫刘欢笑。为了帮助jieba
识别“刘欢”这个词语,并且不让它从中间一分为二,被上下文语意所撕裂,我们构建一个文本文件user_dict
把“刘欢”这个名字写进去,并且利用jieba.load_userdict(filepath)
添加进去。
更多的细节我们不再展开,比如在后面可以进一步地添加词频与词性等。另外,需要说明的是你把“刘欢”加了进去,如果你用jieba
分的那段文字里面刘欢这哥们老笑着说话,那么还是有可能分词为“刘欢笑”+”道“,这是内部算法所决定的,没有更精细需求的可以略去。
示例:
user_dict.txt
#内容是:
#刘欢
import jieba
jieba.load_userdict('user_dict.txt')
概述
需要说一下的是,诚然可以从网上尽情搜罗金庸宇宙的各种人名、丹药或秘籍的名字,直接放在user_dict里面进行分割,但是完全失去了这个作业本应锻炼我们的地方。所以我选择一周每天额外工作两个小时左右,从产生想法到实现算法自己提取这些未知的词汇,现在看来不仅提取了在网上没有出现过的内容,并且给了我很大的锻炼。
很喜欢徐君老师的一句话,有多少人工就有多少智能。
因此构造user dict
会是本篇博客的重点,不感兴趣的可以跳过,看看后面对于分词与词频统计、绘图的内容。
本部分的工作流程如下:
p.s. 如果任务很急的话还是下载个细胞词库直接切吧
核心思想【以姓名提取为例】
就像证明数学题一样,我们首先看看目标:提取一系列词语,特别地是我们不知道的,甚至有一些是由作家天马行空想象出来的,所以我们无法直接精准定位。那怎么办呢?最直觉的想法就是去找有什么东西是人的特征,或者说有没有什么动作或者是形容词是专门用来讲人的。
最开始的想法是:在小说里,只要不是哑巴都得说话,而在金庸的这部小说里,语言的提示词基本都是”道“。
用写论文的文笔来阐述这个想法是这样的:
记文段中随机选择一段定长的字串,其中含有人物姓名为事件AAA,记其概率为P(A)\mathbf{P}{(A)}P(A)。
另一方面,虽然我们并不清楚文章中人物具体做了什么,但是能断定,至少主要人物一定会说话、有台词。经过简单的浏览,发现文中用 道 这个字来指示人物的说话内容,因此我们可以有以下记号。
记文段中随机选择一段定长的字串,其中含有 道 这个字为事件BBB。那么P(A∣B)\mathbf{P}(A|B)P(A∣B)表示对于含有 道 这个字的字串,其含有人物姓名的概率。
由于P(B)≤1\mathbf{P}(B) \leq 1P(B)≤1,显然有
P(A)≤P(A∣B)\mathbf{P}(A) \leq \mathbf{P}(A|B)P(A)≤P(A∣B)
事实上,在应用中我们可以发现,当简单地添加一些停止词,如道路、道德后,我们显著地有以下结果:
P(A)<P(A∣B)\mathbf{P}(A) < \mathbf{P}(A|B)P(A)<P(A∣B)
进一步,这项观察给了我们新的启发,我们发现有些人名经常有一些后缀,比如哥、姐、大师、散人这样,因此把这样的提示词也加入其中进行筛查,并写入一些停止词。
detect_words = ['散人','道','姑','哥','大师','姐']
stop_names = ['一人','长老','那人','那书生','大师父','姑娘','大哥','老哥','师哥','小哥']
在代码的第二大块中,我们对每个提示词,在所有章节中进行搜索,将通过停止词筛选的提示词上下文写入文件中。
我们通过把一些名字筛出来,添加到停止词中。
stop_names = ['一人','长老','那人','那书生','大师父','姑娘','大哥','老哥','师哥','小哥','黄蓉','郭靖','洪七公','黄药师',
'欧阳锋','丘处机','包惜弱','杨铁心','郭啸天','颜烈','鲁有脚','张十五','柯镇恶','周伯通','陆乘风','朱聪','段天德','裘千仞',
'颜洪烈','铁木真','欧阳克']
但是发现剩余的句子还是很多。类似地参考条件概率的思想,由于人物之间通常有关系并在一起行动,我认为在某已知姓名的上下文中,很有可能出现其他未出现的人名。
依据这个想法,通过下一个模块在网上找到的函数,通过paddle进一步识别姓名,并通过更新的stop_names
进行交叉排除,最后只剩余100~200个选项,简单地人工筛选过后便得到65个出现频率比较高的人名。
下面是我在网络上找到的代码,但是忘记原作者是哪位了,这里进行标注,也希望有知道的各位在评论里告诉我,从而对来源进行修正。
import pandas as pd
import jieba
import paddle
import jieba.posseg as pseg
paddle.enable_static()
jieba.enable_paddle()def get_per_list(text):per_list = [] # 人名列表word_list = jieba.lcut(text)for word in word_list:if len(word)==1: # 不加判断会爆continuewords = pseg.cut(word, use_paddle=True) # paddle模式word, flag = list(words)[0]if flag=='PER': per_list.append(word)per_list = list(set(per_list))return per_list
# 注意 本段代码非原创
# 注意 本段代码非原创
# 注意 本段代码非原创
丹药与秘籍提取
核心思想是一样的,利用关键词进行全文搜索,截取上下文一定window_size的窗口进行进一步的处理。然后不断向其中添加停止词,不断走流程图中的后三步。
提示词可以有这些:
detect_words = ['鞭','枪','经','腿','手','剑','掌','刀','拳','指','功','大法','真经','宝典','诀','棒']
charac_words = ['药','丹','散','粉','菩提','膏','丸']
地点提取
这个的处理就比较暴力了,金庸在杜撰地名的时候和现代网络小说东拼西凑让名字听起来炫酷不一样,而是通常在后面跟着”岛“”寺“等提示词,但另一方面jieba
本来就可以对其进行识别,所以我通过对上述借鉴的代码进行微调,将函数中最后一个if
的条件改成if flag=='LOC'
就直接可以用了。
绘图
其实感觉这也没啥可说的,用matplotlib
画画bar plot就ok了。
from matplotlib import pyplot as plt
import os
plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False #该语句解决图像中的“-”负号的乱码问题num_upper_bound = 5# data_file_name = '射雕英雄传 cut.txt'
key_file_name = '可能丹药.txt'def count_appear_times(key, data_file_name):count = 1with open(data_file_name, 'r', encoding='utf-8') as fin:for line in fin.readlines():pos = line.find(key)while pos != -1:count += 1line = line[pos + len(key):]pos = line.find(key)return countdef most_frequent(data_file_name, key_file_name, num_upper_bound):key_list = []with open(key_file_name, 'r', encoding='utf-8') as fin:for line in fin.readlines():key_list.append(line.strip())key_count_dict = dict()for key in key_list:key_count_dict[key] = int(count_appear_times(key, data_file_name))return sorted(key_count_dict.items(), key= lambda x:x[1], reverse=True)[:num_upper_bound]
我分章节画了一遍,总体又画了一遍。分章节的时候使用了plt.subplot2grid()
这个函数来在一张图中绘制多个图表。
具体效果图见下:
当时犯懒用ipynb文件进行调试的,没有对代码总体地整理,如果大家有代码的需求可以私信我,我抽时间弄一下传上来。
【射雕英雄传】文本分析初步(姓名,丹药,秘籍,招式)[scrapy, jieba, matplotlib]相关推荐
- 【射雕英雄传】文本分析初步 第二弹【gensim word2vec lda roberta】
我来填坑了,这学期五门数学课期末属实有点顶,废话不多说好吧,切入正题. 下面文中可能会时不时'引用前文',第一弹链接在这里 文章目录 内容概览 词云 gensim Word2Vec LDA 情感分析[ ...
- 独家交付秘籍之招式拆解(第一回)
简介:上一回说到经历种种交付难题的王小锤一行人,意外发现一本交付秘籍,打开了新世界.本次他们带着具体交付场景来到阿里云,与交付宗师阿莫探讨秘籍中的招式以及招式背后的秘密. 作者:吕莫.新钰 前情介绍 ...
- Python中文分析:《射雕英雄传》统计人物出场次数、生成词云图片文件、根据人物关系做社交关系网络和其他文本分析
前言 python中文分析作业,将对<射雕英雄传>进行中文分析,统计人物出场次数.生成词云图片文件.根据人物关系做社交关系网络和其他文本分析等. 对应内容 1.中文分词,统计人物出场次数, ...
- python 英语词频统计软件_Python数据挖掘——文本分析
作者 | zhouyue65 来源 | 君泉计量 文本挖掘:从大量文本数据中抽取出有价值的知识,并且利用这些知识重新组织信息的过程. 一.语料库(Corpus) 语料库是我们要分析的所有文档的集合. ...
- r语言上机文本分析与词云绘制_倚天屠龙记的文本分析
<倚天屠龙记>作为金庸先生的经典作品,在无数人心目中留下了深刻的印象,基本上隔一段时间这部经典作品就会被重新拍成电影或者电视剧,可见观众的喜爱程度.虽然本人没有完完全全拜读过先生的这部作品 ...
- Java正则速成秘籍(一)之招式篇
目录 导读 概述 Pattern类 Matcher类 校验文本是否与正则规则匹配 案例:lookingAt vs find vs matches 查找匹配正则规则的文本位置 案例:使用start(). ...
- 从入门到入土:机器学习part01|python|代码分析|初步学习
此博客仅用于记录个人学习进度,学识浅薄,若有错误观点欢迎评论区指出.欢迎各位前来交流.(部分材料来源网络,若有侵权,立即删除) 本人博客所有文章纯属学习之用,不涉及商业利益.不合适引用,自当删除! 若 ...
- 《计算传播学导论》读书笔记——第二章文本分析简介
<计算传播学导论>读书笔记--第二章文本分析简介 第一节 文本分析研究现状 常用文本挖掘技术 第二节 文本分析与传播学研究 (一)为什么文本挖掘技术逐渐受到传播学者的关注 (二)不同文本分 ...
- 【文本分析】基于粤港澳大湾区博物馆访客评价的文本分析
此文是2021年初在深圳大学文化产业研究院黄老师的指导下,与吴同学合作完成的,且于2021年4月发表于<文化深圳>杂志第一期. 文章目录 1 背景 2 研究思路 3 数据来源 4 数据基本 ...
最新文章
- kde重启_在Linux系统中出现KDE Plasma面板崩溃问题的解决方法
- Oracle性能监控脚本
- Index Condition Pushdown Optimization
- idea中如何将一个普通项目转换为maven项目
- JS 查看标签下某元素所有信息(查看元素,查询元素,遍历元素、HTMLCollection对象、NodeList对象)
- 5-1WordCount单词计数
- 制作好的app需要服务器吗,在直播app制作过程中,服务器是如何配置的?
- 努力奋斗,但不想像蚂蚁那样!
- redhat6 本地 yum源配置方法
- WORD中输入已知编码的特殊字符
- PreScan笔记(1)——入坑之简单介绍和Demo
- IT 常用词汇(一)
- SCM供应链协同管理系统解决方案
- mac trace traceroute 简要使用
- Massive MIMO简介
- 【HDU5442】 Favorite Donut(后缀数组)
- Cloud Foundry 运行bosh create-env时报错: TLS handshake timeout
- python如何导入包
- 凭技术可以受欢迎,但想得到尊重要有灵魂——Leo简历工作室 蓝血十杰简介
- Hibernate @SequenceGenerator的注解介绍
热门文章
- sqlserver broker远端端点证书认证
- 通用引用、引用折叠与完美转发问题
- [译] 冲冠一怒为代码:论程序员与负能量
- 观察者模式——气象局高温预警
- 【ARCGIS创建中国南海诸岛及九段线小图框】
- oracle测试主要做什么的,ERP软件测试主要做什么?
- 解决报错Parameter 0 of constructor in XXX required a bean...elasticsearch 继承ElasticsearchConfiguration方法
- ARM | STM32F10xxx课堂学习笔记(时钟 高级控制定时器)
- Cartographer学习总结
- 快手2020校园招聘秋招笔试--工程A试卷 题4