栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

基于结巴分词做的全文分词统计词频小脚本

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于结巴分词做的全文分词统计词频小脚本

受朋友之托,写一个小脚本,断断续续做了两天,写一下两天的收获。

起因

有个朋友说专业文档很枯燥难懂,需要一个能把全文的关键词找出来并排序的东西,找不到现成的,问我能不能做一个。我前些天也听车神说有关分词的东西,用这个机会认识一下中文分词也不错。本来还想弄下 PDF 2 TXT的,不过没找到合适的工具,先弄这个吧。

要实现把全文的关键词找出来并排序,就需要识别文中的词而不是字,有了词才能进行排序。中文和其他语言不同,没有明确的词分界,不像英语有空格作为词边界。分词算法什么的我实在弄不出来了,所以用别人的吧。上百度和Github找工具,最后确定用结巴分词,因为结巴分词有Javascript版,分词还是很OK的。

开干

分词统计并排序

之前是用Javascript版的结巴分词写的,不过在分词统计的时候没想起来Javascript有什么能排序的模块,就换Python版的结巴分词写了。

因为那个朋友的资料是繁体的,为了兼容繁体,我引入了繁体字典,不过加载好像有问题,我直接把繁体字典当用户字典加载了。

说这么多干嘛,上源码。

# index.py
#encoding=utf-8
'''

'''
import jieba
import jieba.posseg as pseg
from collections import Counter
# 用户字典 可自行添加专业名词 防止被jieba分错了
jieba.load_userdict('dict/user.dict')
# jieba.load_userdict('dict/dict.txt.big')
# 简体&繁体字典 这个不用修改,所以我让他当用户字典加载了
#jieba.set_dictionary('dict/dict.txt.big')
# './源文件.txt'为想打开的文件
file_object = open('./源文件.txt','r')
## 定义一个 list
L =list()
## 获取带词性的词对象(没学过py不知道得到的是什么)
words = pseg.cut(file_object.read())
i=0
## 遍历这个词对象
for word, flag in words:
    ## 如果词性(flag)或者词(word)属于这个范围就直接跳过 自己填写
    if flag=="x" or flag=="p"  or flag=="uj" or word=="年"or word=="月"or word=="日" :
 continue
    ## 打印计数 为了区分程序是不是挂了
    i=i+1
    print(i)
    ##把词追加到list中
    L.append(word)
## 计算出现次数
getObj = Counter(L)
## 写到./getObj.json文件里
f = open('./getObj.json', 'w')
f.write(str(getObj).replace("Counter(","").replace(")","").replace("'",'"'))
f.close()
file_object.close()
## end

查询关键词频

弄完分词,朋友又说能不能加一个关键词查找,可以到想要的词出现的频率。我毕竟Python是边学边写的,还是用node写这个功能把。



var fs = require('fs');

var keyWord = [
    "本行",
    "人民币",
];

var json = JSON.parse(fs.readFileSync('./getObj.json'));
var Arr = []
for (var i = 0; i < keyWord.length; i++) {
    let get = keyWord[i] + ':' + json[keyWord[i]]
    console.log(get)
    Arr.push(get)
}
//你要的关键词在这里
fs.writeFileSync('keyWord.txt', Arr.join('n'), 'utf8')

自动化脚本

因为用了两种语言,运行要分段,我这么懒的人,这么会等第一段运行完再运行第二段呢,一言不合写sh。

# main.sh
#
python index.py 
echo "----------------关键词-------------------"
node Search.js
echo "----------------------------------------
排序在getObj.json文件
关键词搜索在keyWord.txt文件"
怎么用
  1. 把要转换的文件放在在当前文件夹,并改名为源文件.txt,运行sudo easy_install jieba
  2. 终端下运行 python index.py,等待完成,等待完成期间可以在Search.js文件里把想要搜索的关键字填在数组里,保存好。
  3. 完成第二步,接着执行node Search.js,等待完成。
  4. 关键字搜索结果在keyWord.txt文件里
  5. 或者写个脚本自动化,sh main.sh
额外收获

毕竟是自己摸索写的东西,收获还是不错的。为了以后想用的时候能找得到,便也记录下来。

