经过长时间的调查研究,初步确定部分文本在进行 GBK–>UTF-8编码转换时会遇到个别字节缺失导致的转码出错中断或转码结果乱码的情况。
以 20230101/aliyun.20230101.8.武侠小说/1184.txt 第563行为例:
如果我们用Python对它进行正常的编码转换通常都会遇到如下错误: UnicodeDecodeError: 'gbk' codec can't decode byte 0xac in position 46: illegal multibyte sequence, 这正是由于文本中单个字节丢失导致的。
转换出错原因(GBK编码的文本中丢失单个字节导致):
在GBK编码的定义中,00-7F是单字节,和ASCII保持一致,此范围内有96个文字和32个控制符号。从81-FE都是双字节编码,换句话说,所有的中文汉字在GBK编码中都以双字节形式呈现。
例如汉字 `中国人` 的GBK字节编码为 \xd6\xd0\xb9\xfa\xc8\xcb
, 其中 \xd6\xd0 是 “中”, \xb9\xfa 是 “国”, xc8\xcb 是 “人”,我们可以用Python对 \xd6\xd0\xb9\xfa\xc8\xcb
进行decode得到正确的汉字。
b'\xd6\xd0\xb9\xfa\xc8\xcb'.decode("gbk") >> 中国人
假如我们把删掉 \xd6\xd0\xb9\xfa\xc8\xcb
的第2个字节 xd0,让它变成 \xd6\xb9\xfa\xc8\xcb
,再对它进行decode,程序就会报错了: UnicodeDecodeError: 'gbk' codec can't decode byte 0xfa in position 2: illegal multibyte sequence,程序在进行中文编码转换时按两个字节一组进行decode,但它无法正确的识别并转换 \xd6\xb9
, 所以就报错了。
举例说明:
我们把 \xd6\xd0\xb9\xfa\xc8\xcb
的1个字节和第3个字节删除掉,组成一个新的字节序列: \xd0\xfa\xc8\xcb
,再对其进行GBK识别,原本的 中国人 被错误的识别成了 喧人,文本原意已经被混淆。
如果我们对1184.txt 这个文本的 563行内容进行忽略错误的编码转换会得到以下结果:
我们可以很清楚的看到这段文本因为 errors=“ignore”
的作用,会跳过识别错误的单字节,把后续的字节尽量按GBK编码的方式识别,但是早已经丢失了原意,这也是因为该段落文本中出现单个字节丢失的原因导致的。
为什么很多GBK文本出现一次或者多次单个字节丢失的情况我们还不得而知,不过基于以上的研究,我们可以设计一个新的编码识别转换的方法,就是想办法正确的标记单个字节丢失的真正位置,再交由人工进行识别处理,并借助其他自动化或者AI工具 ,补全这些字符。