Skip to content

Sogou Dictionary Analysis

He Zhizhou edited this page Dec 18, 2022 · 12 revisions

搜狗拼音词库文件解析

先放点图压压惊 :) EnglishPicture transparentPicture BinED

下载词库:搜狗输入法词库QQ输入法词库

词库格式

拼音词库格式

.scel为搜狗词库后缀名,.qcel为QQ拼音词库后缀名,两者的数据均由十六进制编码,且文件内数据的结构相同。本文以搜狗拼音词库举例。

以十六进制查看文件

在 Vim 或 Vi 的命令状态

将当前文件以每组一个字节按大写字母十六进制输出:

:%!xxd -g 1 -u

其中%表示整个文件,!表示执行外部命令,-g 1表示每组一个字节,-u表示使用大写字母。

将当前文件转为原格式查看:

:%!xxd -r

Vim xxd

左边的8位数为范围,中间的16列为文件数据,右边为乱码。不必在意右边的乱码,这并不影响我们解析词库。

当然,使用其他方法也能实现同样的效果,比如使用Notepad++软件,IDEA插件BinED

文件解析

搜狗词库由以下四部分组成:

  1. 基本信息
  2. 拼音表
  3. 词库
  4. 词库黑名单

其中第四部分词库黑名单仅在一些较新的词库中才拥有。

组成部分 数据范围 偏移量
基本信息 0x0000 - 0x1540 0x0000
拼音表 0x1540 - 0x2627 0x1540
词库 0x2628 开始 0x2628

每2字节(2列)表示1个数据。数据为数字或文字,其中文字又包括字母和汉字。如图为0x01200x013F的数据:

0120-0123Example

由于文字使用的是UTF-16LE编码,因此数据需要从右往左读,例如0x01200x0121表示十六进制0xBEE0,即十进制48864


基本信息

基本信息的数据范围:0x00000x1540。主要的内容如下表:

数据范围 对应信息 数据类型
0x0120 - 0x0123 不同音词条数 数字
0x0124 - 0x0127 总词条数 数字
0x0130 - 0x0337 词库名 文字
0x0338 - 0x053F 地点 文字
0x0540 - 0x0D3F 备注 文字
0x0D40 - 0x153F 示例词条 文字

0120-0130

  • 绿色框的数据表示数字48864+0=48864,即不同音的词条数有48864个;

  • 蓝色框的数据表示数字49662+0=49662,即总词条数有49662个;

  • 红色框的数据表示文字%u7F51%u7EDC,即词库名中的“网络“二字。


拼音表

拼音表的数据范围:0x15400x2627。数据的组成顺序如下:

[拼音表的拼音数] [拼音的索引] [拼音的长度] [拼音] [拼音的索引] [拼音的长度] [拼音] ……

主要的内容如下表:

数据范围 对应信息 占用字节数 赋值
0x1540 - 0x1543 拼音表的拼音数 2
0x1544 - 0x1545 拼音的索引 2
0x1546 - 0x1547 拼音的长度 2 py_length
0x1548 - 0x1548 + py_length 拼音 py_length
... ... ...

1540-1550

  • 前两个绿色框的数据表示数字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
... ... ...

2620-2650

  • 第一个绿色框的数据表示数字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时,数据的组成顺序具体如下:

[拼音所表示的词条数] [拼音索引的长度] [拼音的索引] [词的长度] [词] [词的权重的长度] [词的权重] [词的长度] [词] [词的权重序号的长度] [词的权重序号]

2ED0-2FF00


词库黑名单

词库黑名单数据无固定范围,也无固定起始位置,它紧接在词库后面,且仅在一些较新的词库中出现。

因为黑名单中的词条只有词,没有对应拼音索引,因此其组成顺序较为简单,具体如下:

[黑名单标识] [黑名单词条数] [词的字数] [词] [词的字数] [词]

假设黑名单数据从0x9200开始,主要内容如下表:

数据范围 对应信息 占用的字节数 赋值
0x9200 - 0x920C 黑名单标识 12
0x920D - 0x920E 拼音表长度 2
0x920F - 0x9210 词的字数 2 word_count
0x9211 - 0x9211 + word_count * 2 word_count * 2
... ... ...

注意,黑名单中的词的字数与词库中词的长度不同,因为一个字占两个字节,所以词的长度等于两倍的词的个数

由于黑名单中的词一般为政治敏感词,所以就不再深入解析了。

代码实现

搜狗输入法词库转Rime词库: 源码地址