JB的Python之旅-数据分析篇-jieba&wordcloud(词云)

一句话概括

本文通过实战围绕介绍使用jieba库进行中文分词,并使用collections模块进行分词的次数统计,介绍了wordcloud词云库的使用方式;

前言

爬虫获取数据后,就需要数据分析了,那数据怎么处理?用到什么数据?一起来看看吧~

最近又重新看回了全职高手这部小说及动漫,犹记得当时被刘老师安利,说这小说很好看,后来腾讯买了版权,出了动画,虽然有删减,但依然有空看几遍;
但有时候也在想,为什么自己那么沉迷这小说,除了里面写的游戏基本跟读书时玩的DNF一样外,应该没其他特别的;
既然如何?有没有办法把小说里的内容进行提取关键字,然后再弄个词云?
这不就找到了jieba&wordcloud库吗?

1 数据准备:

直接网上找全职高手txt下载,一大堆,解压后获取到txt文件;
全职高手txt小说下载地址

1.2 读取全职高手文本

with open("quanzhigaoshou.txt") as f:
    qzgs_text = f.read()
print(len(qzgs_text))
复制代码

结果直接执行,报错了

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》 没毛病,编码问题,open时指定下utf-8即可:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》 看了下,整个文本的长度有 8623554 个字节,数据量非常可观,感觉题材会很丰富的~

这是不是就准备好了呢?
答案是NO,因为文本内容是这样的:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

从上图可以看出,文本里面会有各种符号跟广告,目前这步,要做的就是把各种标点符号干掉先;

with open("quanzhigaoshou.txt",encoding='utf-8') as f:
    qzgs_text = f.read()
pattern = re.compile('[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?“”、~@#¥%……&*()(\d+)]+')
new_qzgs_text = pattern.sub("",qzgs_text)
print(new_qzgs_text)
复制代码

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

到此,字符串搞定啦~

1.3 jieba中文分词库

因为我们的样例都是中文,因此就选用据说是最好的python中文分词库jieba

  • GitHub仓库:https://github.com/fxsjy/jieba
  • 官方文档:https://pypi.org/project/jieba/
  • 一个比较详细的教程:https://blog.csdn.net/fontthrone/article/details/72782499

二话不说,直接安装一波先:

pip install jieba
复制代码

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

安装过程没什么好说的;目前暂未遇到问题

官方提供的特点:

  • 支持三种分词模式:
    • 精确模式,试图将句子最精确地切开,适合文本分析;
    • 全模式,把句子中所有的可以成词的词语都扫描出来,速度非常快,但是不能解决歧义;
    • 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

这里贴一个官方的例子:

import jieba

seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精确模式

seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")  # 搜索引擎模式
print(", ".join(seg_list))
复制代码

输出的结果:

【全模式】: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学
【精确模式/默认模式】: 我/ 来到/ 北京/ 清华大学
【搜索引擎模式】:小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, ,, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造
复制代码

从官网的例子可以看到,就一个cut参数里面放需要分词的字符串跟cu_all参数,是否打开全模式;
比如大傻叉,默认模式/精准模式,就是会辨识到大,傻,叉;
而全模式,则会变成大傻,傻叉,大傻叉这样
当然,这个结果是想象出来的,实际并非这样,具体原因未明,可能是没有入词库导致?

ok,了解到jieba如何使用,就来试试把:

qzgs_word = [word for word in jieba.cut(new_qzgs_text,cut_all=False) if len(word)>2]
#这看上去很长,但很好理解,获取分词,然后长度大于2个才算一个词;在遍历下,就能
复制代码

写个for把分词遍历下:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

没毛病,继续;

接下来就是统计同词词频,一般来说,会统计词出现的次数,也叫频次;

这块,有collections模块的Counter来实现;
Counter类的目的是用来跟踪值出现的次数
它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。

这里介绍下Counter类的一些方法:
1)创建

