18  中文分词

中文文本不像英文那样用空格分隔单词。因此,处理中文文本的第一步往往就是分词——将连续的句子切分成有意义的词语。本章介绍 jieba 分词库的基本使用。

18.1 安装 jieba

jieba 是第三方库,需要先安装:

pip install jieba

安装完成后,在 Python 中就可以导入使用了。

18.2 jieba分词

  1. 一般用jieba.cut()jieba.lcut()分词即可。 cut()返回生成器1lcut()返回列表。
  2. jieba.posseg.cut()jieba.posseg.lcut()在分词的同时标注词性(part of speech)。
import jieba
# 精确模式
text = '我来到北京清华大学'
words = jieba.lcut(text)
print(words)

# 全模式
words = jieba.lcut(text, cut_all=True)
print(words)
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\HUAWEI\AppData\Local\Temp\jieba.cache
Loading model cost 1.153 seconds.
Prefix dict has been built successfully.
['我', '来到', '北京', '清华大学']
['我', '来到', '北京', '清华', '清华大学', '华大', '大学']

jieba.posseg 可以在分词(seg,segmentation)的同时标注每个词的词性(pos,part of speech):

import jieba.posseg as pseg

text = '我来到北京清华大学'
words = pseg.lcut(text)
for w in words:
    print(f'{w.word}  {w.flag}')
我  r
来到  v
北京  ns
清华大学  nt
图 18.1: 部分词性标记符号含义

jieba还有其他分词模式:

  • 全模式,将句子中所有可能的词都切分出来,可能产生冗余的分词结果,不常用。 在jieba.cut()jieba.lcut()中设定参数cut_all = True就是全模式。
  • 搜索引擎模式,在精确模式的基础上,在精确模式的基础上,对长词再次切分,提高召回率(词语被命中的可能性),适用于搜索引擎技术。用jieba.cut_for_search()jieba.lcut_for_search()实现。
  • paddle模式,用深度学习框架PaddlePaddle分词。需安装paddlepaddle-tiny(pip install paddlepaddle-tiny==1.6.1),jieba版本>=0.4。
import jieba

# 全模式
text = '我来到北京清华大学'
words = jieba.lcut(text, cut_all=True)
print(words)
['我', '来到', '北京', '清华', '清华大学', '华大', '大学']

18.3 去停用词

分词结果中包含很多高频但对分析无意义的词,如“的”“了”“在”“是”等。这些词称为停用词(stop words),需要在进一步分析前去除。

停用词表可以通过网络搜索获得,也可以通过对本地文本数据的词频分析获得。 有时还需要考虑分析的具体文本数据。 例如,如果分析游戏《黑神话·悟空》的Staem评论,可能需要将“黑神话”“悟空”等列为停用词; 如果分析美国驻华大使馆的官方微博文本,往往需要将“美国”列为停用词。

用列表推导式就能去除列表中的停用词。

# 从文件读取停用词表
# 用集合set存储停用词表,查找速度比列表快
with open(stopwords_file, 'r', encoding='utf-8') as f:
        stopwords = set(line.strip() for line in f)
# 假设words是列表,各元素是分词后的一个个词元token
result = [w for w in words if w not in stopwords]

18.4 自定义词典

jieba 内置的词典很全面,但某些领域专有词可能没有被收录。

jieba.add_word() 可以将在程序中动态修改词典,把新词添加到词典中:

text = '原神是一款开放世界游戏'
print('添加前:', jieba.lcut(text))

jieba.add_word('原神')
jieba.add_word('开放世界')
print('添加后:', jieba.lcut(text))
添加前: ['原神', '是', '一款', '开放', '世界', '游戏']
添加后: ['原神', '是', '一款', '开放世界', '游戏']

如果要添加大量词语,可以准备一个词典文件,用 jieba.load_userdict() 加载。 词典文件的每行记录一个词,格式为 词语 词频 词性。 词频和词性都是为分词提供辅助信息的,可省略。

例如,my_dict.txt内容如下

原神 5 n
开放世界 3 n
jieba.load_userdict('my_dict.txt')
text = '原神是一款开放世界游戏'
print(jieba.lcut(text))
['原神', '是', '一款', '开放', '世界', '游戏']

涉及文件读写的代码,一般用相对路径,这要求相关文件位于同一个项目文件夹中。

18.5 词频统计

分词 + 去停用词后,常做的下一步是统计词频——看看哪些词出现次数最多。

text = '中国社会各阶级的分析是毛泽东的一篇重要文章。中国社会各阶级的分析分析了中国社会的各个阶级。'

# 分词
words = jieba.lcut(text)

# 去停用词
stopwords = {'的', '是', '了', '。'}
words = [w for w in words if w not in stopwords]

# 词频统计(用字典)
freq = {}
for w in words:
    if w in freq:
        freq[w] += 1
    else:
        freq[w] = 1

# 排序输出前 5 个
sorted_freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
print(sorted_freq[:5])
[('中国', 3), ('社会', 3), ('阶级', 3), ('分析', 3), ('各', 2)]

18.6 词云图

词云是一种直观展示文本关键词的方式——词出现频率越高,在图中显示的越大。

pip install wordcloud安装 wordcloud 库。

生成词云的流程:分词 → 去停用词 → 生成词云 → 保存图片。

注意: wordcloud 默认不支持中文,因此必须指定中文字体路径,否则所有中文会显示为方框。

from wordcloud import WordCloud

# 字体路径(根据系统选择)
# Windows: C:/Windows/Fonts/simhei.ttf(黑体)或 simsun.ttc(宋体)
# Mac:     /System/Library/Fonts/PingFang.ttc
# Linux:   /usr/share/fonts/truetype/wqy/wqy-zenhei.ttc

font_path = 'C:/Windows/Fonts/simhei.ttf'

# 用WordCloud类创建一个对象wc
wc = WordCloud(
    font_path=font_path,
    width=800,
    height=600,
    background_color='white'
)

# wc的方法generate()接收的文本需要是用空格分隔的词语
text_for_cloud = ' '.join(words)
wc.generate(text_for_cloud)

# 保存为图片
wc.to_file('词云.png')

词云的样式(颜色、形状、背景色等)可通过 WordCloud 的参数调整,具体可查阅官方文档。

图 18.2: 词云示意图。

18.7 练习

  1. 使用 jieba 对《中国社会各阶级的分析》全文进行分词。统计(去掉必要的停用词后)出现频率最高的 10 个词。

  2. 重复1,使用词性标注,只保留名词,然后再统计词频。

  3. 将“王者荣耀”添加为自定义词,然后对“王者荣耀是一款手机游戏”进行分词,对比添加前后的结果差异。


  1. 生成器是一种惰性计算的可迭代对象↩︎