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 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
| #!/usr/bin/python # -*- coding: utf-8 -*-
import struct import sys import binascii import pdb import os #搜狗的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] != "\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] #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] !="\x40\x15\x00\x00\x44\x43\x53\x01\x01\x00\x00\x00": 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', '2.scel' ] o=os.listdir('D:\work\pythonwork') #scel文件夹目录
for f in o: name, ext = os.path.splitext(f) if ext=='.scel': deal(f)
# 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('utf-8') )#最终保存文件的编码,可以自给改 f.write( unicode(word).encode('utf-8') )#最终保存文件的编码,可以自给改
f.write('\n') f.close()
|