python下对爬取到的史书用nltk统计词频,词云生成,snownlp做文章情感分析及对应柱状图

本文详细介绍了如何进行情感分析、词频统计、词云生成和柱状图制作。首先,通过结巴分词、nltk库处理中文文本,构建停用词库,去除无意义词汇。接着,利用SnowNLP进行情感分析,展示史书情感正负面的柱状图。最后,结合WordCloud和背景图片创建词云,提供了一步一步的实现步骤和解决问题的方法。
摘要由CSDN通过智能技术生成

前言

此文比较适合第一次做情感分析,结巴分词,统计词频,生成词云,画统计图的同学,应该会让你们少走点弯路。

完整代码放最后面,前面是解决各种可能出现的问题。建议一步一步做,都可以理解的。

一、首先是库的引用

代码如下(示例):


import json
import jieba
import nltk
import os
from wordcloud import WordCloud,ImageColorGenerator
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from snownlp import SnowNLP
from snownlp import SnowNLP
from pylab import *

二、进入正题,解决各种可能出现的问题

1.安装库

我是用Windows下的pycharm做的,其中的Wordcloud库的安装,pycharm会报错。以后遇到这类问题,有个很好用的办法。
步骤:
1.先到python的官网下载你想要的包,注意,要对应你python解释器的版本,满足3.91,64位机之类的一些要求。
2.进去终端,先进入到包下载位置的对应路径,然后pip install wordcloud,如果报错说没有wheel,那就在重新进入终端,输入pip install wheel,然后再安装对应的库。这样可以解决绝大多数包安装错误的问题。

2.中文乱码

我在生成统计图时,统计图的标题和横坐标全都是方框,这就是中文乱码,解决方法就是下面这两行代码放进去就好,具体看我完整代码。

# from pylab import *   这个包就是下面两句代码用的

#处理统计图中中文会出现乱码的问题
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False

3.1进入正题,先读取要分析的文件

我这边是从一个大文件下读取文件,文件夹中有130个json文件,那就需要os库对文件夹进行遍历,获取文件夹下的文件名字,方便打开,读取。上代码:

def get_txt():
    fpath = 'D:/编程project/后汉书_译文'   #这是文件夹对应我电脑的路径
    flist = os.listdir(fpath)            #得到文件夹下的所有文件名称
    data_2 = ''                          #我这边是把这些想要的内容拼接在一起
    for file in flist:  # 遍历文件夹
        fpath_2 = fpath + '/' + file     #这里就是每个循环要打开的文件的路径了
        of = open(fpath_2, 'r', encoding='utf-8')  # 打开文件
        diclist = json.load(of)          #读取json文件
        of.close()
        data_1 = str(diclist['content']) #读取的json文件内容是字典,我要的是键值对,键为content对应的值
        data_2 = data_1 + data_2
    return data_2                        #要返回的就是最后获取的字符串了    

3.2获取停用词库以及去除停用词

一篇文章,你要对他的词频进行统计,那就尽量使得获取到了的大部分词频是有意义的,那就要从获取到的词频中选出那些经常出现但又没有意义的词。然后从词频中去掉这些词,这就叫去除停用词。

对了,要词频统计,要先分词啊。就先介绍一下最好用的中文分词的库,结巴库。
上代码:

text='今天天气真好,那就出去玩吧'
word1=jieba.cut(text,cut_all=False)
print("精确模式 "+' '.join(word1))
word2=jieba.cut(text,cut_all=True)
print('全模式 '+' '.join(word2))
word3=jieba.cut_for_search(text)
print('搜索引擎模式 '+' '.join(word3))

运行结果就是:
精确模式 今天天气 真 好 , 那 就 出去 玩吧
全模式 今天 今天天气 天天 天气 真好 , 那 就 出去 出去玩 玩吧
搜索引擎模式 今天 天天 天气 今天天气 真 好 , 那 就 出去 玩吧

简单的了解了结巴分词,那就可以做词频统计

首先构建停用词库,并写入文件存到对应的盘,我这边是用sorted函数对词频进行降序排序,也就是从大到小的顺序,其中有用replace函数去除一些存在的没有意义的符号。

