用于utf-8文件的Python 3.5 UnicodeDecodeError(语言为'ang',古英语)

gat*_*ost 8 python utf-8 nltk python-3.x

这是我第一次使用StackOverflow提出一个问题,但是我已经集体保存了这么多年来我在家里感受到的许多项目.

我正在使用Python3.5和nltk来解析旧英语的完整语料库,它作为77个文本文件和XML文档发布给我,它将文件序列指定为TEI格式语料库的连续段.以下是XML文档标题的相关部分,显示我们实际上正在使用TEI:

<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
  <teiHeader type="ISBD-ER">
    <fileDesc>
Run Code Online (Sandbox Code Playgroud)

是的,所以作为测试,我只是试图使用NLTK的MTECorpusReader打开语料库并使用words()方法来证明我能够打开它.我正在通过交互式Python shell完成所有这些工作,只是为了便于测试.这就是我所做的一切:

# import the reader method    
import nltk.corpus.reader as reader

# open the sequence of files and the XML doc with the MTECorpusReader    
oecorpus = reader.mte.MTECorpusReader('/Users/me/Documents/0163','.*')

# print the first few words in the corpus to the interactive shell
oecorpus.words()
Run Code Online (Sandbox Code Playgroud)

当我尝试这个时,我得到以下回溯:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/util.py", line 765, in __repr__
    for elt in self:
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/corpus/reader/util.py", line 397, in iterate_from
    for tok in piece.iterate_from(max(0, start_tok-offset)):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/corpus/reader/util.py", line 291, in iterate_from
    tokens = self.read_block(self._stream)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/corpus/reader/mte.py", line 25, in read_block
    return list(filter(lambda x: x is not None, XMLCorpusView.read_block(self, stream, tagspec, elt_handler)))
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/corpus/reader/xmldocs.py", line 307, in read_block
    xml_fragment = self._read_xml_fragment(stream)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/corpus/reader/xmldocs.py", line 252, in _read_xml_fragment
    xml_block = stream.read(self._BLOCK_SIZE)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/data.py", line 1097, in read
    chars = self._read(size)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/data.py", line 1367, in _read
    chars, bytes_decoded = self._incr_decode(bytes)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/nltk/data.py", line 1398, in _incr_decode
    return self.decode(bytes, 'strict')
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 59: invalid start byte
Run Code Online (Sandbox Code Playgroud)

所以,因为我是一个英勇的StackOverflowsketeer,我已经确定一个或多个文件已损坏,或者文件中有一些字符包含Python的utf-8解码器不知道如何处理的字符.我可以相当肯定这个文件的完整性(请相信我的话),所以我正在追求

我尝试了以下重新格式化77文本文件,没有明显的效果:

for file in loglist:
    bufferfile = open(file, encoding='utf-8', errors='replace')
    bufferfile.close()
loglist = [name for name in os.listdir('.') if os.path.isfile(name)]
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

1)到目前为止,我的方法是否有意义,或者我在故障排除中搞砸了什么?

2)根据UTF-8错误很早出现(在十六进制位置59)以及我的utf-8错误替换这一事实,此问题必须与XML文档一致,这是否公平?脚本对问题没什么影响?如果我认为这是错误的,那我怎样才能更好地隔离这个问题呢?

3)如果我们可以得出结论问题与XML文档有关,那么清除它的最佳方法是什么?我是否可以尝试找到十六进制字节和它对应的ASCII并更改字符?

预先感谢您的帮助!

Ala*_*ack 5

您的转换技术不起作用,因为您再也没有读取和写回该文件。

\n\n

0x80不是 UTF-8 或任何 iso-8859-* 字符集中的有效字节。它在 Windows 代码页中有效,但只有 Unicode 可以支持古英语字符,因此您有一些非常损坏的数据。

\n\n

要转换带有坏字节的 UTF-8,请执行以下操作:

\n\n
with open('input.txt', 'r', encoding='utf-8', errors='ignore') as input,\n        open('output.txt', 'w', encoding='utf-8') as output:\n\n     output.write(input.read())\n
Run Code Online (Sandbox Code Playgroud)\n\n

encoding如果您不关心丢失数据,则可以使用MTECorpusReader 上的参数来逃脱:

\n\n
oecorpus = reader.mte.MTECorpusReader('/Users/me/Documents/0163','.*', encoding='cp1252')\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将生成0x80一个欧元 (\xe2\x82\xac) 符号。

\n