分词工具

jieba:这个工具挺好用的,这个是python版的,还有很多种版本

codecs:一个python库,用来转码的

Counter:一个python库工具,用来做统计的

一些杂脚本

gbk2utf8

网上下载些文本文件,很多都是在win上写的,win上一般默认保存为gbk。这样在Linux上打开都是乱码,所以上网找了段代码自己改。

#encoding=utf-8
'''

'''
import codecs
# gbk转utf8脚本
def ReadFile(filePath,encoding="gb18030"):
    with codecs.open(filePath,"r",encoding) as f:
 return f.read()
def WriteFile(filePath,u,encoding="utf-8"):
    with codecs.open(filePath,"w",encoding) as f:
 f.write(u)
def UTF8_2_GBK(src,dst):
    content = ReadFile(src,encoding="gb18030")
    WriteFile(dst,content,encoding="utf-8")

UTF8_2_GBK("./in.txt","./out.txt")

nodejiba

之前是用node版的结巴写的分词,后来因为py比较容易写统计,就换py写分词了。留下这段代码以后需要再看看咯


var nodejieba = require("nodejieba")
var fs = require("fs")
var data = fs.readFileSync("./4.txt", "utf-8")
nodejieba.load({
    userDict: './dict.utf8',
})
var result = nodejieba.extract(data, 100);
var a = {
    "fen": []
}
let j = 0
for (let i = 0; i < result.length; i++) {
    if (result[i].tag !== "uj" && result[i].tag !== "zg" && result[i].tag !== "x") {
 a.fen[j] = {
     "word": "1",
     "tag": "2"
 };
 a.fen[j].word = result[i].word;
 a.fen[j].tag = result[i].tag;
 fs.writeFileSync("./5.txt", JSON.stringify(a), 'utf8')
 j++
    }
}
console.log(a);

scel2txt

因为弄分词的原因,想找一下专业名词,就跑到搜狗输入法的词库下载词包,发现这个格式我解码不了,上github找了别人的脚本(其实我并不知道这段代码是谁写的)。

#!/usr/bin/python  
# -*- coding: utf-8 -*-  

import struct  
import sys  
import binascii   
import pdb  
#搜狗的scel词库就是保存的文本的unicode编码,每两个字节一个字符(中文汉字或者英文字母)  
#找出其每部分的偏移位置即可  
#主要两部分  
#1.全局拼音表,貌似是所有的拼音组合,字典序  
#格式为(index,len,pinyin)的列表  
#index: 两个字节的整数 代表这个拼音的索引  
#len: 两个字节的整数 拼音的字节长度  
#pinyin: 当前的拼音,每个字符两个字节,总长len  
#  
#2.汉语词组表  
#格式为(same,py_table_len,py_table,{word_len,word,ext_len,ext})的一个列表  
#same: 两个字节 整数 同音词数量  
#py_table_len:  两个字节 整数  
#py_table: 整数列表,每个整数两个字节,每个整数代表一个拼音的索引  
#  
#word_len:两个字节 整数 代表中文词组字节数长度  
#word: 中文词组,每个中文汉字两个字节,总长度word_len  
#ext_len: 两个字节 整数 代表扩展信息的长度,好像都是10  
#ext: 扩展信息 前两个字节是一个整数(不知道是不是词频) 后八个字节全是0  
#  
#      {word_len,word,ext_len,ext} 一共重复same次 同音词 相同拼音表  

#拼音表偏移,  
startPy = 0x1540;  

#汉语词组表偏移  
startChinese = 0x2628;  

#全局拼音表  

GPy_Table ={}  

#解析结果  
#元组(词频,拼音,中文词组)的列表  
GTable = []  

def byte2str(data):  
    '''''将原始字节码转为字符串'''  
    i = 0;  
    length = len(data)  
    ret = u''  
    while i < length:  
 x = data[i] + data[i+1]  
 t = unichr(struct.unpack('H',x)[0])  
 if t == u'r':  
     ret += u'n'  
 elif t != u' ':  
     ret += t  
 i += 2  
    return ret  