def get_first_stopwords():     #获得没去除停用词的词频文档,进行构建停用词库
    data=get_txt()
    word = jieba.cut(data, cut_all=False)
    freq = nltk.FreqDist(word)
    puts_1=open('D:/编程project/make_stopwords.txt','w',encoding='utf-8')
    puts_1.writelines('以下是词频结果'+'\n')
    for key, val in sorted(freq.items(), key=lambda x: (x[1], x[0]), reverse=True):
        work=(str(key) + ':' + str(val))
        work=work.replace('’','').replace('‘','').replace('?','')
        puts_1.write(work + '\n')
    puts_1.close()

这时,你针对获取到的词频,选出那些高频低价值的词,构建停用词库,一行一个吧,比较简明清晰。这个停用词库是你自己新建一个txt文档自己编写。

下面这个文档就是自己编写的,然后读取返回里面的停用词。

def get_stopwords():
    files=open('D:/编程project/1913206138_stopword .txt','r').read()
    return files

3.3获取最终词频统计并写入文档

接下来就是重点,进行分词和统计词频。

def jiebafc(data,stopwords):
    word = jieba.cut(data, cut_all=False)
    final=''
    for seg in word:              #这个循环就是去除停用词,非常好理解
        if seg not in stopwords:
            final +=seg           
    final = jieba.cut(final, cut_all=False) #上面循环得到的是一个大字符串,这里要再分词
    final_2= ''
    for seg in final:     #这个循环是去除里面的空格,我也不知道为啥有空格,你们看实际情况。
        if seg !='':
            final_2 += seg           
    final_2 = jieba.cut(final_2, cut_all=False)
    freq=nltk.FreqDist(final_2)          #这个就是获取词频的函数调用了,和上面获取停用词库类似。
    puts_1=open('D:/编程project/new_1913206138_worddist.txt','w',encoding='utf-8')
    puts_1.writelines('以下是词频结果'+'\n')
    for key, val in sorted(freq.items(), key=lambda x: (x[1], x[0]), reverse=True):
        work=(str(key) + ':' + str(val))
        work=work.replace('’','').replace('‘','').replace('?','')
        puts_1.write(work + '\n')
    puts_1.close()
    print("统计词频及写入文件结束!")  #这边因为整体代码不止词频统计,这边能看到词频是不是完成写入了。

3.4针对词频生成词云

def ciyun_get(data):
    stopwords=get_stopwords()       #用获取到的频率最高的词中去除的无意义词
    word = jieba.cut(data, cut_all=False)
    final=''
    for seg in word:
        if seg not in stopwords:
            final+=seg
    final = jieba.cut(final, cut_all=False)
    stopwords_2 = {}.fromkeys(['章节', '目录', '后汉书', '一章', '』', '『', ' ','”','“','"'])
    final_2= ''
    for seg in final:
        if seg not in stopwords_2:
            final_2 += seg
    final_2 = jieba.cut(final_2, cut_all=False)
    #上面的代码任然是去除停用词和一下我爬到的一些没用的东西
    background_image=np.array(Image.open('D:/壁纸/cipin_1.png')) #如下图
    txt=(' '.join(final_2))
    wcd=WordCloud(background_color='white',mask=background_image,
                  max_font_size=40, max_words=4000,
                  margin=2,font_path="C:/Windows/Fonts/simfang.ttf",
                  ).generate(txt).to_file('cipin-yuntu.png')  #这个是写成文件,会在你当前目录下生成。
    image_colors=ImageColorGenerator(background_image)
    plt.imshow(wcd.recolor(color_func=image_colors),interpolation="bilinear") 
    #这两行代码的意思就是从图片中提取到的颜色用到词云的颜色上
    plt.axis('off')
    plt.show   #显示词云

这个就是要用到的词云的显示模板,注意,图片的非图形部分一定要是空白背景,不然生成的词云就不是特定的形状了。用美图秀秀就可以抠图了,很简单!
在这里插入图片描述
这个就是我生成的词云了
在这里插入图片描述

3.5做情感正负面分析并生成对应柱状图

先上代码:
分析在代码下面

