分词:将一个句子分成以词为单位的组成(中文都是以词组句子)
分词方法:动态规划方法,维特比算法(HMM)
分词工具:jieba、snowNLP、THULAC
1. jieba
pip install jieba
算法
- 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)
- 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
- 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法
jieba.cut(data),返回generator, 需list(jieba.cut(data))
jieba.cut(data, cut_all=False) #默认精确模式cut_all=False; 若cut_all=True为全模式
github上jieba介绍:
https://github.com/fxsjy/jieba
import jieba
import re
# 载入数据(txt文本,encoding="utf-8")
data = open("test.txt", encoder="utf-8",errors="ignore").readlines()
# 观察数据
data[:5]
[out]:
['\ufeff\n',
'\u3000第一回\u3000风雪惊变\n',
'\n',
'\u3000\u3000钱塘江浩浩江水,日日夜夜无穷无尽的从临安牛家村边绕过,东流入海。江畔一排数十株乌柏树,叶子似火烧般红,正是八月天时。村前村后的野草刚起始变黄,一抹斜阳映照之下,更增了几分萧索。两株大松树下围着一堆村民,男男女女和十几个小孩,正自聚精会神的听着一个瘦削的老者说话。\n',
'\n']
# 定义分词函数,首先预处理数据成可以用于分词的数据,再使用jieba.cut分词
def process(data, lenNum):
# 过滤长度小于lenNum的行
filterdata = filter(lambda s: len(s)>=lenNum, data)
# 去掉字符串收尾缩进"\u3000"和换行符"\n",注意filter,map返回的是生成器,不能直接读取,要使用list()
m1 = map(lambda s: s.strip("\u3000|\n"), filterdata)
# 去掉字符串中间的缩进,用replace("\u3000","")
m2 = map(lambda s: s.replace("\u3000",""),m1)
# 去掉中文标点符号,正则表达式re.sub("a","b",c)将c中的a换成b
m3 = map(lambda s: re.sub("[!?。※ □"#$%&'()《》*+,-/:;<=>@[\]^_`{|}~⦅⦆「」、、〃》「」『』【】〔〕〖〗〘〙〚〛〜〝〞〟〰〾〿–—‘’‛“”„‟…‧﹏.]+","",s),m2)
# 中文分词, jieba.cut()返回generator,list(jieba.cut())将结果显示出来
cut_words = map(lambda s: list(jieba.cut(s)),m3)
return list(cut_words)
# 将制定文本分词
cut_words = process(data, 5)
cut_words[:2]
[out:]
[['第一回', '风雪', '惊变'],
['钱塘江',
'浩浩',
'江水',
'日日夜夜',
'无穷无尽',
'的',
'从',
'临安',
'牛家村',
'边',
'绕过',
'东',
'流入',
'海',
'江畔',
'一排',
'数十株',
'乌',
'柏树',
'叶子',
'似',
'火烧',
'般红',
'正是',
'八月',
'天时',
'村前村后',
'的',
'野草',
'刚',
'起始',
'变黄',
'一抹',
'斜阳',
'映照',
'之下',
'更增',
'了',
'几分',
'萧索',
'两株',
'大',
'松树',
'下',
'围着',
'一堆',
'村民',
'男男女女',
'和',
'十几个',
'小孩',
'正自',
'聚精会神',
'的',
'听',
'着',
'一个',
'瘦削',
'的',
'老者',
'说话']]
# cut_words返回的list为分行分词后的结果,要统计所有字符的频率
total_words = []
for each in cut_words:
# 用extend是将each列表中的元素4添加到原列表[1,2,3]中,组成一个新的列表[1,2,3,4]。而append是将each列表[4]为一个整体添加到原列表中[1,2,3,[4]]
total_words.extend(each)
len(total_words)
[out]:458018
len(cut_words)
[out]:2690