-
Notifications
You must be signed in to change notification settings - Fork 0
Sogou Dictionary Analysis
先放点图压压惊 :)
.scel
为搜狗词库后缀名,.qcel
为QQ拼音词库后缀名,两者的数据均由十六进制编码,且文件内数据的结构相同。本文以搜狗拼音词库举例。
在 Vim 或 Vi 的命令状态下
将当前文件以每组一个字节按大写字母十六进制输出:
:%!xxd -g 1 -u
其中%
表示整个文件,!
表示执行外部命令,-g 1
表示每组一个字节,-u
表示使用大写字母。
将当前文件转为原格式查看:
:%!xxd -r
左边的8位数为范围,中间的16列为文件数据,右边为乱码。不必在意右边的乱码,这并不影响我们解析词库。
当然,使用其他方法也能实现同样的效果,比如使用Notepad++软件,IDEA插件BinED
搜狗词库由以下四部分组成:
- 基本信息
- 拼音表
- 词库
- 词库黑名单
其中第四部分词库黑名单仅在一些较新的词库中才拥有。
组成部分 | 数据范围 | 偏移量 |
---|---|---|
基本信息 | 0x0000 - 0x1540 | 0x0000 |
拼音表 | 0x1540 - 0x2627 | 0x1540 |
词库 | 0x2628 开始 | 0x2628 |
每2字节(2列)表示1个数据。数据为数字或文字,其中文字又包括字母和汉字。如图为0x0120
至0x013F
的数据:
由于文字使用的是UTF-16LE编码,因此数据需要从右往左读,例如0x0120
和0x0121
表示十六进制0xBEE0
,即十进制48864。
基本信息的数据范围:0x0000
至0x1540
。主要的内容如下表:
数据范围 | 对应信息 | 数据类型 |
---|---|---|
0x0120 - 0x0123 | 不同音词条数 | 数字 |
0x0124 - 0x0127 | 总词条数 | 数字 |
0x0130 - 0x0337 | 词库名 | 文字 |
0x0338 - 0x053F | 地点 | 文字 |
0x0540 - 0x0D3F | 备注 | 文字 |
0x0D40 - 0x153F | 示例词条 | 文字 |
-
绿色框的数据表示数字48864+0=48864,即不同音的词条数有48864个;
-
蓝色框的数据表示数字49662+0=49662,即总词条数有49662个;
-
红色框的数据表示文字
%u7F51
和%u7EDC
,即词库名中的“网络“二字。
拼音表的数据范围:0x1540
至0x2627
。数据的组成顺序如下:
[拼音表的拼音数] [拼音的索引] [拼音的长度] [拼音] [拼音的索引] [拼音的长度] [拼音] ……
主要的内容如下表:
数据范围 | 对应信息 | 占用字节数 | 赋值 |
---|---|---|---|
0x1540 - 0x1543 | 拼音表的拼音数 | 2 | |
0x1544 - 0x1545 | 拼音的索引 | 2 | |
0x1546 - 0x1547 | 拼音的长度 | 2 | py_length |
0x1548 - 0x1548 + py_length | 拼音 | py_length | |
... | ... | ... |
-
前两个绿色框的数据表示数字413+0=413,即拼音表的拼音数为413个;
-
第一个蓝色框的数据表示数字0,即拼音的索引为0;
-
第一个红色框的数据表示数字2,即拼音的长度为2字节,也就是一个字母;
-
第一个黄色框的数据表示文字
%u0061
,即拼音为”a“。
用自然语言解释:“拼音表,此表共有413个拼音。第一个拼音有1个字母,拼音为'a',其索引为0;第二个拼音有2个字母,拼音为‘ai',其索引为1……”
后面的同色色框对应的信息同上。
通常情况,拼音表的拼音数也就是汉语拼音音节索引为413个,从0开始到412结束。音节索引用于下面的词库进行查找操作。
词库的数据范围:0x2628
开始。数据的组成顺序如下:
[拼音所表示的词条数] [拼音索引的长度] [拼音的索引] [词的长度] [词] [权重序号的长度] [权重序号] [拼音所表示的词条数] [拼音] [拼音索引的长度] [拼音的索引] [词的长度] [词] [权重序号的长度] [权重序号] ……
主要内容如下表:
数据范围 | 对应信息 | 占用的字节数 | 赋值 |
---|---|---|---|
0x2628 - 0x2629 | 拼音所表示的词条数 | 2 | |
0x262A - 0x262B | 拼音索引的长度 | 2 | py_index_len |
0x262C - 0x262C + py_index_len | 拼音的索引 | py_index_len | |
~ - ~ + 4( ~ 表示0x262C + py_index_len + 1 ) | 词的长度 | 2 | word_len |
~ - ~ + word_len( ~ 表示上一列的 ~ + 4+ 1 ) | 词 | word_len*2 | |
~ - ~ + 2 | 权重序号的长度 | 2 | weight_len |
~ - ~ + weight_len | 权重序号 | weight_len | |
... | ... | ... |
-
第一个绿色框的数据表示数字1,即拼音所表示的词条数为1条,也就是没有同音词;
-
第一个蓝色框的数据表示数字4,即拼音索引的长度为4字节,也就是两个拼音;
-
前两个红色框的数据分别表示数字0和4,即拼音的索引为0和4,0和4分别对应拼音表的‘a’和‘ao’;
-
第一个黄色框的数据表示数字4,即词的长度为4字节,也就是两个字;
-
前两个橙色框的数据表示文字
%u963F
和%u6556
,即词为”阿敖“; -
第一个黑色框的数据表示数字10,即词的权重序号的长度为10字节;
-
前五个紫色框的数据表示数字22799,即词的权重序号为27799。
用自然语言解释:“词库,第一个词的拼音共表示1个词,拼音的索引有2个,分别为0和4,词有2个字,词为’阿敖‘,词的权重排第27799位……”
后面的同色色框对应的信息同上。
解释一下一些数据的作用,词的拼音的索引用于在拼音表中查找对应的拼音,拼音一般不止一个,所以索引也同样不止一个;关于词的权重,词的权重即为词的使用频率,权重序号即为使用频率的降序排序序号,因此,词的权重序号越小,词的使用频率越高。关于同音词,当拼音所表示的词条数大于1,即存在同音词时,数据的组成顺序有所不同,一组拼音索引对应多个词。例如当拼音所表示的词条数为2时,数据的组成顺序具体如下:
[拼音所表示的词条数] [拼音索引的长度] [拼音的索引] [词的长度] [词] [词的权重的长度] [词的权重] [词的长度] [词] [词的权重序号的长度] [词的权重序号]
词库黑名单数据无固定范围,也无固定起始位置,它紧接在词库后面,且仅在一些较新的词库中出现。
因为黑名单中的词条只有词,没有对应拼音索引,因此其组成顺序较为简单,具体如下:
[黑名单标识] [黑名单词条数] [词的字数] [词] [词的字数] [词]
假设黑名单数据从0x9200
开始,主要内容如下表:
数据范围 | 对应信息 | 占用的字节数 | 赋值 |
---|---|---|---|
0x9200 - 0x920C | 黑名单标识 | 12 | |
0x920D - 0x920E | 拼音表长度 | 2 | |
0x920F - 0x9210 | 词的字数 | 2 | word_count |
0x9211 - 0x9211 + word_count * 2 | 词 | word_count * 2 | |
... | ... | ... |
注意,黑名单中的词的字数与词库中词的长度不同,因为一个字占两个字节,所以词的长度等于两倍的词的个数。
由于黑名单中的词一般为政治敏感词,所以就不再深入解析了。
搜狗输入法词库转Rime词库: 源码地址