python 实现中文分词统计

pySVNA 2019-06-25

总是看到别人用Python搞各种统计,前端菜鸟的我也来尝试了一把。有各种语义分析库在,一切好像并不是很复杂。不过Python刚开始看,估计代码有点丑。

一、两种中文分词开发包

thulac (http://thulac.thunlp.org/)

THULAC(THU Lexical Analyzer for Chinese)由清华大学自然语言处理与社会人文计算实验室研制推出的一套中文词法分析工具包,具有中文分词和词性标注功能。THULAC具有如下几个特点:

  • 能力强。利用我们集成的目前世界上规模最大的人工分词和词性标注中文语料库(约含5800万字)训练而成,模型标注能力强大。
  • 准确率高。该工具包在标准数据集Chinese Treebank(CTB5)上分词的F1值可达97.3%,词性标注的F1值可达到92.9%,与该数据集上最好方法效果相当。
  • 速度较快。同时进行分词和词性标注速度为300KB/s,每秒可处理约15万字。只进行分词速度可达到1.3MB/s。

jieba (https://github.com/fxsjy/jieba

据说是最好的中文分词组件,支持Python、C++、Java、node.js、PHP等多种语言。

  • 支持三种分词模式()

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

二、语义分词

2.1 简单文本分词

两种分词组件的使用都比较简单,以 jieba 为例:

# -*- coding: utf-8 -*-
import jieba
# 精确模式
seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print "Default Mode: " + "/ ".join(seg_list)
#输出结果:
#Default Mode: 我/ 来到/ 北京/ 清华大学

2.2 对文件内容进行分词

对文件内容进行分词其实本质上和对字符串的分词一样,只不过多了个文件读写的过程。
这里写了两个读写文件的函数,之所以使用codecs来读取,主要是为了解决Python2.7 文件读写过程中Unicode编码问题

# -*- coding: utf-8 -*-
import codecs
# @see 读取文件内容
def readFile(filename):
  content = ""
  try:
    fo = codecs.open(filename,'r', "utf-8")
    print "读取文件名:", filename
    for line in fo.readlines():
      content += line.strip()
    print "字数:", len(content)
  except IOError as e:
    print "文件不存在或者文件读取失败"
    return ""
  else:
    fo.close()
    return content
    
# @see 写入文件内容(数组会使用writelines进行写入)codec.open实现
# @param toFile 文件名
#        content 内容
def writeFile(toFile, content):
  try:
    fo = codecs.open(toFile, 'wb', "utf-8")
    print "文件名:", toFile
    if type(content) == type([]):
      fo.writelines(content)
    else:
      fo.write(content)
  except IOError:
    print "没有找到文件或文件读取失败"
  else:
    print "文件写入成功"
    fo.close()

将文件读写和分词结合起来

# 读取源文件(sourceFile)内容
rawContent = readFile(sourceFile)
# 结巴分词
seg_list = jieba.cut(rawContent, cut_all=False)
# 把分词结果写到目标文件(targetFile)中,这里是用空格分割,也可以改成其他符号
writeFile(targetFile, " ".join(seg_list))

三、对分词结果进行统计和排序

简单说一下思路,读取分词结果的txt文件,然后用空格分割成词语数组,遍历数组,分别统计词语的出现次数。最后对所有的单词根据频次进行排序。

3.1 统计分词

# 词语数组
wordList= []
# 用于统计词频
wordCount= {}

# 从分词后的源文件中读取数据
sourceData = readFile(sourceFile)
# 利用空格分割成数组
wordList = sourceData.split(' ')
# 遍历数组进行词频统计,这里使用wordCount 对象,出发点是对象下标方便查询
for item in wordList:
  if item not in wordCount:
    wordCount[item] = 1
  else:
    wordCount[item] += 1
# 循环结束,wordCount 对象将保存所有的词语和词频

3.2 根据词频排序

Python 数组中自带sort() 函数,为了方便比较,我们定义了一个对象,并标明了比较方法

# 定义wordItem 类
class wordItem:
  label = ''
  times = 0
  # 构造函数
  def __init__(self, l, t):
    self.label = l
    self.times = t
  # 用于比较
  def __lt__(self, other):
    return self.times < other.times

# 定义wordItem 数组用于排序
wordItemArray= []
# 构造对象数组
for key in wordCount:
  wordItemArray.append(wordItem(key, wordCount[key]))
# 按词频由高到低倒序排列
wordItemArray.sort(reverse = True)

# 写入目标文件 target
wf = codecs.open(targetFile,'w', "utf-8")
for item in wordItemArray:
  wf.write(item.label+' '+str(item.times) + '\n')

四、使用命令行

使用命令行需要引入import sys,通过sys.argv[n]可以获得输入的命令行参数,注意第一个是脚本名。

import sys
# 我们调用时会 python index.py 'source.txt' 'target.txt'
# 注意这里argv 是脚本名
# print "name: ", sys.argv[0] # 脚本名 如:index.py
sourceFile = sys.argv[1]
targetFile = sys.argv[2]

五、完整代码

参见 github node-popcorn,项目中加入了一些puppeteer无头浏览器爬虫抓取网页内容的代码。

相关推荐