def get_clueimage():
    fpath = 'D:/编程project/后汉书_译文'
    flist = os.listdir(fpath)  # 得到文件夹下的所有文件名称
    data_2 = []
    data_3 = []
    for file in flist:  # 获取每篇文章的名字
        file = file.replace('《', '').replace('》', '').replace('_译文.json', '')
        file = file.replace('后汉书·', '').replace('志·', '').replace('列传·', '')
        file = file.replace('.json', '').replace('本纪·', '')
        data_3.append(file)
    n = 0  # 对文章名的计数器
    st = []  # 存每篇文章总体的平均情感值
    for file in flist:  # 遍历文件夹
        fpath_2 = fpath + '/' + file
        of = open(fpath_2, 'r', encoding='utf-8')  # 打开文件
        diclist = json.load(of)
        of.close()
        data_1 = str(diclist['content'])
        content_1 = SnowNLP(data_1)
        sw = []  # 存一篇文章的每个句子的情感值
        for i in range(0, len(content_1.sentences)):
            content_2 = SnowNLP(content_1.sentences[i])
            sw.append(content_2.sentiments)
        ave_1 = np.mean(sw)
        st.append(ave_1)
        # print(data_3[n], '情感正负面平均值:{}'.format(ave_1))
        # n = n + 1
        #上两行代码打印出每篇具体的情感值
    fig, ax = plt.subplots(figsize=(12, 7))
    ax.bar(data_3,             #横坐标
           st,                 #纵坐标
           width=0.06,         # 柱子宽度,默认0.8,两根柱子中心的距离默认为1.0
           align="center",     # 柱子的对齐方式,'center' or 'edge'
           color="blue",       # 柱子颜色
           edgecolor="blue", # 柱子边框的颜色
           linewidth=2.0)      # 柱子边框线的大小
    plt.xticks(data_3, rotation=90, fontsize=4)  # 这里是调节横坐标的倾斜度,rotation是度数
    plt.ylabel('情感正负面平均值', fontsize=10)
    plt.xlabel('本纪', fontsize=10)
    ax.set_title('史书情感统计图', fontsize=15)
    plt.show()

其实我感觉已经很详细了,先说一下我走的弯路吧,我先是把这些文本划分成一个个句子存进列表里面的,然后做循环,进行情感分析,然后对这篇文章的情感值做平均。但是中文是不能这么进行情感分析的,当然了,英文也不能。这样得到的值差异太大了,你们可以尝试一下。划分的部分代码先贴出来。

pattern = r',|。|! |? '  # 以标点进行划分
     for i in range(130):
         result_lists = re.split(pattern, data_2[i])
         data_4.append(result_lists)

这里面的data_2是130篇史书的字符串,这样能划分成一个个句子。但会有空字符串,下面就是去除空字符串的代码。

for i in data_4:
         while '' in i:  # 去除空字符串
             i.remove('')
print(data_4[3])

总结

好了好了,上最后的代码吧
可以自己一步一步调试。

import json
import jieba
import nltk
import os
from wordcloud import WordCloud,ImageColorGenerator
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from snownlp import SnowNLP
from snownlp import SnowNLP
from pylab import *

#处理统计图中中文会出现乱码的问题
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
def get_txt():
    fpath = 'D:/编程project/后汉书_译文'
    flist = os.listdir(fpath)  # 得到文件夹下的所有文件名称
    data_2 = ''
    for file in flist:  # 遍历文件夹
        fpath_2 = fpath + '/' + file
        of = open(fpath_2, 'r', encoding='utf-8')  # 打开文件
        diclist = json.load(of)
        of.close()
        data_1 = str(diclist['content'])
        data_2 = data_1 + data_2
    return data_2

def get_stopwords():
    files=open('D:/编程project/1913206138_stopword .txt','r').read()
    return files

def get_first_stopwords():     #获得没去除停用词的词频文档,进行构建停用词库
    data=get_txt()
    word = jieba.cut(data, cut_all=False)
    freq = nltk.FreqDist(word)
    puts_1=open('D:/编程project/make_stopwords.txt','w',encoding='utf-8')
    puts_1.writelines('以下是词频结果'+'\n')
    for key, val in sorted(freq.items(), key=lambda x: (x[1], x[0]), reverse=True):
        work=(str(key) + ':' + str(val))
        work=work.replace('’','').replace('‘','').replace('?','')
        puts_1.write(work + '\n')
    puts_1.close()

