Как мне записать данные на диск в кодировке UTF-8 на Python? - PullRequest
0 голосов
/ 27 июня 2010

Следующий код 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 голосов
/ 28 июня 2010

Проблема не в 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 ed файловый объект всегда получает аргументы Unicode в write и правильно записывает их в utf-8).

Если charset отсутствует, или использование его для декодирования текста приводит к ошибкам (предполагая, что charset неверно), в качестве последней надежды на спасение вы можете попробовать Universal Encoding Detector , который использует эвристика для этой цели (в конце концов, многие страницы в сети содержат ужасные ошибки метаданных, а также неработающий HTML и т. д.)

1 голос
/ 27 июня 2010
  1. AFAIK, Вы не можете этого сделать.Тем не менее, вы можете обнаружить кодирование из заголовков / HTML и перекодировать.
  2. Я не знаю.Я всегда использовал двоичный режим для записи, и он всегда работал

Пример:

data = urlopen(uri).read().decode(encoding)
f = open(file_name, 'wb')
f.write(data.encode('utf-8'))
f.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...