使用Python3处理UTF8文件中的编码错误

2024-09-25 00:22:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用语料库来训练ML模型,但我遇到了一些编码错误,这些错误可能是由其他人对文件的转换/注释引起的。在vim中打开文件时,我可以直观地看到错误,但python在读取时似乎没有注意到这些错误。语料库相当大,所以我需要找到一种方法让python检测它们,并希望找到一种方法来纠正它们

这是一个在vim中查看的示例行

# ::snt That<92>s what we<92>re with<85>You<92>re not sittin<92> there in a back alley and sayin<92> hey what do you say, five bucks?

这个<;92>;应该是撇号和<;85>;应该是3点。其他行上还显示了许多其他值。通过谷歌搜索,我认为原始编码可能是CP1252,但目前Linux下的file命令将该文件列为UTF-8。我试过几种方法打开这个,但没有运气

with open(fn) as f:返回

# ::snt Thats what were withYoure not sittin there in a back alley and sayin hey what do you say, five bucks?

这就是跳过那些标记并连接单词,这是一个问题

with open(fn, encoding='CP1252') as f:返回

# ::snt ThatA's what weA're withA...YouA're not sittinA' there in a back alley and sayinA' hey what do you say, five bucks?

在视觉上为那些奇怪的字符插入“A”

with io.open(fn, errors='strict')不会产生任何错误,读取字节流和解码也不会产生任何错误,因此不幸的是,在这一点上,我甚至无法检测到错误,更不用说对它们的正确性了

有没有办法读入这个大文件并检测其中的编码错误。更好的是,有没有办法纠正它们


Tags: and文件方法inre编码错误with
2条回答

这里有一个可行但不是很优雅的解决方案

# Read in file as a raw byte-string
fn  = 'bad_chars.txt'
with open(fn, 'rb') as f:
    text = f.read()
print(text)

# Detect out of range 
has_bad = False
for c in text:
    if c >= 128:
        has_bad = True
print('Had bad:', has_bad)

# Fix offending characters
text = text.replace(b'\xc2\x92', b"\x27")
text = text.replace(b'\xc2\x85', b"...")
text = text.decode('utf-8')
print(text)

这将产生以下输出

b'# ::snt That\xc2\x92s what we\xc2\x92re with\xc2\x85You\xc2\x92re not sittin\xc2\x92 there in a back alley and sayin\xc2\x92 hey what do you say, five bucks?\n'

Had bad: True

# ::snt That's what we're with...You're not sittin' there in a back alley and sayin' hey what do you say, five bucks?

缺点是我需要找到有问题的字符,并编写一个replace命令使其工作。类似问题中的可能替换代码表位于efficiently replace bad characters

使用您答案中的原始数据,您已经从双重编码中获得了mojibake。你需要双重解码才能正确翻译

>>> s = b'# ::snt That\xc2\x92s what we\xc2\x92re with\xc2\x85You\xc2\x92re not sittin\xc2\x92 there in a back alley and sayin\xc2\x92 hey what do you say, five bucks?\n'
>>> s.decode('utf8').encode('latin1').decode('cp1252')
'# ::snt That’s what we’re with…You’re not sittin’ there in a back alley and sayin’ hey what do you say, five bucks?\n'

数据实际上是UTF-8格式,但在解码为Unicode时,错误的代码点是Windows-1252代码页的字节。.encode('latin1')将Unicode代码点1:1转换回字节,因为latin1编码是Unicode的前256个代码点,所以它可以作为Windows-1252正确解码

相关问题 更多 >