因爲項目中要用到詞庫,而下載的搜狗詞庫是.scel格式,因此就用python腳本將搜狗詞庫.scel格式文件轉化爲.txt格式文件。python
1 #!/bin/python 2 # -*- coding: utf-8 -*- 3 4 5 import struct 6 import sys 7 import binascii 8 import pdb 9 10 try: 11 reload(sys) 12 sys.setdefaultencoding('utf-8') 13 except: 14 pass 15 16 # 搜狗的scel詞庫就是保存的文本的unicode編碼,每兩個字節一個字符(中文漢字或者英文字母) 17 # 找出其每部分的偏移位置便可 18 # 主要兩部分 19 # 1.全局拼音表,貌似是全部的拼音組合,字典序 20 # 格式爲(index,len,pinyin)的列表 21 # index: 兩個字節的整數 表明這個拼音的索引 22 # len: 兩個字節的整數 拼音的字節長度 23 # pinyin: 當前的拼音,每一個字符兩個字節,總長len 24 # 25 # 2.漢語詞組表 26 # 格式爲(same,py_table_len,py_table,{word_len,word,ext_len,ext})的一個列表 27 # same: 兩個字節 整數 同音詞數量 28 # py_table_len: 兩個字節 整數 29 # py_table: 整數列表,每一個整數兩個字節,每一個整數表明一個拼音的索引 30 # 31 # word_len:兩個字節 整數 表明中文詞組字節數長度 32 # word: 中文詞組,每一箇中文漢字兩個字節,總長度word_len 33 # ext_len: 兩個字節 整數 表明擴展信息的長度,好像都是10 34 # ext: 擴展信息 前兩個字節是一個整數(不知道是否是詞頻) 後八個字節全是0 35 # 36 # {word_len,word,ext_len,ext} 一共重複same次 同音詞 相同拼音表 37 38 # 拼音表偏移, 39 startPy = 0x1540; 40 41 # 漢語詞組表偏移 42 startChinese = 0x2628; 43 44 # 全局拼音表 45 46 GPy_Table = {} 47 48 # 解析結果 49 # 元組(詞頻,拼音,中文詞組)的列表 50 GTable = [] 51 52 53 def byte2str(data): 54 '''''將原始字節碼轉爲字符串''' 55 i = 0; 56 length = len(data) 57 ret = u'' 58 while i < length: 59 x = data[i] + data[i + 1] 60 t = unichr(struct.unpack('H', x)[0]) 61 if t == u'\r': 62 ret += u'\n' 63 elif t != u' ': 64 ret += t 65 i += 2 66 return ret 67 68 69 # 獲取拼音表 70 def getPyTable(data): 71 if data[0:4] != "\x9D\x01\x00\x00": 72 return None 73 data = data[4:] 74 pos = 0 75 length = len(data) 76 while pos < length: 77 index = struct.unpack('H', data[pos] + data[pos + 1])[0] 78 # print index, 79 pos += 2 80 l = struct.unpack('H', data[pos] + data[pos + 1])[0] 81 # print l, 82 pos += 2 83 py = byte2str(data[pos:pos + l]) 84 # print py 85 GPy_Table[index] = py 86 pos += l 87 88 # 獲取一個詞組的拼音 89 90 91 def getWordPy(data): 92 pos = 0 93 length = len(data) 94 ret = u'' 95 while pos < length: 96 index = struct.unpack('H', data[pos] + data[pos + 1])[0] 97 ret += GPy_Table[index] 98 pos += 2 99 return ret 100 101 102 # 獲取一個詞組 103 def getWord(data): 104 pos = 0 105 length = len(data) 106 ret = u'' 107 while pos < length: 108 index = struct.unpack('H', data[pos] + data[pos + 1])[0] 109 ret += GPy_Table[index] 110 pos += 2 111 return ret 112 113 114 # 讀取中文表 115 def getChinese(data): 116 # import pdb 117 # pdb.set_trace() 118 119 pos = 0 120 length = len(data) 121 while pos < length: 122 # 同音詞數量 123 same = struct.unpack('H', data[pos] + data[pos + 1])[0] 124 # print '[same]:',same, 125 126 # 拼音索引表長度 127 pos += 2 128 py_table_len = struct.unpack('H', data[pos] + data[pos + 1])[0] 129 # 拼音索引表 130 pos += 2 131 py = getWordPy(data[pos: pos + py_table_len]) 132 133 # 中文詞組 134 pos += py_table_len 135 for i in xrange(same): 136 # 中文詞組長度 137 c_len = struct.unpack('H', data[pos] + data[pos + 1])[0] 138 # 中文詞組 139 pos += 2 140 word = byte2str(data[pos: pos + c_len]) 141 # 擴展數據長度 142 pos += c_len 143 ext_len = struct.unpack('H', data[pos] + data[pos + 1])[0] 144 # 詞頻 145 pos += 2 146 count = struct.unpack('H', data[pos] + data[pos + 1])[0] 147 148 # 保存 149 GTable.append((count, py, word)) 150 151 # 到下個詞的偏移位置 152 pos += ext_len 153 154 155 def deal(file_name): 156 print '-' * 60 157 f = open(file_name, 'rb') 158 data = f.read() 159 f.close() 160 161 if data[0:12] != "\x40\x15\x00\x00\x44\x43\x53\x01\x01\x00\x00\x00": 162 print "確認你選擇的是搜狗(.scel)詞庫?" 163 sys.exit(0) 164 # pdb.set_trace() 165 166 print "詞庫名:", byte2str(data[0x130:0x338]) # .encode('GB18030') 167 print "詞庫類型:", byte2str(data[0x338:0x540]) # .encode('GB18030') 168 print "描述信息:", byte2str(data[0x540:0xd40]) # .encode('GB18030') 169 print "詞庫示例:", byte2str(data[0xd40:startPy]) # .encode('GB18030') 170 171 getPyTable(data[startPy:startChinese]) 172 getChinese(data[startChinese:]) 173 174 175 if __name__ == '__main__': 176 177 # 將要轉換的詞庫添加在這裏就能夠了 178 o = [u'明星【官方推薦】.scel',] 179 180 181 for f in o: 182 deal(f) 183 184 # 保存結果 185 f = open('amuse.txt', 'w') 186 for word in GTable: 187 # GTable保存着結果,是一個列表,每一個元素是一個元組(詞頻,拼音,中文詞組),有須要的話能夠保存成本身須要個格式 188 # 我沒排序,因此結果是按照上面輸入文件的順序 189 #f.write(unicode(word).encode('GB18030')) # 最終保存文件的編碼,能夠自給改 190 f.write(word[2]) 191 f.write('\n') 192 f.close()