c = Counter()  # 创建一个空的Counter类
c = Counter('gallahad')  # 从一个可iterable对象(list、tuple、dict、字符串等)创建
c = Counter({'a': 4, 'b': 2})  # 从一个字典对象创建
c = Counter(a=4, b=2)  # 从一组键值对创建
复制代码

2)计数值的访问与缺失的键 当访问的健不存在时,返回0,否则就返回它的计数

c= Counter("abcdefgab")
print(c["a"])
print(c["c"])
print(c["h"])

输出的结果:
2
1
0
复制代码

3)计算器的更新(update和subtract) 可以使用一个iterable对象或者另一个Counter对象来更新键值。
计数器的更新包括增加和减少两种。其中,增加使用
update()**方法:

c= Counter("which")
c.update("witch")
print(c["h"])

d = Counter("watch")
c.update(d)
print(c["h"])

输出的结果:
3
4
复制代码

减少则使用**subtract()**方法:

c= Counter("which")
c.subtract("witch")
print(c["h"])

d = Counter("watch")
c.subtract(d)
print(c["a"])

输出的结果:
1
-1
复制代码

4)键的删除: 当计数值为0时,并不意味着元素被删除,删除元素应当使用del。

c= Counter("abcdcba")
print(c)

c["b"]=0
print(c)

del c["a"]
print(c)

输出的结果:
Counter({'a': 2, 'b': 2, 'c': 2, 'd': 1})
Counter({'a': 2, 'c': 2, 'd': 1, 'b': 0})
Counter({'c': 2, 'd': 1, 'b': 0})
复制代码

5)elements(): 返回一个迭代器。元素被重复了多少次,在该迭代器中就包含多少个该元素。元素排列无确定顺序,个数小于1的元素不被包含。

c = Counter(a=4, b=2, c=0, d=-2)
print(list(c.elements()))

输出的结果:
['a', 'a', 'a', 'a', 'b', 'b']
复制代码

6)most_common(): 返回一个TopN列表。如果n没有被指定,则返回所有元素。当多个元素计数值相同时,排列是无确定顺序的。

c= Counter("abracadabra")
print(c.most_common())
print(c.most_common(3))

