Python读取scel文件

这篇博客介绍了如何使用Python将搜狗词库的.scel文件转换为.txt文件,详细解析了.scel文件的结构,并提供了转换过程中的关键代码和参考资料。
部署运行你感兴趣的模型镜像

背景介绍:将搜狗词库中 .scel 文件转化为 .txt 文件

  1. 搜狗词库链接:https://pinyin.sogou.com/dict/
  2. 搜狗的scel词库就是保存的文本的unicode编码,每两个字节一个字符(中文汉字或者英文字母)找出其每部分的偏移位置即可,主要两部分:

    2.1 全局拼音表,貌似是所有的拼音组合,字典序 格式为(index,len,pinyin)的列表 index: 两个字节的整数 代表这个拼音的索引 len: 两个字节的整数 拼音的字节长度 pinyin: 当前的拼音,每个字符两个字节,总长len

    2.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次 同音词 相同拼音表
  3. struct函数 -- struct.pack()和struct.unpack()

    在转化过程中,主要用到了一个格式化字符串(format strings),用来规定转化的方法和格式。

    3.1 struct.pack(fmt,v1,v2,.....)

      将v1,v2等参数的值进行一层包装,包装的方法由fmt指定。被包装的参数必须严格符合fmt。最后返回一个包装后的字符串。

    3.2 struct.unpack(fmt,string)

      顾名思义,解包。比如pack打包,然后就可以用unpack解包了。返回一个由解包数据(string)得到的一个元组(tuple), 即使仅有一个数据也会被解包成元组。其中len(string) 必须等于 calcsize(fmt),这里面涉及到了一个calcsize函数。struct.calcsize(fmt):这个就是用来计算fmt格式所描述的结构的大小。 格式字符串(format string)由一个或多个格式字符(format characters)组成,对于这些格式字符的描述参照Python manual如下:

FormatC TypePython
xpad byteno value
ccharstring of length
bsigned charinteger
Bunsigned charinteger
hshortinteger
Hunsigned shortinteger
iintinteger
Iunsigned intlong
llonginteger
Lunsigned longlong
qlong longlong
Qunsigned long longlong
ffloatfloat
ddoublefloat
schar[]string
pchar[]string
Pvoid *integer

下面给出 Python 代码:


import struct
import os

# 拼音表偏移,
startPy = 0x1540;

# 汉语词组表偏移
startChinese = 0x2628;

# 全局拼音表
GPy_Table = {}

# 解析结果
# 元组(词频,拼音,中文词组)的列表
GTable = []

# 原始字节码转为字符串
def byte2str(data):
    pos = 0
    str = ''
    while pos < len(data):
        c = chr(struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0])
        if c != chr(0):
            str += c
        pos += 2
    return str

# 获取拼音表
def getPyTable(data):
    data = data[4:]
    pos = 0
    while pos < len(data):
        index = struct.unpack('H', bytes([data[pos],data[pos + 1]]))[0]
        pos += 2
        lenPy = struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0]
        pos += 2
        py = byte2str(data[pos:pos + lenPy])
        GPy_Table[index] = py
        pos += lenPy

# 获取一个词组的拼音
def getWordPy(data):
    pos = 0
    ret = ''
    while pos < len(data):
        index = struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0]
        ret += GPy_Table[index]
        pos += 2
    return ret

# 读取中文表
def getChinese(data):
    pos = 0
    while pos < len(data):
        # 同音词数量
        same = struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0]

        # 拼音索引表长度
        pos += 2
        py_table_len = struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0]

        # 拼音索引表
        pos += 2
        py = getWordPy(data[pos: pos + py_table_len])

        # 中文词组
        pos += py_table_len
        for i in range(same):
            # 中文词组长度
            c_len = struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0]
            # 中文词组
            pos += 2
            word = byte2str(data[pos: pos + c_len])
            # 扩展数据长度
            pos += c_len
            ext_len = struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0]
            # 词频
            pos += 2
            count = struct.unpack('H', bytes([data[pos], data[pos + 1]]))[0]

            # 保存
            GTable.append((count, py, word))

            # 到下个词的偏移位置
            pos += ext_len


