【问题标题】:Handling Encoding Errors in a UTF-8 File with Python3使用 Python3 处理 UTF-8 文件中的编码错误
【发布时间】:2020-08-24 19:22:53
【问题描述】:

我正在尝试使用语料库来训练 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?

应该是撇号, 应该是 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”。

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

【问题讨论】:

  • 那个 lib 似乎不起作用,unidecode 也不起作用,尽管 unidecode 至少删除了有问题的字符。
  • cp1252 中只有 some 行吗?整个文件是cp1252吗?
  • 我有点不清楚发生了什么。以 CP1252 读取文件(或仅上面的示例行)无法正常工作,所以我猜该文件是用 UTF-8 编码的,但其中包含 vim 能够检测到但 python 忽略的无效字符?
  • 也许您可以将原始文件放在 Google Drive(或类似门户)上,以便我们下载原始文件并进行测试。

标签: python python-3.x unicode


【解决方案1】:

使用您的答案中的原始数据,您已经从双重编码中获得了 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。

【讨论】:

    【解决方案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 的类似问题中找到了可能的替换代码表。

    【讨论】:

      猜你喜欢
      • 2010-09-21
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      • 2014-12-25
      • 2019-08-16
      • 1970-01-01
      • 2016-08-31
      相关资源
      最近更新 更多