我从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>
答案 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