——— 本文来自于萌新的小作业
根据自然语言处理,请选择一本你喜欢的小说,对该小说进行分析。比如分析该小说的分词,词频,词性,小说人物出场次数排序,小说中食物排序(这个得有,我喜欢吃),小说人物关系等等。
代码如下:
import re
import networkx as nx
import matplotlib.pyplot as plt
import jieba.posseg as pseg # 引入词性标注接口
# 导入random包
import random
import codecs
# 导入pyecharts
from pyecharts import options as opts
# pyecharts 柱状图
from pyecharts.charts import Bar
# pyecharts 词云图
from pyecharts.charts import WordCloud
# 词云
import wordcloud
import imageio
1. 文本读取
读取整本小说并转换为utf-8,代码如下:
# 定义主要人物的个数
keshihuaTop=10 # 可视化人物图人数
mainTop = 100 # 人物词云图人物数
peopleTop=10 # 人物关系图# 获取小说文本
# 读取文件
fn = open('prepare/天龙八部.txt', encoding="utf-8")
string_data = fn.read() # 读出整个文件
fn.close() # 关闭文件
2.文本预处理
利用正则表达式除去换行等字符,代码如下:
# 文本预处理
pattern = re.compile(u'\t|\n|\.|-|:|;|\)|\(|\?|"') # 定义正则表达式匹配模式
txt = re.sub(pattern, '', string_data) # 将符合模式的字符去除
print('预处理完毕')
1. 词性分析
利用停用词文档分词,通过键值对的形式存储词语并且统计出现次数,以高到低排序生成词频文档
# 停词文档
def stopwordslist(filepath):stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()]return stopwordsstopwords = stopwordslist('prepare/tingyong.txt')# 通过键值对的形式存储词语及其出现的次数
counts1 = {} # 存放词性词频
counts2={} #存放人物词频
# # 生成词频词性文件
def getWordTimes1():cutFinal = pseg.cut(txt)for w in cutFinal:if w.word in stopwords or w.word == None:continueelse:real_word = w.word+'_'+w.flagcounts1[real_word] = counts1.get(real_word, 0) + 1getWordTimes1()items1 = list(counts1.items())
# 进行降序排列 根据词语出现的次数进行从大到小排序
items1.sort(key=lambda x: x[1], reverse=True)# 导出数据
# 分词生成人物词频(写入文档)
def wordFreq1(filepath, topn1):with codecs.open(filepath, "w", "utf-8") as f:for i in range(topn1):word, count = items1[i]f.write("{}:{}\n".format(word, count))# 生成词频文件
wordFreq1("output/天龙八部词频词性.txt", 300)
输出结果如下:
先将text数据转换为字典形式,提取字典中的数据用bar函数绘制柱状图,调用render函数生成html。
# 将txt文本里的数据转换为字典形式
fr1 = open('output/天龙八部词频词性.txt', 'r', encoding='utf-8')
dic1 = {}
keys1 = [] # 用来存储读取的顺序
for line in fr1:# 去空白,并用split()方法返回列表v1 = line.strip().split(':')dic1[v1[0]] = v1[1]keys1.append(v1[0])
fr1.close()list_name1 = list(dic1.keys()) # 人名
list_name_times1 = list(dic1.values()) # 提取字典里的数据作为绘图数据
def create_wordproperties():bar1 = Bar()bar1.add_xaxis(list_name1[0:keshihuaTop])bar1.add_yaxis("词语出现次数", list_name_times1,color='blue')bar1.set_global_opts(title_opts=opts.TitleOpts(title="词频词性可视化图", subtitle="词频词性top10"),xaxis_opts=opts.AxisOpts(axislabel_opts={"rotate": 45}))bar1.set_series_opts(label_opts=opts.LabelOpts(position="top"))# 生成 html 文件bar1.render("output/天龙八部词频词性可视化图.html")
如图所示,显然可见大部分词频在2000左右,最高词频为8651
同样利用jieba分词,排除长度小于2或该词词性不为nr的词,对出现次数排序并写入文档,代码如下:
# 得到 分词和出现次数
def getWordTimes2():# 分词&#xff0c;返回词性poss &#61; pseg.cut(txt)for w in poss:if w.flag !&#61; &#39;nr&#39; or len(w.word) < 2:continue # 当分词长度小于2或该词词性不为nr&#xff08;人名&#xff09;时认为该词不为人名else:real_word &#61; w.wordcounts2[real_word] &#61; counts2.get(real_word, 0) &#43; 1getWordTimes2()
items2 &#61; list(counts2.items())
# 进行降序排列 根据词语出现的次数进行从大到小排序
items2.sort(key&#61;lambda x: x[1], reverse&#61;True)# 导出数据
# 分词生成人物词频&#xff08;写入文档&#xff09;
def wordFreq2(filepath, topn):with codecs.open(filepath, "w", "utf-8") as f:for i in range(topn):word, count &#61; items2[i]f.write("{}:{}\n".format(word, count))# 生成词频文件
wordFreq2("output/天龙八部词频_人名.txt", 300)
输出结果如下&#xff1a;
与词频方法相同可视化人物人名出场次数&#xff0c;最终生成html
# 将txt文本里的数据转换为字典形式
fr &#61; open(&#39;output/天龙八部词频_人名.txt&#39;, &#39;r&#39;, encoding&#61;&#39;utf-8&#39;)
dic &#61; {}
keys &#61; [] # 用来存储读取的顺序
for line in fr:# 去空白,并用split()方法返回列表v &#61; line.strip().split(&#39;:&#39;)dic[v[0]] &#61; v[1]keys.append(v[0])
fr.close()
# 输出前几个的键值对
print("人物出现次数TOP", mainTop)
print(list(dic.items())[:mainTop])# 绘图
# 人名列表 (用于人物关系图,pyecharts人物出场次数图)
list_name &#61; list(dic.keys()) # 人名
list_name_times &#61; list(dic.values()) # 提取字典里的数据作为绘图数据# 可视化人物出场次数
def creat_people_view():bar &#61; Bar()bar.add_xaxis(list_name[0:keshihuaTop])bar.add_yaxis("人物出场次数", list_name_times,color&#61;&#39;blue&#39;)bar.set_global_opts(title_opts&#61;opts.TitleOpts(title&#61;"人物出场次数可视化图", subtitle&#61;"天龙八部人物TOP10"),xaxis_opts&#61;opts.AxisOpts(axislabel_opts&#61;{"rotate": 45}))bar.set_series_opts(label_opts&#61;opts.LabelOpts(position&#61;"top"))# bar.render_notebook() # 在 notebook 中展示# make_snapshot(snapshot, bar.render(), "bar.png")# 生成 html 文件bar.render("output/天龙八部人物出场次数可视化图.html")
由柱状图可见段誉出场次数最多&#xff0c;阿紫出场次数最少
2.词云及人物关系
根据单词频率创建词云&#xff0c;生成词云图片&#xff0c;用pyecharts 生成词云&#xff0c;返回html,如下图所示&#xff1a;
# 生成词云
def creat_wordcloud():bg_pic &#61; imageio.imread(&#39;prepare/img.png&#39;)wc &#61; wordcloud.WordCloud(font_path&#61;&#39;c:\Windows\Fonts\simhei.ttf&#39;,background_color&#61;&#39;white&#39;,width&#61;1000, height&#61;800,max_words&#61;500,mask&#61;bg_pic # mask参数设置词云形状)# 从单词和频率创建词云wc.generate_from_frequencies(counts2)# generate(text) 根据文本生成词云# wc.generate(txt)# 保存图片wc.to_file(&#39;output/天龙八部词云_人名.png&#39;)# 显示词云图片plt.imshow(wc)plt.axis(&#39;off&#39;)plt.show()# 使用pyecharts 的方法生成词云
def creat_wordcloud_pyecharts():wordsAndTimes &#61; list(dic.items())(WordCloud().add(series_name&#61;"人物次数", data_pair&#61;wordsAndTimes,word_size_range&#61;[20, 100], textstyle_opts&#61;opts.TextStyleOpts(font_family&#61;"cursive"), ).set_global_opts(title_opts&#61;opts.TitleOpts(title&#61;"天龙八部词云")).render("output/天龙八部词云_人名.html"))# 颜色生成
colorNum &#61; len(list_name[0:peopleTop])# print(&#39;颜色数&#39;,colorNum)
def randomcolor():colorArr &#61; [&#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;7&#39;, &#39;8&#39;, &#39;9&#39;, &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39;]color &#61; ""for i in range(6):color &#43;&#61; colorArr[random.randint(0, 14)]return "#" &#43; colordef color_list():colorList &#61; []for i in range(colorNum):colorList.append(randomcolor())return colorList# 解决中文乱码
plt.rcParams[&#39;font.sans-serif&#39;] &#61; [&#39;SimHei&#39;] # 用来正常显示中文标签
这俩张图展示了由人名构成的不同形状的词云&#xff0c;字体越大表现人物出场次数越多。
用Fruchterman-Reingold算法排列节点&#xff0c;根据每一段出现共现关系创建无向图绘制人物关系图
# 生成人物关系图
def creat_relationship():# 人物节点颜色colors &#61; color_list()Names &#61; list_name[0:peopleTop]relations &#61; {}# 按段落划分&#xff0c;假设在同一段落中出现的人物具有共现关系lst_para &#61; (txt).split(&#39;\n&#39;) # lst_para是每一段for text in lst_para:for name_0 in Names:if name_0 in text:for name_1 in Names:if name_1 in text and name_0 !&#61; name_1 and (name_1, name_0) not in relations:relations[(name_0, name_1)] &#61; relations.get((name_0, name_1), 0) &#43; 1maxRela &#61; max([v for k, v in relations.items()])relations &#61; {k: v / maxRela for k, v in relations.items()}# return relationsplt.figure(figsize&#61;(15, 15))# 创建无多重边无向图G &#61; nx.Graph()for k, v in relations.items():G.add_edge(k[0], k[1], weight&#61;v)# 筛选权重大于0.6的边elarge &#61; [(u, v) for (u, v, d) in G.edges(data&#61;True) if d[&#39;weight&#39;] > 0.6]# 筛选权重大于0.3小于0.6的边emidle &#61; [(u, v) for (u, v, d) in G.edges(data&#61;True) if (d[&#39;weight&#39;] > 0.3) & (d[&#39;weight&#39;] <&#61; 0.6)]# 筛选权重小于0.3的边esmall &#61; [(u, v) for (u, v, d) in G.edges(data&#61;True) if d[&#39;weight&#39;] <&#61; 0.3]# 设置图形布局pos &#61; nx.spring_layout(G) # 用Fruchterman-Reingold算法排列节点&#xff08;样子类似多中心放射状&#xff09;# 设置节点样式nx.draw_networkx_nodes(G, pos, alpha&#61;0.8, node_size&#61;1300, node_color&#61;colors)# 设置大于0.6的边的样式nx.draw_networkx_edges(G, pos, edgelist&#61;elarge, width&#61;2.5, alpha&#61;0.9, edge_color&#61;&#39;g&#39;)# 0.3~0.6nx.draw_networkx_edges(G, pos, edgelist&#61;emidle, width&#61;1.5, alpha&#61;0.6, edge_color&#61;&#39;y&#39;)# <0.3nx.draw_networkx_edges(G, pos, edgelist&#61;esmall, width&#61;1, alpha&#61;0.4, edge_color&#61;&#39;b&#39;, style&#61;&#39;dashed&#39;)nx.draw_networkx_labels(G, pos, font_size&#61;14)plt.title("《天龙八部》主要人物社交关系网络图")# 关闭坐标轴plt.axis(&#39;off&#39;)# 保存图表plt.savefig(&#39;output/《天龙八部》主要人物社交关系网络图.png&#39;, bbox_inches&#61;&#39;tight&#39;)plt.show()def main():#生成词频词性文件create_wordproperties()# 人物出场次数可视化图creat_people_view()# 词云图creat_wordcloud()creat_wordcloud_pyecharts()# 人物关系图creat_relationship()
自然语言处理就是通过用计算机来处理人类的语言、文字&#xff0c;从而可以代替人类做一些文书类的工作&#xff0c;例如咨询、售后、海量数据处理以及公文阅读与处理等。基于此&#xff0c;NLP领域延基于此&#xff0c;NLP领域延伸处理种类繁多的任务。通过本次作业学会了分词的技术及关键词的提取&#xff0c;同时也会生成词云和柱状图的绘制&#xff0c;奇怪的知识又增加了不少。
jieba分词特点&#xff1a;
支持三种分词模式&#xff1a;
精确模式&#xff0c;试图将句子最精确地切开&#xff0c;适合文本分析&#xff1b;
全模式&#xff0c;把句子中所有的可以成词的词语都扫描出来, 速度非常快&#xff0c;但是不能解决歧义&#xff1b;
搜索引擎模式&#xff0c;在精确模式的基础上&#xff0c;对长词再次切分&#xff0c;提高召回率&#xff0c;适合用于搜索引擎分词。
支持繁体分词
支持自定义词典
MIT 授权协议
算法&#xff1a;
基于前缀词典实现高效的词图扫描&#xff0c;生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)
采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
对于未登录词&#xff0c;采用了基于汉字成词能力的 HMM 模型&#xff0c;使用了 Viterbi 算法