#获取拼音表  
def getPyTable(data):  

    if data[0:4] != "x9Dx01x00x00":  
 return None  
    data = data[4:]  
    pos = 0  
    length = len(data)  
    while pos < length:  
 index = struct.unpack('H',data[pos]+data[pos+1])[0]  
 #print index,  
 pos += 2  
 l = struct.unpack('H',data[pos]+data[pos+1])[0]  
 #print l,  
 pos += 2  
 py = byte2str(data[pos:pos+l])  
 #print py  
 GPy_Table[index]=py  
 pos += l  

#获取一个词组的拼音  
def getWordPy(data):  
    pos = 0  
    length = len(data)  
    ret = u''  
    while pos < length:  

 index = struct.unpack('H',data[pos]+data[pos+1])[0]  
 ret += GPy_Table[index]  
 pos += 2      
    return ret  

#获取一个词组  
def getWord(data):  
    pos = 0  
    length = len(data)  
    ret = u''  
    while pos < length:  

 index = struct.unpack('H',data[pos]+data[pos+1])[0]  
 ret += GPy_Table[index]  
 pos += 2      
    return ret  

#读取中文表      
def getChinese(data):  
    #import pdb  
    #pdb.set_trace()  

    pos = 0  
    length = len(data)  
    while pos < length:  
 #同音词数量  
 same = struct.unpack('H',data[pos]+data[pos+1])[0]  
 #print '[same]:',same,  

 #拼音索引表长度  
 pos += 2  
 py_table_len = struct.unpack('H',data[pos]+data[pos+1])[0]  
 #拼音索引表  
 pos += 2  
 py = getWordPy(data[pos: pos+py_table_len])  

 #中文词组  
 pos += py_table_len  
 for i in xrange(same):  
     #中文词组长度  
     c_len = struct.unpack('H',data[pos]+data[pos+1])[0]  
     #中文词组  
     pos += 2    
     word = byte2str(data[pos: pos + c_len])  
     #扩展数据长度  
     pos += c_len   
     ext_len = struct.unpack('H',data[pos]+data[pos+1])[0]  
     #词频  
     pos += 2  
     count  = struct.unpack('H',data[pos]+data[pos+1])[0]  

     #保存  
     GTable.append((count,py,word))  

     #到下个词的偏移位置  
     pos +=  ext_len  

def deal(file_name):  
    print '-'*60  
    f = open(file_name,'rb')  
    data = f.read()  
    f.close()  

    if data[0:12] !="x40x15x00x00x44x43x53x01x01x00x00x00":  
 print "确认你选择的是搜狗(.scel)词库?"  
 sys.exit(0)  
    #pdb.set_trace()  

    print "词库名:" ,byte2str(data[0x130:0x338])#.encode('GB18030')  
    print "词库类型:" ,byte2str(data[0x338:0x540])#.encode('GB18030')  
    print "描述信息:" ,byte2str(data[0x540:0xd40])#.encode('GB18030')  
    print "词库示例:",byte2str(data[0xd40:startPy])#.encode('GB18030')  

    getPyTable(data[startPy:startChinese])  
    getChinese(data[startChinese:])  

if __name__ == '__main__':  

    #将要转换的词库添加在这里就可以了  
    o = ['1.scel',  
    ]  

    for f in o:  
 deal(f)  

    #保存结果    
    f = open('sougou.txt','w')  
    for count,py,word in GTable:  
 #GTable保存着结果,是一个列表,每个元素是一个元组(词频,拼音,中文词组),有需要的话可以保存成自己需要个格式  
 #我没排序,所以结果是按照上面输入文件的顺序  
 f.write( unicode('{%(count)s}' %{'count':count}+py+' '+ word).encode('utf8') )#最终保存文件的编码GB18030,可以自给改  
 f.write('n')  
    f.close()      

emoji-scel2txt

这是Ruby写的,颜文字导出

scel2mmseg

这是python写的,到处成mmseg格式,据说这个可以用来做中文分词,以后再看看吧。

scel2pyim
一个将搜狗输入法scel细胞词库转换为emacs chinese-pyim文本词库的小工具。因为我最近在学emacs,就收藏了。

scel2txt

还是个scel2txt小工具。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号