def scel2txt(file_name):
    # 分隔符
    print('-' * 60)
    # 读取文件
    with open(file_name, 'rb') as f:
        data = f.read()

    print("词库名:", byte2str(data[0x130:0x338])) # .encode('GB18030')
    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__':

    # scel所在文件夹路径
    in_path = "Scel"

    fin = [fname for fname in os.listdir(in_path) if fname[-5:] == ".scel"]
    for f in fin:
        f = os.path.join(in_path, f)
        scel2txt(f)
        
    f = open('./Scel/coal_dict.txt', 'w')
    for count, py, word in GTable:
        f.write(str(count)+ '\t\t\t' + py + '\t\t\t' + word + '\n')
    f.close()

得到结果如下:

 

------------------------------------------------------------
词库名: 东北话大全【官方推荐】
词库类型: 方言
描述信息: 贼拉逗的东北话你一定听过,说起来实在霸气!词库终于出来了,再也不愁打不出来你想说的话,专门为你私人订制哦,还不快去下载!!!
词库示例: 不想嘎哈 老嘎瘩 嗯呐 瞅你咋的 咋地  
------------------------------------------------------------
词库名: 史记【官方推荐】
词库类型: 文学
描述信息: 作者司马迁以其“究天人之际,通古今之变,成一家之言”的史识,使《史记》成为中国第一部,也是最出名的纪传体通史。小编整理了书中经典故事、名句、人物等,让你更快打出相关词汇,我在这等你哦~
词库示例: 十表 姬昌 项羽本纪 武王伐纣 虚怀若谷 商鞅变法 
------------------------------------------------------------
词库名: 开发大神专用词库【官方推荐】
词库类型: 互联网
描述信息: 程序猿们是不是遨游在代码的海洋里无法自拔?小编知道你们整日找BUG辛苦了,为辅助你们的工作特意奉上专属词库,提高工作效率,畅快打字。欢迎你们前来补充词条哦 !
词库示例: 资源保留 代码 优先级 启动事件 排期 公开测试 
------------------------------------------------------------
词库名: 柳宗元诗词【官方推荐】
词库类型: 诗词歌赋
描述信息: 柳宗元,唐朝文学家、散文家和思想家。倡导唐代古文运动。散文论说性强,笔锋犀利,讽刺辛辣。游记写景状物,多所寄托。诗多抒写抑郁悲愤、思乡怀友之情,自成一路。
词库示例: 柳河东 永州八记 捕蛇者说 柳河东集 江雪 小石潭记 
------------------------------------------------------------
词库名: 诗经【官方推荐】
词库类型: 诗词歌赋
描述信息: 《诗经》是中国古代诗歌开端,最早的一部诗歌总集,现存305篇(此外有目无诗的6篇,共311篇),分《风》、《雅》、《颂》三部分。《颂》有40篇,《雅》有105篇(《小雅》中有6篇有目无诗,不计算在内),《风》的数量最多,共160篇,合起来是305篇。古人取其整数,常说“诗三百”。
词库示例: 君子好逑 悠哉悠哉 左右采之 琴瑟友之 施于中谷 黄鸟于飞 

GitHub项目链接:

scel文件:https://github.com/CQiang27/Spark_Python/tree/master/Scel

Python源码:https://github.com/CQiang27/Spark_Python/blob/master/scel_TR_txt.ipynb

 

参考文献:

[1] 多个.scel合并为同一dict,并去重,https://blog.csdn.net/leitouguan8655/article/details/82834517

[2] scel2txt 搜狗scel格式转txt python3,https://blog.csdn.net/cFarmerReally/article/details/78149648

[3] Python中struct.pack()和struct.unpack()用法详细说明,http://www.php.cn/python-tutorials-356984.html

 

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值