输出的结果:
[('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]
[('a', 5), ('b', 2), ('r', 2)]
复制代码

还有copy跟集合算术操作,这里就不说明了,很简单;

扯远了,我们的目的是跟踪值出现的次数,根据上面的介绍,发现most_common()这个方法能符号要求;
根据上面most_common的介绍,会返回2个参数,一个是词,一个是次数,因此只需要把这两个玩意输出即可: c = Counter(qzgs_words) for word in c.most_common(50): word,freq = word print(word,freq) #50代表取的TOP50 输出的结果:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

嗯,想要的数据拿到了,但是这内容,是不是很奇怪?wwwmianhuatangla这玩意都出现了,还有小说网,看起来,是不是这种,是没有任何意义的,那我们还需要对数据进行处理,也叫数据清洗,就是定义一个过滤列表,把想过滤的词都扔进去,分词遍历后,把符合的元素进行移除即可:

invalid_words = ["所有人","看起来","小说网","wwwmianhuatangla","是不是","为什么","没什么","其他人","未完待续",
                "事实上","一时间","是因为","一瞬间","只不过","差不多","不至于","这时候","越来越","没想到","可不是","不得不","接下来",
                 "魄之力","俱乐部"]

for word in qzgs_words:
    if word in invalid_words:
        qzgs_words.remove(word)
复制代码

输出是这样的:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》 不知道为什么,wwwmianhuatangla这玩意还是一直存在,连boss都有,只是次数有所下降了,而临时方案是,则写多一个invalid_words_en,然后进行二次过滤,这样处理后,就完全把这两个英文过滤了;
《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

关于频次的讲解,大致就到这里;

接下来是介绍频率的统计,就是百分比,这个是通过jieba库里的analyse模块解决,支持直接读取文件过滤,即把不想要的分词丢在一个文件里,然后会自动过滤,函数是:extract_tags
jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())

  • sentence 为待提取的文本

  • topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20,简单理解就是提取多少个

  • withWeight 为是否一并返回关键词权重值,默认值为 False

  • allowPOS 仅包括指定词性的词,默认值为空,即不筛选

    invalid_words_file = “invalidwords.txt”

    #设置停用词 jieba.analyse.set_stop_words(invalid_words_file)

    #获取关键词频率 tags = jieba.analyse.extract_tags(qzgs_text,topK=100,withWeight=True) for tag in tags: print(tag) 输出的结果:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》 这里也有不少无效的内容,懒得添加了;

到这里,分词跟词频都了解到了,接下来,看词云吧~

2 词云

网上找了下词云的库,基本都用wordcloud,那我们也跟着用这个吧;

  • GitHub仓库:https://github.com/amueller/word_cloud
  • 官方文档:https://amueller.github.io/word_cloud/
  • 一个比较详细的教程:https://blog.csdn.net/fontthrone/article/details/72775865

pip安装一波:

pip install wordcloud
复制代码

但是JB在安装的时候报错了;

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

然后改用另外一种解决方案了,打开下面的链接:

http://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud 直接搜索wordcloud,JB用的是Windows系统,所以选择下载这个: wordcloud-1.4.1-cp36-cp36m-win_amd64.whl

下载后,直接运行,问题解决;(折腾一个小时了,坑~)

pip install wordcloud-1.4.1-cp36-cp36m-win_amd64.whl
复制代码

这个库的使用,关键在于WordCloud构造函数

def __init__(self, font_path=None, width=400, height=200, margin=2,
             ranks_only=None, prefer_horizontal=.9, mask=None, scale=1,
             color_func=None, max_words=200, min_font_size=4,
             stopwords=None, random_state=None, background_color='black',
             max_font_size=None, font_step=1, mode="RGB",
             relative_scaling=.5, regexp=None, collocations=True,
             colormap=None, normalize_plurals=True):
复制代码

参数讲解:

  • font_path:字体路径,就是绘制词云用的字体,比如monaco.ttf
  • width:输出的画布宽度,默认400像素
  • height:输出的画布宽度,默认200像素
  • margin:画布偏移,默认2像素
  • prefer_horizontal : 词语水平方向排版出现的频率,默认0.9,垂直方向出现概率0.1
  • mask:如果参数为空,则使用二维遮罩绘制词云。如果 mask 非空,设置的宽高值将 被忽略,遮罩形状被 mask,除全白(#FFFFFF)的部分将不会绘制,其余部分会用于绘制词云。 如:bg_pic = imread(‘读取一张图片.png’),背景图片的画布一定要设置为白色(#FFFFFF), 然后显示的形状为不是白色的其他颜色。可以用ps工具将自己要显示的形状复制到一个纯白色 的画布上再保存,就ok了。
  • scale:按照比例进行放大画布,如设置为1.5,则长和宽都是原来画布的1.5倍
  • color_func:生成新颜色的函数,如果为空,则使用 self.color_func
  • max_words:显示的词的最大个数
  • min_font_size:显示的最小字体大小
  • stopwords:需要屏蔽的词(字符串集合),为空使用内置STOPWORDS
  • random_state:如果给出了一个随机对象,用作生成一个随机数
  • background_color:背景颜色,默认为黑色
  • max_font_size:显示的最大的字体大小
  • font_step:字体步长,如果步长大于1,会加快运算但是可能导致结果出现较大的误差
  • mode:当参数为”RGBA”,并且background_color不为空时,背景为透明。默认RGB
  • relative_scaling:词频和字体大小的关联性,默认5
  • regexp:使用正则表达式分隔输入的文本
  • collocations:是否包括两个词的搭配
  • colormap:给每个单词随机分配颜色,若指定color_func,则忽略该方法
  • normalize_plurals:是否删除尾随的词语

常用的方法:

  • fit_words(frequencies) //根据词频生成词云
  • generate(text) //根据文本生成词云
  • generate_from_frequencies(frequencies[, …]) #根据词频生成词云
  • generate_from_text(text) #根据文本生成词云
  • process_text(text) #将长文本分词并去除屏蔽词 (此处指英语,中文分词还是需要自己用别的库先行实现,使用上面的 fit_words(frequencies) )
  • recolor([random_state, color_func, colormap]) #对现有输出重新着色。重新上色会比重新生成整个词云快很多。
  • to_array() #转化为 numpy array
  • to_file(filename) #输出到文件

看完后贼难受的,而且真没多少记得,懵逼吧,先从简单的例子入手吧:

from wordcloud import WordCloud

data = "所有人,看起来,说网,不是,什么"

wc= WordCloud(background_color="white")
wc = wc.generate(data)
wc.to_file("111.jpg")
复制代码

代码能执行,执行的效果是这样的:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

看上去,好像是没有字体导致的,加个字体试试,因为JB是用WINDOWS,直接那系统的字体了;

data = "所有人,看起来,说网,不是,什么"

wc= WordCloud(background_color="white",font_path="C:/Windows/Fonts/STFANGSO.ttf")
wc = wc.generate(data)
wc.to_file("111.jpg")
复制代码

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

ok,现在可以了~
有个效率的问题,现在是每次保存到111.jpg,然后手动打开,这个过程虽然不麻烦,但是次数一到就觉得厌倦了,那能否自动弹出图片?答案是有的,需要matplotlib.pyplot这个库:

from wordcloud import WordCloud,
import matplotlib.pyplot as plt

data = "所有人,看起来,说网,不是,什么"
wc= WordCloud(background_color="white",font_path="C:/Windows/Fonts/STFANGSO.ttf")
wc = wc.generate(data)

#显示词云图片
plt.imshow(wc)
plt.show()

#保存图片
wc.to_file("111.jpg")
复制代码

修改成这样后,执行后就自动弹出图片了,图片长这样的:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

居然带有坐标,这多丑啊,怎么去除?

#显示词云图片
plt.imshow(wc)
plt.axis("off")
#axis函数接收一个list,设定横纵坐标尺度,list各个参数分别代表[X初始刻度,X终止刻度,Y起始刻度,Y终止,off就是不显示坐标尺寸
plt.show()
复制代码

只需要加上plt.axis(“off”)即可:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

但是网上看到别人的是这样的,为啥我们的差距那么大?

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

那我们也来找一张图片,如下(正经图正经图):

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

然后改一波代码把:

#data自己定义哈,为了显示效果,用尽可能多的数据了

#字体路径
path = "C:/Windows/Fonts/STFANGSO.ttf"

#读入背景图片,就是上面那张图片
bg_pic = imread("11.jpg")     

wc= WordCloud(background_color="white",font_path=path,mask=bg_pic)
wc = wc.generate(data)

#显示词云图片
plt.imshow(wc)
plt.axis("off")
#axis函数接收一个list,设定横纵坐标尺度,list各个参数分别代表[X初始刻度,X终止刻度,Y起始刻度,Y终止,off就是不显示坐标尺寸
plt.show()

#保存图片
wc.to_file("111.jpg")
复制代码

效果如下:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

整体效果出来了,这字体颜色貌似是随机的,要不让字体跟随着图片颜色变化?

#读入背景图片
bg_pic = imread("11.jpg")
#从背景图片生成颜色值
image_colors = ImageColorGenerator(bg_pic)

wc= WordCloud(background_color="black",font_path=path,mask=bg_pic,color_func=image_colors)
复制代码

结果是这样的:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

尼玛,忘记图片大部分是白色的。。那把背景改黑色吧:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

剩下的,就是怎选图跟选用字体以后一些参数细节,这块不打算详细说了,也不想纠结了,大致知道用法即可;

把整体代码封装下,最后代码如下:

import re
import jieba.analyse
from collections import Counter
from wordcloud import WordCloud, ImageColorGenerator,STOPWORDS
import matplotlib.pyplot as plt
from scipy.misc import imread

#这个文件是统计频率时,把需要过滤的词放到这个文件里面
#invalid_words_file = "invalidwords.txt"


def get_Words():
    #读取TXT文件获取文本里的内容
    with open("quanzhigaoshou.txt", encoding='utf-8') as f:
        qzgs_text = f.read()
    #制定正则规则,把各种符号去掉,最后生成没有各种符号的字符串
    pattern = re.compile('[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?“”、~@#¥%……&*()(\d+)]+')
    new_qzgs_text = pattern.sub("", qzgs_text)

    #获取分词
    qzgs_words = [word for word in jieba.cut(new_qzgs_text, cut_all=False) if len(word) > 2]

    # #设置停用词
    # jieba.analyse.set_stop_words(invalid_words_file)
    #
    # #获取关键词频率
    # tags = jieba.analyse.extract_tags(qzgs_text,topK=100,withWeight=True)
    # for tag in tags:
    #     print(tag)

    #制定需要过滤的词
    invalid_words_zh = ["所有人", "看起来", "小说网", "是不是", "为什么", "没什么", "其他人", "未完待续",
                        "事实上", "一时间", "是因为", "一瞬间", "只不过", "差不多", "不至于", "这时候", "越来越", "没想到", "可不是", "不得不", "接下来",
                        "魄之力", "俱乐部", "挑战赛", "全明星", "擂台赛", "季后赛","boss", "wwwmianhuatangla"]

    #进行过滤操作
    for word in qzgs_words:
        if word in invalid_words_zh:
            qzgs_words.remove(word)

    # 获取分词频数
    # c = Counter(qzgs_words)
    # for word in c.most_common(50):
    #     word,freq = word
    #     print(word,freq)

    #空格分隔下
    data = r" ".join(qzgs_words)
    return data

def generate_wc(data):
    # 字体路径
    path = "C:/Windows/Fonts/STFANGSO.ttf"
    # 读入背景图片
    bg_pic = imread("bjt.jpg")
    # 从背景图片生成颜色值
    image_colors = ImageColorGenerator(bg_pic)
    # 生成词云,后面的generate是根据文本生成词云
    wc = WordCloud(background_color="black", font_path=path, mask=bg_pic, color_func=image_colors)
    wc = wc.generate(data)
    # 显示词云图片
    plt.imshow(wc)
    plt.axis("off")
    # axis函数接收一个list,设定横纵坐标尺度,list各个参数分别代表[X初始刻度,X终止刻度,Y起始刻度,Y终止,off就是不显示坐标尺寸
    plt.show()
    # 保存图片
    wc.to_file("result.jpg")


if __name__ =="__main__":
    data=get_Words()
    generate_wc(data)
复制代码

底图一换,就成这样:

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

挑个好字体跟好颜色,估计更好看,这字体太模糊了=。=

小结

虽然做的比较丑,但算是达到目的了,折腾了不少时间,主要还是在环境搭建那块,当然看资料也算,虽然网上很多教程,但大部分都是直接扔一堆代码过来的,连注释都比较少,对于新同学不是很友好;
本文通过实战围绕介绍使用jieba库进行中文分词,并使用collections模块进行分词的次数统计,介绍了wordcloud词云库的使用方式;

杂七杂八

中文分词,用jieba,那英文分词呢?
有NLTK,基本逻辑跟中文分词类似:

  • 读取文件->过滤特殊符号->分词->词形还原->统计词频->词云
    词形还原什么鬼,简单看了下,没太懂,大致有个库能通过是过去式还是进行时来还原部分词,大致是这样;

好了,本章介绍了,下章会结合爬取拉钩等招聘网站,来介绍numpy,pandas和matplotlib进行数据分析;

谢谢大家!~

《JB的Python之旅-数据分析篇-jieba&wordcloud(词云)》

    原文作者:python入门
    原文地址: https://juejin.im/post/5b1e95286fb9a01e336439fc
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