如何在Python中以UTF-8编码将数据写入磁盘?

0 投票
2 回答
1732 浏览
提问于 2025-04-16 00:29

以下是一些Python代码...

html_data = urllib2.urlopen(some_url).read()
f = codecs.open(filename, 'w', encoding='utf-8')
f.write(html_data)
f.close()

... 有时会出现 UnicodeDecodeError 错误...

File "/.../lib/python2.6/codecs.py", line 686, in write
  return self.writer.write(data)
File "/.../lib/python2.6/codecs.py", line 351, in write
  data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 5605: ordinal not in range(128)

我有几个问题:

  • 我该如何确保我的 urllib2.urlopen(some_url).read() 调用总是返回UTF-8格式的数据?
  • 我的 codecs.open(...) 调用有没有什么问题,导致它无法以UTF-8编码将数据存储到磁盘上?

2 个回答

2

问题不在于 codecs.open,而是你传给 .write 的字节串,它里面有 \xd0 这个代码,明显是用某种 ISO-8859-* 或相关编码格式编码的。

urllib2.urlopen 返回一个响应对象,除了像文件一样的行为外,还有一个额外的方法:

info() — 返回页面的元信息,比如头部信息,以 httplib.HTTPMessage 实例的形式呈现(可以参考 HTTP头部快速参考

特别是对于文本类内容,Content-Type 头部应该有一个 charset 参数,指定它使用的编码,比如 Content-Type: text/html; charset=ISO-8859-4。你需要解析并提取出 charset,然后用它来把内容解码成Unicode(这样你的 codecs.open 打开的文件对象在 write 时总是接收Unicode参数,并且能正确地以 utf-8 格式写出内容)。

如果 charset 缺失,或者用它解码文本时出现错误(这说明 charset 可能不对),作为最后的救命稻草,你可以尝试使用 通用编码检测器,它使用一些启发式方法来进行检测(毕竟,网上很多页面的元数据都有严重错误,还有破损的HTML等等)。

1
  1. 据我所知,你是做不到这一点的。不过,你可以从头部信息或HTML中检测编码,然后重新编码。
  2. 我不太确定。我一直使用二进制模式来写文件,这样总是能正常工作。

示例:

data = urlopen(uri).read().decode(encoding)
f = open(file_name, 'wb')
f.write(data.encode('utf-8'))
f.close()

撰写回答