本章详细介绍了中文分词以及清洗的常用方法、中文词频统计方法以及词云可视化方法等内容。
无
1.中文分词概述
2.结巴分词应用
3.词频统计应用
4.中文分词实战
中文分词指的是将一个汉字序列切分成一个一个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。
学者提出了很多关于统计模型的中文分词方法,主要有以下几种:
- 基本思想是基于词典匹配,将待分词的中文文本根据一定的规则切分和调整,然后跟词典中的词语进行匹配,匹配成功则按照词典的词进行分词,匹配失败则调整或者重新选择,如此反复循环即可。
- 基本思想是通过专家系统或者机器学习神经网络方法模拟人的理解能力。
- 前者是通过专家对分词规则的逻辑推理并总结形成特征规则,不断迭代完善规则,其受到资源消耗大和算法复杂度高的制约;
- 后者是通过机器模拟人类理解的方式,虽然可以取得不错的效果,但是依旧受训练时间长和过度拟合等因素困扰。
- 基本思想是通过不同的数学统计模型进行分析
- 基于隐马尔可夫模型的中文分词方法;
- 基于最大熵模型的中文分词方法;
- 基于条件随机场模型的中文分词方法。
本章将基于隐马尔可夫模型
和自定义词典
结合的方法,其在分词速度、歧义分析、新词发现和准确率方面都具有良好的效果
结巴分词(jieba分词)是基于Python 的中文分词工具,其分词功能强大且安装方便。该分词工具支持三种分词模式:
安装命令
pip install jieba -i https://pypi.tuna.tsinghua.edu.cn/simple/
中文分词方法
方法一、jieba.cut()
jieba.cut(sentence, cut_all=False, HMM=True)
- sentence:待分词的字符串
- cut_all:是否采用全模式,分全模式 True、精确模式False
- HMM:是否使用HMM模型 (隐马尔科夫模型),基本少用
jieba.cut()返回的结构是一个可迭代的 generator。
1. 精确模式(默认 cut_all=False)
默认是精确模式,适合文本分析
import jieba s = "我来到中国北京故宫博物馆" segList = jieba.cut(s) print(segList) for segListi in segList: print(segListi)
我
来到
中国
北京故宫
博物馆
2. 全模式(cut_all=True)
全模式,扫描所有可以成词的词语,速度非常快,不能解决歧义
import jieba s = "我来到中国北京故宫博物馆" segList = jieba.cut(s, cut_all=True) print(segList) for segListi in segList: print(segListi)
我
来到
中国
北京
北京故宫
故宫
博物
博物馆
方法二、jieba.lcut()
jieba.lcut(sentence, cut_all=False, HMM=True)
- sentence:待分词的字符串
- cut_all:是否采用全模式,分全模式 True、精确模式False
- HMM:是否使用HMM模型 (隐马尔科夫模型),基本少用
jieba.lcut()方法直接返回列表(List)。
import jieba s = "我来到中国北京故宫博物馆" segList = jieba.lcut(s) print(segList)
['我', '来到', '中国', '北京故宫', '博物馆']
方法三、jieba.cut_for_search()
jieba.cut_for_search(sentence, HMM=True)
- sentence:待分词的字符串
- HMM:是否使用HMM模型 (隐马尔科夫模型),基本少用
jieba.cut_for_search()返回的结构是一个可迭代的 generator。
搜索引擎模式,对长词再次切分,粒度比较细,提高召回率,适合用于搜索引擎分词。
import jieba s = "我来到中国北京故宫博物馆" segList = jieba.cut_for_search(s) print(segList) for segListi in segList: print(segListi)
我
来到
中国
北京
故宫
北京故宫
博物
博物馆
方法四、jieba.lcut_for_search()
jieba.lcut_for_search(sentence, HMM=True)
- sentence:待分词的字符串
- HMM:是否使用HMM模型 (隐马尔科夫模型),基本少用
jieba.lcut_for_search()方法直接返回列表(List)。
import jieba s = "我来到中国北京故宫博物馆" segList = jieba.lcut_for_search(s) print(segList)
['我', '来到', '中国', '北京', '故宫', '北京故宫', '博物', '博物馆']
词典定义方法
无论哪种分词都不能做到100%的准确,尤其是对一些歧义词的处理,比如“如果放在数据库中将会出错。”:
import jieba s = "如果放在数据库中将会出错。" segList = jieba.lcut(s) print(segList)
['如果', '放在', '数据库', '中将', '会', '出错', '。']
为解决以上问题,jieba 提供 动态修改词频 和 添加词典文件 两种方法。
方法一、动态修改词频 jieba.suggest_freq()
可以将自定义词典逐个插入词典
jieba.suggest_freq(segment, tune=True)
- segment:新增词组,可以为 单字符串 / 元组 / 列
- tune:是否分离出来
动态修改词频,调节单个词语的词频,使其能(不能)被分出来。
import jieba jieba.suggest_freq(['中', '将'], tune=True) s = "如果放在数据库中将会出错。" segList = jieba.lcut(s) print(segList)
['如果', '放在', '数据库', '中', '将', '会', '出错', '。']
方法二、添加词典文件 jieba.load_userdict()
可以将自定义词典放在一个文本文件中,实现批量添加到词典。
jieba.load_userdict(file_name)
- file_name:词典文件路径及名称
添加词典文件,文件需要有特定格式,并且为UTF-8编码。
import jieba jieba.load_userdict(r"./user_dict.txt") s = "今天很高兴在课室和大家交流学习。" segList = jieba.lcut(s) print(segList)
['今天', '很高兴', '在', '课室', '和', '大家', '交流学习', '。']
关键词提取方法
关键词就是最能够反映出文本主题或者意思的词语,关键词抽取就是从文本里面把跟这篇文档意义最相关的一些词抽取出来。
但是网络上写文章的人不会像写论文那样告诉你本文的关键词是什么,这个时候就需要利用计算机自动抽取出关键词,算法的好坏直接决定了后续步骤的效果。
本文将基于TF-IDF关键词抽取算法展开介绍,先抽取出候选词,然后对各个候选词进行打分,然后输出topK个分值最高的候选词作为关键词。
from jieba import analyse # 引入TF-IDF关键词抽取接口 tfidf = analyse.extract_tags s = ''' 此外,公司拟对全资子公司吉林欧亚置业有限公司增资4.3亿元,增资后,吉林欧亚置业注册资本由7000万元增加到5亿元。 吉林欧亚置业主要经营范围为房地产开发及百货零售等业务。 目前在建吉林欧亚城市商业综合体项目。 2013年,实现营业收入0万元,实现净利润-139.13万元。 ''' kwList = tfidf(s,10, withWeight=True) ## s 表示待分词的字符串,10 表示显示前10个词组,withWeight=True 表示是否返回权重 for k, v in kwList: print('%s %s' % (k, v))
欧亚 0.7300142700289363
吉林 0.659038184373617
置业 0.4887134522112766
万元 0.3392722481859574
增资 0.33582401985234045
4.3 0.25435675538085106
7000 0.25435675538085106
2013 0.25435675538085106
139.13 0.25435675538085106
实现 0.19900979900382978
词性标注方法
词性标注就是对分词结果根据词性进行标记,在过滤特征词或者实体处理都是比较有用的。
import jieba s = "我来到中国北京故宫博物馆" words = jieba.posseg.cut(s) for word, flag in words: print('%s %s' % (word, flag))
我 r
来到 v
中国 ns
北京故宫 ns
博物馆 n
词性标注代码含义:
类型 | 代码 | 类型 | 代码 |
---|---|---|---|
1.名词 | n 名词 | 11.量词 | q 量词 |
1.名词 | nr 人名 | 11.量词 | qv 动量词 |
1.名词 | nr1 汉语姓氏 | 11.量词 | qt 时量词 |
1.名词 | nr2 汉语名字 | 12.副词 | d 副词 |
1.名词 | nrj 日语人名 | 13.介词 | p 介词 |
1.名词 | nrf 音译人名 | 13.介词 | pba 介词“把” |
1.名词 | ns 地名 | 13.介词 | pbei 介词“被” |
1.名词 | nsf 音译地名 | 14.连词 | c 连词 |
1.名词 | nt 机构团体名 | 14.连词 | cc 并列连词 |
1.名词 | nz 其它专名 | 15.助词 | u 助词 |
1.名词 | nl 名词性惯用语 | 15.助词 | uzhe 着 |
1.名词 | ng 名词性语素 | 15.助词 | ule 了 喽 |
2.时间词 | t 时间词 | 15.助词 | uguo 过 |
2.时间词 | tg 时间词性语素 | 15.助词 | ude1 的 底 |
3.处所词 | s 处所词 | 15.助词 | ude2 地 |
4.方位词 | f 方位词 | 15.助词 | ude3 得 |
5.动词 | v 动词 | 15.助词 | usuo 所 |
5.动词 | vd 副动词 | 15.助词 | udeng 等 等等 云云 |
5.动词 | vn 名动词 | 15.助词 | uyy 一样 一般 似的 般 |
5.动词 | vshi 动词“是” | 15.助词 | udh 的话 |
5.动词 | vyou 动词“有” | 15.助词 | uls 来讲 来说 而言 说来 |
5.动词 | vf 趋向动词 | 15.助词 | uzhi 之 |
5.动词 | vx 形式动词 | 15.助词 | ulian 连 (“连小学生都会”) |
5.动词 | vi 不及物动词(内动词) | 16.叹词 | e 叹词 |
5.动词 | vl 动词性惯用语 | 17.语气词 | y 语气词(delete yg) |
5.动词 | vg 动词性语素 | 18.拟声词 | o 拟声词 |
6.形容词 | a 形容词 | 19.前缀 | h 前缀 |
6.形容词 | ad 副形词 | 20.后缀 | k 后缀 |
6.形容词 | an 名形词 | 21.字符串 | x 字符串 |
6.形容词 | ag 形容词性语素 | 21.字符串 | xx 非语素字 |
6.形容词 | al 形容词性惯用语 | 21.字符串 | xu 网址URL |
7.区别词 | b 区别词 | 22.标点符号 | w 标点符号 |
7.区别词 | bl 区别词性惯用语 | 22.标点符号 | wkz 左括号,全角:( 〔 [ { 《 【 〖 〈 半角:( [ { < |
8.状态词 | z 状态词 | 22.标点符号 | wky 右括号,全角:) 〕 ] } 》 】 〗 〉 半角: ) ] { > |
9.代词 | r 代词 | 22.标点符号 | wyz 左引号,全角:“ ‘ 『 |
9.代词 | rr 人称代词 | 22.标点符号 | wyy 右引号,全角:” ’ 』 |
9.代词 | rz 指示代词 | 22.标点符号 | wj 句号,全角:。 |
9.代词 | rzt 时间指示代词 | 22.标点符号 | ww 问号,全角:? 半角:? |
9.代词 | rzs 处所指示代词 | 22.标点符号 | wt 叹号,全角:! 半角:! |
9.代词 | rzv 谓词性指示代词 | 22.标点符号 | wd 逗号,全角:, 半角:, |
9.代词 | ry 疑问代词 | 22.标点符号 | wf 分号,全角:; 半角: ; |
9.代词 | ryt 时间疑问代词 | 22.标点符号 | wn 顿号,全角:、 |
9.代词 | rys 处所疑问代词 | 22.标点符号 | wm 冒号,全角:: 半角: : |
9.代词 | ryv 谓词性疑问代词 | 22.标点符号 | ws 省略号,全角:…… … |
9.代词 | rg 代词性语素 | 22.标点符号 | wp 破折号,全角:—— -- ——- 半角:— ---- |
10.数词 | m 数词 | 22.标点符号 | wb 百分号千分号,全角:% ‰ 半角:% |
10.数词 | mq 数量词 | 22.标点符号 | wh 单位符号,全角:¥ $ £ ° ℃ 半角:$ |
消除停用词方法
文本分词中的去除停用词在数据预处理中是不可或缺的内容,针对待分词文本,通过匹配停用词、数字、单个字符、空格,对文本内容进行清洗。
import sys import re import jieba # 1.加载自定义分词词典 jieba.load_userdict("./user_dict.txt") # 2.读取待分词文本信息 fNews = "./体育news.txt" with open(fNews,'r',encoding='utf-8') as f: docList = f.read().split('\n') # 3.读取停用词 fStopwords = "./NLPIR_stopwords.txt" with open(fStopwords,'r',encoding='utf-8') as f: stopwordList = f.read().split('\n') # 4.遍历待分词文本信息,去除符合规则的词组 docResult = [] for docListi in docList: # jieba.cut()返回可迭代的 generator,使用list() 转换为列表对象 docListiCut = list(jieba.cut(docListi, cut_all=False)) for i in range(len(docListiCut))[::-1]: if docListiCut[i] in stopwordList: # 去除停用词 docListiCut.pop(i) elif docListiCut[i].isdigit(): # 去除数字 docListiCut.pop(i) elif len(docListiCut[i]) == 1: # 去除单个字符 docListiCut.pop(i) elif docListiCut[i] == " ": # 去除空字符 docListiCut.pop(i) docResult.extend(docListiCut) print(docResult)
['马晓旭', '意外', '受伤', '国奥', '警惕', '无奈', '大雨', '青睐', '殷家', '记者', '傅亚雨', '沈阳', '报道', '来到', '沈阳', '国奥队', '依然', '摆脱', '雨水', '困扰', '下午', '国奥队', '日常', '训练', '再度', '大雨', '干扰', '无奈', '之下', '队员', '慢跑', '分钟', '草草收场', '上午', '国奥队', '奥体中心', '外场', '训练', '阴沉沉', '气象预报', '显示', '当天', '下午', '沈阳', '大雨', '幸好', '队伍', '上午', '训练', '干扰', '下午', '球队', '抵达', '训练场', '大雨', '几个', '小时', '丝毫', '停下来', '试一试', '态度', '球队', '当天', '下午', '例行', '训练', '分钟', '天气', '转好', '迹象', '保护', '球员', '国奥队', '中止', '当天', '训练', '全队', '返回', '酒店', '训练', '足球队', '稀罕', '奥运会', '全队', '变得', '娇贵', '沈阳', '一周', '训练', '国奥队', '保证', '现有', '球员', '出现意外', '伤病', '情况', '影响', '正式', '比赛', '这一', '阶段', '控制', '训练', '受伤', '控制', '感冒', '疾病', '队伍', '放在', '位置', '抵达', '沈阳', '后卫', '冯萧霆', '训练', '冯萧霆', '长春', '患上', '感冒', '参加', '塞尔维亚', '热身赛', '队伍', '介绍', '冯萧霆', '发烧', '症状', '两天', '静养', '休息', '感冒', '恢复', '训练', '冯萧霆', '例子', '国奥队', '对雨中', '训练', '显得', '特别', '谨慎', '担心', '球员', '受凉', '引发', '感冒', '非战斗', '减员', '女足', '队员', '马晓旭', '热身赛', '受伤', '导致', '无缘', '奥运', '前科', '沈阳', '国奥队', '警惕', '训练', '嘱咐', '队员', '动作', '再出', '事情', '一位', '工作人员', '长春', '沈阳', '雨水', '一路', '伴随', '国奥队', '长春', '几次', '训练', '大雨', '搅和', '没想到', '沈阳', '碰到', '事情', '一位', '国奥', '球员', '雨水', '青睐', '不解']
词频统计是一种用于情报检索与文本挖掘的常用加权技术,用以评估一个词对于一个文件的重要程度。
字词的重要性随着它在文件中出现次数成正比增加。
collections 作为python的重点、高频模块,通过其中的 Counter类可快速实现字词列表的词频统计。
Counter作为字典dicit()的一个子类,将元素进行数量统计,计数后返回一个字典,键值为元素,值为元素个数。因此可参照字典进行基本操作。
from collections import Counter ## docResult 作为字词列表(见上节返回结果) Words = Counter(docResult) for k, v in Words.items(): print(k, v) # .items() 返回每个键值对组成的元组,按字典集合中,每一个元组的第二个元素排列。 WordsSorted=sorted(Words.items(),key=lambda x:x[1],reverse=False) print(WordsSorted)
马晓旭 2
意外 1
受伤 3
国奥 2
警惕 2
无奈 2
...
[('意外', 1), ('殷家', 1), ('记者', 1), ('傅亚雨', 1), ('报道', 1), ('来到', 1), ('依然', 1), ('摆脱', 1), ('困扰', 1), ('日常', 1), ('再度', 1), ('之下', 1), ('慢跑', 1), ('草草收场', 1), ('奥体中心', 1), ('外场', 1), ('阴沉沉', 1), ('气象预报', 1), ('显示', 1), ('幸好', 1), ('训练场', 1), ('几个', 1), ('小时', 1), ('丝毫', 1), ('停下来', 1), ('试一试', 1), ('态度', 1), ('例行', 1), ('天气', 1), ('转好', 1), ('迹象', 1), ('保护', 1), ('中止', 1), ('返回', 1), ('酒店', 1), ('足球队', 1), ('稀罕', 1), ('奥运会', 1), ('变得', 1), ('娇贵', 1), ('一周', 1), ('保证', 1), ('现有', 1), ('出现意外', 1), ('伤病', 1), ('情况', 1), ('影响', 1), ('正式', 1), ('比赛', 1), ('这一', 1), ('阶段', 1), ('疾病', 1), ('放在', 1), ('位置', 1), ('后卫', 1), ('患上', 1), ('参加', 1), ('塞尔维亚', 1), ('介绍', 1), ('发烧', 1), ('症状', 1), ('两天', 1), ('静养', 1), ('休息', 1), ('恢复', 1), ('例子', 1), ('对雨中', 1), ('显得', 1), ('特别', 1), ('谨慎', 1), ('担心', 1), ('受凉', 1), ('引发', 1), ('非战斗', 1), ('减员', 1), ('女足', 1), ('导致', 1), ('无缘', 1), ('奥运', 1), ('前科', 1), ('嘱咐', 1), ('动作', 1), ('再出', 1), ('工作人员', 1), ('一路', 1), ('伴随', 1), ('几次', 1), ('搅和', 1), ('没想到', 1), ('碰到', 1), ('不解', 1), ('马晓旭', 2), ('国奥', 2), ('警惕', 2), ('无奈', 2), ('青睐', 2), ('干扰', 2), ('分钟', 2), ('上午', 2), ('球队', 2), ('抵达', 2), ('全队', 2), ('控制', 2), ('热身赛', 2), ('事情', 2), ('一位', 2), ('受伤', 3), ('雨水', 3), ('队员', 3), ('当天', 3), ('队伍', 3), ('长春', 3), ('下午', 4), ('球员', 4), ('感冒', 4), ('冯萧霆', 4), ('大雨', 5), ('沈阳', 8), ('国奥队', 8), ('训练', 13)]
NLTK概述
NLTK(Natural Language Toolkit,自然语言工具包)是Python编程语言实现的自然语言处理工具,广泛应用于经验语言学、认知科学、人工智能、信息检索和机器学习领域。
nltk库安装
pip install nltk -i https://pypi.tuna.tsinghua.edu.cn/simple/
文本词频统计
使用NLTK的方法统计字词列表的词频信息:
from nltk import * ## docResult 作为字词列表(见上节返回结果) fdist = FreqDist(docResult) print(fdist) print(type(fdist)) words = fdist.keys() ## 字词列表 print(words) wordsFreq = fdist.values() ## 字词频数 print(wordsFreq)
dict_keys(['马晓旭', '意外', '受伤', '国奥', '警惕', '无奈', '大雨', '青睐', '殷家', '记者', '傅亚雨', '沈阳', '报道', '来到', '国奥队', '依然', '摆脱', '雨水', '困扰', '下午', '日常', '训练', '再度', '干扰', '之下', '队员', '慢跑', '分钟', '草草收场', '上午', '奥体中心', '外场', '阴沉沉', '气象预报', '显示', '当天', '幸好', '队伍', '球队', '抵达', '训练场', '几个', '小时', '丝毫', '停下来', '试一试', '态度', '例行', '天气', '转好', '迹象', '保护', '球员', '中止', '全队', '返回', '酒店', '足球队', '稀罕', '奥运会', '变得', '娇贵', '一周', '保证', '现有', '出现意外', '伤病', '情况', '影响', '正式', '比赛', '这一', '阶段', '控制', '感冒', '疾病', '放在', '位置', '后卫', '冯萧霆', '长春', '患上', '参加', '塞尔维亚', '热身赛', '介绍', '发烧', '症状', '两天', '静养', '休息', '恢复', '例子', '对雨中', '显得', '特别', '谨慎', '担心', '受凉', '引发', '非战斗', '减员', '女足', '导致', '无缘', '奥运', '前科', '嘱咐', '动作', '再出', '事情', '一位', '工作人员', '一路', '伴随', '几次', '搅和', '没想到', '碰到', '不解'])
dict_values([2, 1, 3, 2, 2, 2, 5, 2, 1, 1, 1, 8, 1, 1, 8, 1, 1, 3, 1, 4, 1, 13, 1, 2, 1, 3, 1, 2, 1, 2, 1, 1, 1, 1, 1, 3, 1, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, 1, 1, 4, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1])
特定字词词频统计
使用NLTK的方法统计特定字词的词频信息(频率和次数):
from nltk import * ## docResult 作为字词列表(见上节返回结果) fdist = FreqDist(docResult) w = '训练' print(fdist.freq(w)) ## 特定字词出现的频率 print(fdist[w]) ## 特定字词出现的次数
0.06878306878306878
13
字词词频分布表
由于散落的列表形式不容易观察词频分布情况,因此需要使用词频分布表来显示。
from nltk import * ## docResult 作为字词列表(见上节返回结果) fdist = FreqDist(docResult) fdist.tabulate(10) ## 字词频率分布表:字词及频数
训练 沈阳 国奥队 大雨 下午 球员 感冒 冯萧霆 受伤 雨水
13 8 8 5 4 4 4 4 3 3
在词频统计基础上,为了更加精准地分析特征词和模型结果,需要识别区分高频词和低频词。词频的选择主要考虑以下3个方面:
from collections import Counter ''' 剔除频数过高或过低的字词 wordList:字词列表 nmin:低频词的数量阈值 nmax:高频词的数量阈值 ''' def wordFreq(wordList, nmin, nmax): wordResult = [] wordDict = Counter(wordList) for key in wordDict.keys(): if wordDict.get(key) > nmin and wordDict.get(key) < nmax: wordResult.append((key, wordDict.get(key))) return wordResult ## docResult 作为字词列表(见上节返回结果) wordSelect = wordFreq(docResult, 2, 15) print(wordSelect)
[('受伤', 3), ('大雨', 5), ('沈阳', 8), ('国奥队', 8), ('雨水', 3), ('下午', 4), ('训练', 13), ('队员', 3), ('当天', 3), ('队伍', 3), ('球员', 4), ('感冒', 4), ('冯萧霆', 4), ('长春', 3)]
特征词中有一类词特别重要,这类词指的是实体,包括人名、地名、机构名、数字、日期等。
因此会出现一个专门的研究方向叫做命名实体识别,可以借助上文的词性对命名实体进行简单的选择,比如需要提取人名、地名、机构团体和其他专有名词,对应的只需要选择(‘nr’,‘ns’,‘nt’,‘nz’)即可。
import jieba.posseg as ps # 1.读取待分词文本信息 fNews = "./体育news.txt" with open(fNews,'r',encoding='utf-8') as f: docList = f.read().split('\n') # 2.读取停用词 fStopwords = "./NLPIR_stopwords.txt" with open(fStopwords,'r',encoding='utf-8') as f: stopwordList = f.read().split('\n') # 3.遍历待分词文本信息,按既定规则进行特征抽取 userPosList = ['nr','ns','nt','nz'] docResult = [] for docListi in docList: for word, pos in ps.cut(docListi): if word not in stopwordList and (word, pos) not in docResult and pos in userPosList: docResult.append((word, pos)) print(docResult)
[('马晓旭', 'nr'), ('国奥', 'nz'), ('傅亚雨', 'nr'), ('沈阳', 'ns'), ('国奥队', 'nt'), ('奥体中心', 'nt'), ('冯萧霆', 'nr'), ('长春', 'ns'), ('非战斗', 'nz')]
需求描述
结合前述的中文分词方法,实现目录下体育新闻文本的批量分词,并对字词列表进行消除停用词处理,以词云形式展示词频分布。
实现思路
实现思路:
基于《第七章 文本信息提取》获取文件列表方法,函数返回值关键字 return
改为 yield
,如此便成了生成器函数,可以大大提升代码执行效率。
import os ## 1. 遍历文件功能以类封装,遍历指定目录路径下文档,读取文档并返回文档内容 class loadFiles(): def __init__(self, par_path): self.par_path = par_path def __iter__(self): for file in os.listdir(self.par_path): # 遍历路径下所有文件 file_path = os.path.join(self.par_path, file) if os.path.isfile(file_path): # 判断是否为文件,以下仅针对文件进行操作 fin = open(file_path, 'rb') # rb读取方式更快 content = fin.read().decode('utf8') yield content fin.close() if __name__ == "__main__": path = "./sportnews/" files = loadFiles(path) for i, filei in enumerate(files): print("正在处理第{}篇文章……".format( i+1 )) # print(filei)
正在处理第1篇文章……
正在处理第2篇文章……
正在处理第3篇文章……
正在处理第4篇文章……
正在处理第5篇文章……
正在处理第6篇文章……
...
结合第 2 节介绍的中文分词方法和消除停用词方法,通过函数封装,实现针对文本分词及清洗功能。
import sys import re import jieba ## 2. 中文分词及清理以类封装,包括停用词文件路径初始化、加载停用词方法、中文文本分词及字词清洗方法 class StrCut(): # 停用词文件路径初始化 def __init__(self, stopwordPath=r""): self.stopwordPath = stopwordPath self.stopwordList = [] # 加载停用词方法 def LoadStopword(self): with open(self.stopwordPath, 'r', encoding='utf-8') as f: self.stopwordList = f.read().split('\n') # 中文文本分词及字词清洗方法:去除停用词、去除数字、去除单个字符、去除空字符 def ClearWord(self, wordStr): docList = wordStr.split('\n') docResult = [] for docListi in docList: # jieba.cut()返回可迭代的 generator,使用list() 转换为列表对象 docListiCut = list(jieba.cut(docListi, cut_all=False)) for i in range(len(docListiCut))[::-1]: if docListiCut[i] in self.stopwordList: # 去除停用词 docListiCut.pop(i) elif docListiCut[i].isdigit(): # 去除数字 docListiCut.pop(i) elif len(docListiCut[i]) == 1: # 去除单个字符 docListiCut.pop(i) elif docListiCut[i] == " ": # 去除空字符 docListiCut.pop(i) docResult.extend(docListiCut) return docResult if __name__ == "__main__": # 1.读取待分词文本信息 fNews = "./体育news.txt" with open(fNews,'r',encoding='utf-8') as f: docList = f.read() ## 中文分词及清理类实例化 stopwordPath = "./NLPIR_stopwords.txt" fileCut = StrCut(stopwordPath) fileCut.LoadStopword() ## 加载停用词 docResult = fileCut.ClearWord(docList) print(docResult)
['马晓旭', '意外', '受伤', '国奥', '警惕', '无奈', '大雨', '青睐', '殷家', '记者', '傅亚雨', '沈阳', '报道', '来到', '沈阳', '国奥队', '依然', '摆脱', '雨水', '困扰', '下午', '国奥队', '日常', '训练', '再度', '大雨', '干扰', '无奈', '之下', '队员', '慢跑', '分钟', '草草收场', '上午', '国奥队', '奥体中心', '外场', '训练', '阴沉沉', '气象预报', '显示', '当天', '下午', '沈阳', '大雨', '幸好', '队伍', '上午', '训练', '干扰', '下午', '球队', '抵达', '训练场', '大雨', '几个', '小时', '丝毫', '停下来', '试一试', '态度', '球队', '当天', '下午', '例行', '训练', '分钟', '天气', '转好', '迹象', '保护', '球员', '国奥队', '中止', '当天', '训练', '全队', '返回', '酒店', '训练', '足球队', '稀罕', '奥运会', '全队', '变得', '娇贵', '沈阳', '一周', '训练', '国奥队', '保证', '现有', '球员', '出现意外', '伤病', '情况', '影响', '正式', '比赛', '这一', '阶段', '控制', '训练', '受伤', '控制', '感冒', '疾病', '队伍', '放在', '位置', '抵达', '沈阳', '后卫', '冯萧霆', '训练', '冯萧霆', '长春', '患上', '感冒', '参加', '塞尔维亚', '热身赛', '队伍', '介绍', '冯萧霆', '发烧', '症状', '两天', '静养', '休息', '感冒', '恢复', '训练', '冯萧霆', '例子', '国奥队', '对雨中', '训练', '显得', '特别', '谨慎', '担心', '球员', '受凉', '引发', '感冒', '非战斗', '减员', '女足', '队员', '马晓旭', '热身赛', '受伤', '导致', '无缘', '奥运', '前科', '沈阳', '国奥队', '警惕', '训练', '嘱咐', '队员', '动作', '再出', '事情', '一位', '工作人员', '长春', '沈阳', '雨水', '一路', '伴随', '国奥队', '长春', '几次', '训练', '大雨', '搅和', '没想到', '沈阳', '碰到', '事情', '一位', '国奥', '球员', '雨水', '青睐', '不解']
词云可视化,需借助第三方库wordcloud 实现。词云可视化功能以函数封装,调用时只要函数名及传入字词列表参数即可。
词云库安装
pip install wordcloud -i https://pypi.tuna.tsinghua.edu.cn/simple/
import os import jieba from wordcloud import WordCloud import matplotlib.pyplot as plt from PIL import Image import numpy as np ## 3. 调用词云作图函数,对字词列表进行可视化 ## 3.1.矩形词云图 def drawPic(docList): # 引用系统中文字体,以防文字无法显示 font = r"C:/Windows/Fonts/微软雅黑/msyhl.ttc" docStr = " ".join(docList) s = WordCloud( font_path=font, background_color=None, width=1200, height=600 ).generate(docStr) s.to_file("cloud.png") # 保存图片 plt.imshow(s) plt.axis("off") plt.show() ## 3.2.指定背景词云图 def drawSportPic(docList): # 引用系统中文字体,以防文字无法显示 font = r"C:/Windows/Fonts/微软雅黑/msyhl.ttc" docStr = " ".join(docList) img = Image.open("logo.jpg") mask = np.array(img) img.close() s = WordCloud( mask = mask, font_path=font, background_color='white', width=720, height=650 ).generate(docStr) s.to_file("sportcloud.png") # 保存图片 plt.imshow(s) plt.axis("off") plt.show() if __name__ == "__main__": # 1.读取待分词文本信息 fNews = "./体育news.txt" with open(fNews,'r',encoding='utf-8') as f: docList = f.read() ## 中文分词及清理类实例化 stopwordPath = "./NLPIR_stopwords.txt" fileCut = StrCut(stopwordPath) fileCut.LoadStopword() ## 加载停用词 docResult = fileCut.ClearWord(docList) drawPic(docResult) ## 矩形词云图 drawSportPic(docResult) ## 以指定图片为背景做词云图
综合以上步骤,经过类和函数封装,用户通过对象实例化和函数调用,只要输入待分词文本路径、停用词文件路径,即可完成指定目录下文件文本分词、字词清理、云图可视化等功能。
- 定义类 loadFiles
- 定义__init__方法(实例属性)
文件目录路径
- 定义__iter__方法
说明实例对象为可迭代的对象,获取文件列表方法
- 定义类 StrCut
- 定义__init__方法(实例属性)
- 停用词文件路径
- 停用词列表
- 定义ClearWord方法
实现中文文本分词及字词清洗:去除停用词、去除数字、去除单个字符、去除空字符
- 3.1. 矩形词云图
- 3.2. 指定背景词云图
#!/usr/bin/python # -*- coding: utf-8 -*- # @Time : 2021年8月19日 # @Author : Alan # @Webchat : [email protected] # @FileName: ch08.py # @Software: Python 3.7 ''' 功能描述: 实现目录下体育新闻文本的批量分词,并对字词列表进行消除停用词处理,以词云形式展示词频分布。 实现思路: 1. 遍历文件功能以类封装,遍历指定目录路径下文档,读取文档并返回文档内容 2. 中文分词及清理以类封装,包括停用词文件路径初始化、加载停用词方法、中文文本分词及字词清洗方法 3. 调用词云作图函数,对字词列表进行可视化 ''' import os import jieba from wordcloud import WordCloud import matplotlib.pyplot as plt from PIL import Image import numpy as np ## 1. 遍历文件功能以类封装,遍历指定目录路径下文档,读取文档并返回文档内容 class loadFiles(): ''' 输入: 1. par_path 指定待遍历文件的目录路径 输出: 1. content 文档内容 ''' def __init__(self, par_path): self.par_path = par_path def __iter__(self): for file in os.listdir(self.par_path): # 遍历路径下所有文件 file_path = os.path.join(self.par_path, file) if os.path.isfile(file_path): # 判断是否为文件,以下仅针对文件进行操作 fin = open(file_path, 'rb') # rb读取方式更快 content = fin.read().decode('utf8') yield content fin.close() ## 2. 中文分词及清理以类封装,包括停用词文件路径初始化、加载停用词方法、中文文本分词及字词清洗方法 class StrCut(): ''' 输入: 1. stopwordPath 指定停用词文件路径 输出: 1. docResult 文档字词经分词及清理后的列表 ''' # 停用词文件路径初始化 def __init__(self, stopwordPath=r""): self.stopwordPath = stopwordPath self.stopwordList = [] # 加载停用词方法 def LoadStopword(self): with open(self.stopwordPath, 'r', encoding='utf-8') as f: self.stopwordList = f.read().split('\n') # 中文文本分词及字词清洗方法:去除停用词、去除数字、去除单个字符、去除空字符 def ClearWord(self, wordStr): docList = wordStr.split('\n') docResult = [] for docListi in docList: # jieba.cut()返回可迭代的 generator,使用list() 转换为列表对象 docListiCut = list(jieba.cut(docListi, cut_all=False)) for i in range(len(docListiCut))[::-1]: if docListiCut[i] in self.stopwordList: # 去除停用词 docListiCut.pop(i) elif docListiCut[i].isdigit(): # 去除数字 docListiCut.pop(i) elif len(docListiCut[i]) == 1: # 去除单个字符 docListiCut.pop(i) elif docListiCut[i] == " ": # 去除空字符 docListiCut.pop(i) docResult.extend(docListiCut) return docResult ## 3. 调用词云作图函数,对字词列表进行可视化 ## 3.1.矩形词云图 def drawPic(docList): # 引用系统中文字体,以防文字无法显示 font = r"C:/Windows/Fonts/微软雅黑/msyhl.ttc" docStr = " ".join(docList) s = WordCloud( font_path=font, background_color=None, width=1200, height=600 ).generate(docStr) s.to_file("cloud.png") # 保存图片 plt.imshow(s) plt.axis("off") plt.show() ## 3.2.指定背景词云图 def drawSportPic(docList): # 引用系统中文字体,以防文字无法显示 font = r"C:/Windows/Fonts/微软雅黑/msyhl.ttc" docStr = " ".join(docList) img = Image.open("logo.jpg") mask = np.array(img) img.close() s = WordCloud( mask = mask, font_path=font, background_color='white', width=720, height=650 ).generate(docStr) s.to_file("sportcloud.png") # 保存图片 plt.imshow(s) plt.axis("off") plt.show() if __name__ == "__main__": ## 遍历文件功能类实例化 path = "./sportnews/" fileStrs = loadFiles(path) ## 中文分词及清理类实例化 stopwordPath = "./NLPIR_stopwords.txt" fileCut = StrCut(stopwordPath) fileCut.LoadStopword() ## 加载停用词 ## 遍历文件,将所有字词合并到一个列表 docList = [] for i, fileStrsi in enumerate(fileStrs): print("正在处理第{}篇文章……".format(i)) docListi = fileCut.ClearWord(fileStrsi) docList.extend(docListi) #drawPic(docList) ## 矩形词云图 drawSportPic(docList) ## 以指定图片为背景做词云图
开始实验