保存utf8文件时忽略UnicodeEncodeError

时间:2017-04-08 10:27:15

标签: python python-3.x python-requests nltk

我从Project Gutenberg下载了一大串小说。我正在尝试将其保存到我的计算机上,但我收到了UnicodeEncodeError,而且我不知道如何修复或忽略它。

from urllib import request

# Get the text
response = request.urlopen('http://www.gutenberg.org/files/2701/2701-0.txt')
# Decode it using utf8
raw = response.read().decode('utf8')
# Save the file
file = open('corpora/canon_texts/' + 'test', 'w')
file.write(raw)
file.close()

这给了我以下错误:

UnicodeEncodeError: 'charmap' codec can't encode character '\ufeff' in position 0: character maps to <undefined>

首先,我尝试删除文件开头的BOM:

# We have to get rid of the pesky Byte Order Mark before we save it
raw = raw.replace(u'\ufeff', '')

但是我得到了同样的错误,只是使用了不同的位置编号:

UnicodeEncodeError: 'charmap' codec can't encode characters in position 7863-7864: character maps to <undefined>

如果我查看该区域,我找不到令人不快的角色,所以我不知道要删除的内容:

raw[7850:7900]

打印出来:

'   BALLENA,             Spanish.\r\n     PEKEE-NUEE-'

这看起来不像是一个问题。

然后我尝试用try语句跳过坏行:

file = open('corpora/canon_texts/' + 'test', 'w')
try:
    file.write(raw)
except UnicodeEncodeError:
    pass
file.close()

但这会跳过整个文本,给我一个0大小的文件。

我该如何解决这个问题?

编辑:

有几个人注意到&#39; \ ufeff&#39;是utf16。我尝试切换到utf16:

# Get the text
response = request.urlopen('http://www.gutenberg.org/files/2701/2701-0.txt')
# Decode it using utf16
raw = response.read().decode('utf-16')

但是在我收到此错误之前,我甚至无法下载数据:

UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0x0a in position 1276798: truncated data

第二次编辑:

我也尝试按照u'\ufeff' in Python string中的建议使用utf-8-sig进行解码,因为这包括BOM,但是当我尝试保存它时我又回到了这个错误:

UnicodeEncodeError: 'charmap' codec can't encode characters in position 7863-7864: character maps to <undefined>

3 个答案:

答案 0 :(得分:1)

解码和重新编码文件只是为了将其保存到磁盘是没有意义的。只需写出你下载的字节,就可以将文件放在磁盘上了:

raw = response.read()
with open('corpora/canon_texts/' + 'test', 'wb') as outfile:
    outfile.write(raw)

这是写入完全您下载内容的唯一可靠方式。

迟早你会想要阅读文件并使用它,所以让我们考虑你的错误。您没有提供完整的堆栈跟踪(总是一个坏主意),但您的错误是在编码期间,而不是解码。解码步骤成功。错误必须出现在行file.write(raw)上,这是文本被编码以便保存的地方。但它转换成什么编码?没人知道,因为你没有指定编码就打开了file!您获得的编码取决于您的位置,操作系统,以及可能的潮汐和天气预报。简而言之:指定编码。

text = response.read().decode('utf8')
with open('corpora/canon_texts/' + 'test', 'w', encoding="utf-8") as outfile:
    outfile.write(text)

答案 1 :(得分:-1)

U + feff适用于UTF-16。试试吧。

答案 2 :(得分:-1)

.decode(encoding="utf-8", errors="strict")提供错误处理作为内置功能:

  

错误的默认值为GROUP BY,这意味着编码错误会引发'strict'。其他可能的值包括UnicodeError'ignore'以及通过'replace'注册的任何其他名称,请参阅codecs.register_error()部分。

可能最安全的选择是

Error Handlers

将使用反斜杠转义编码错误,因此您可以记录无法解码的内容。

方便的是,您的Moby Dick文本不包含反斜杠,因此可以很容易地检查哪些字符无法解码。

该文字有什么奇怪之处在于该网站表示它位于decode("utf8", errors='backslashreplace') ,但utf-8\efeff的BOM。在utf-16中进行解码,看起来您只是遇到了最后一个字符utf-16(这是一个utf-8行结尾)的问题,可以安全地删除

0x0a