def jiebafc(data,stopwords):
    word = jieba.cut(data, cut_all=False)
    final=''
    for seg in word:
        if seg not in stopwords:
            final +=seg
    final = jieba.cut(final, cut_all=False)
    final_2= ''
    for seg in final:
        if seg !='':
            final_2 += seg
    final_2 = jieba.cut(final_2, cut_all=False)
    freq=nltk.FreqDist(final_2)
    puts_1=open('D:/编程project/new_1913206138_worddist.txt','w',encoding='utf-8')
    puts_1.writelines('以下是词频结果'+'\n')
    for key, val in sorted(freq.items(), key=lambda x: (x[1], x[0]), reverse=True):
        work=(str(key) + ':' + str(val))
        work=work.replace('’','').replace('‘','').replace('?','')
        puts_1.write(work + '\n')
    puts_1.close()
    print("统计词频及写入文件结束!")

def ciyun_get(data):
    stopwords=get_stopwords()       #用获取到的频率最高的词中去除的无意义词
    word = jieba.cut(data, cut_all=False)
    final=''
    for seg in word:
        if seg not in stopwords:
            final+=seg
    final = jieba.cut(final, cut_all=False)
    stopwords_2 = {}.fromkeys(['章节', '目录', '后汉书', '一章', '』', '『', ' ','”','“','"'])
    final_2= ''
    for seg in final:
        if seg not in stopwords_2:
            final_2 += seg
    final_2 = jieba.cut(final_2, cut_all=False)
    background_image=np.array(Image.open('D:/壁纸/cipin_1.png'))
    txt=(' '.join(final_2))
    wcd=WordCloud(background_color='white',mask=background_image,
                  max_font_size=40, max_words=4000,
                  margin=2,font_path="C:/Windows/Fonts/simfang.ttf",
                  ).generate(txt).to_file('cipin-yuntu.png')
    image_colors=ImageColorGenerator(background_image)
    plt.imshow(wcd.recolor(color_func=image_colors),interpolation="bilinear")
    plt.axis('off')
    plt.show

def get_clueimage():
    fpath = 'D:/编程project/后汉书_译文'
    flist = os.listdir(fpath)  # 得到文件夹下的所有文件名称
    data_2 = []
    data_3 = []
    for file in flist:  # 获取每篇文章的名字
        file = file.replace('《', '').replace('》', '').replace('_译文.json', '')
        file = file.replace('后汉书·', '').replace('志·', '').replace('列传·', '')
        file = file.replace('.json', '').replace('本纪·', '')
        data_3.append(file)
    n = 0  # 对文章名的计数器
    st = []  # 存每篇文章总体的平均情感值
    for file in flist:  # 遍历文件夹
        fpath_2 = fpath + '/' + file
        of = open(fpath_2, 'r', encoding='utf-8')  # 打开文件
        diclist = json.load(of)
        of.close()
        data_1 = str(diclist['content'])
        content_1 = SnowNLP(data_1)
        sw = []  # 存一篇文章的每个句子的情感值
        for i in range(0, len(content_1.sentences)):
            content_2 = SnowNLP(content_1.sentences[i])
            sw.append(content_2.sentiments)
        ave_1 = np.mean(sw)
        st.append(ave_1)
        # print(data_3[n], '情感正负面平均值:{}'.format(ave_1))
        # n = n + 1
        #上两行代码打印出每篇具体的情感值
    fig, ax = plt.subplots(figsize=(12, 7))
    ax.bar(data_3,             #横坐标
           st,                 #纵坐标
           width=0.06,         # 柱子宽度,默认0.8,两根柱子中心的距离默认为1.0
           align="center",     # 柱子的对齐方式,'center' or 'edge'
           color="blue",       # 柱子颜色
           edgecolor="blue", # 柱子边框的颜色
           linewidth=2.0)      # 柱子边框线的大小
    plt.xticks(data_3, rotation=90, fontsize=4)  # 这里是调节横坐标的倾斜度,rotation是度数
    plt.ylabel('情感正负面平均值', fontsize=10)
    plt.xlabel('本纪', fontsize=10)
    ax.set_title('史书情感统计图', fontsize=15)
    plt.show()

if __name__ == '__main__':
    data=get_txt()
    stopword=get_stopwords()
    jiebafc(data,stopword)
    ciyun_get(data)
    get_clueimage()

在这里插入图片描述

一步一步,做大做强,送给你们。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值