受朋友之托,写一个小脚本,断断续续做了两天,写一下两天的收获。
起因 有个朋友说专业文档很枯燥难懂,需要一个能把全文的关键词找出来并排序的东西,找不到现成的,问我能不能做一个。我前些天也听车神说有关分词的东西,用这个机会认识一下中文分词也不错。本来还想弄下 PDF 2 TXT
的,不过没找到合适的工具,先弄这个吧。
要实现把全文的关键词找出来并排序,就需要识别文中的词而不是字,有了词才能进行排序。中文和其他语言不同,没有明确的词分界,不像英语有空格作为词边界。分词算法什么的我实在弄不出来了,所以用别人的吧。上百度和 Github 找工具,最后确定用结巴分词,因为结巴分词有 JavaScript 版,分词还是很 OK 的。
开干 分词统计并排序 :
之前是用 JavaScript 版的结巴分词写的,不过在分词统计的时候没想起来 JavaScript 有什么能排序的模块,就换 Python 版的结巴分词写了。
因为那个朋友的资料是繁体的,为了兼容繁体,我引入了繁体字典,不过加载好像有问题,我直接把繁体字典当用户字典加载了。
说这么多干嘛,上源码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 ''' /*@version: 0.1 * @author: Bubao * @contact: asd565586630@gmail.com * @time: 2017-07-13 00:22:00 */ ''' import jiebaimport jieba.posseg as psegfrom collections import Counter jieba.load_userdict('dict/user.dict' ) file_object = open ('./源文件。txt' ,'r' ) L =list () words = pseg.cut(file_object.read()) i=0 for word, flag in words: if flag=="x" or flag=="p" or flag=="uj" or word=="年" or word=="月" or word=="日" : continue i=i+1 print (i) L.append(word) getObj = Counter(L) f = open ('./getObj.json' , 'w' ) f.write(str (getObj).replace("Counter(" ,"" ).replace(")" ,"" ).replace("'" ,'"' )) f.close() file_object.close()
查询关键词频 :
弄完分词,朋友又说能不能加一个关键词查找,可以到想要的词出现的频率。我毕竟 Python 是边学边写的,还是用 node 写这个功能把。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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
。
1 2 3 4 5 6 7 8 9 10 11 12 python index.pyecho "----------------关键词-------------------" node Search.jsecho "---------------------------------------- 排序在 getObj.json 文件 关键词搜索在 keyWord.txt 文件"
怎么用
把要转换的文件放在在当前文件夹,并改名为源文件。txt
,运行sudo easy_install jieba
终端下运行 python index.py
,等待完成,等待完成期间可以在Search.js
文件里把想要搜索的关键字填在数组里,保存好。
完成第二步,接着执行node Search.js
,等待完成。
关键字搜索结果在keyWord.txt
文件里
或者写个脚本自动化,sh main.sh
额外收获 毕竟是自己摸索写的东西,收获还是不错的。为了以后想用的时候能找得到,便也记录下来。
分词工具 jieba :这个工具挺好用的,这个是 python 版的,还有很多种版本
codecs :一个 python 库,用来转码的
Counter :一个 python 库工具,用来做统计的
一些杂脚本 gbk2utf8 :
网上下载些文本文件,很多都是在 win 上写的,win 上一般默认保存为gbk
。这样在 Linux 上打开都是乱码,所以上网找了段代码自己改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ''' /*@version: 0.1 * @author: Bubao * @contact: asd565586630@gmail.com * @time: 2017-07-13 00:22:00 */ ''' import codecsdef 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 写分词了。留下这段代码以后需要再看看咯
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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 找了别人的脚本(其实我并不知道这段代码是谁写的)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 import struct import sys import binasciiimport pdb 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 ] != "\x9D\x01\x00\x00" : return None data = data[4 :] pos = 0 length = len (data) while pos < length: index = struct.unpack('H' ,data[pos]+data[pos+1 ])[0 ] pos += 2 l = struct.unpack('H' ,data[pos]+data[pos+1 ])[0 ] pos += 2 py = byte2str(data[pos:pos+l]) 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 ): pos = 0 length = len (data) while pos < length: same = struct.unpack('H' ,data[pos]+data[pos+1 ])[0 ] 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 ] !="\x40\x15\x00\x00\x44\x43\x53\x01\x01\x00\x00\x00" : print "确认你选择的是搜狗 (.scel) 词库?" sys.exit(0 ) print "词库名:" ,byte2str(data[0x130 :0x338 ]) print "词库类型:" ,byte2str(data[0x338 :0x540 ]) print "描述信息:" ,byte2str(data[0x540 :0xd40 ]) print "词库示例:" ,byte2str(data[0xd40 :startPy]) 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: f.write( unicode('{%(count)s}' %{'count' :count}+py+' ' + word).encode('utf8' ) ) f.write('\n' ) f.close()
emoji-scel2txt
这是 Ruby 写的,颜文字导出
scel2mmseg
这是 python 写的,到处成 mmseg 格式,据说这个可以用来做中文分词,以后再看看吧。
scel2pyim 一个将搜狗输入法 scel 细胞词库转换为 emacs chinese-pyim 文本词库的小工具。因为我最近在学 emacs,就收藏了。
scel2txt
还是个 scel2txt 小工具。