Есть ли функция библиотеки Python, которая пытается угадать кодировку символов некоторых байтов?
Я пишу какое-то программное обеспечение для обработки почты в Python, которое встречает странные байты в полях заголовков. Я подозреваю, что это просто неправильная почта; само сообщение утверждает, что оно является us-ascii, поэтому я не думаю, что есть истинная кодировка, но я хотел бы получить строку юникода, аппроксимирующую исходную, не выбрасывая UnicodeDecodeError
.
Итак, я ищу функцию, которая принимает str
и, возможно, некоторые подсказки и делает ее darndest, чтобы вернуть мне unicode
. Я мог бы написать один из них, но если такая функция существует, ее автор, вероятно, подумал немного глубже о том, как лучше всего это сделать.
Я также знаю, что дизайн Python предпочитает явно неявное и что стандартная библиотека предназначена для предотвращения неявной магии в декодировании текста. Я просто хочу прямо сказать "идти вперед и угадать".
Ответы
Ответ 1
Насколько я могу судить, стандартная библиотека не имеет функции, хотя ее не так сложно написать, как было предложено выше. Я думаю, что реальная вещь, которую я искал, - это способ декодирования строки и гарантировать, что она не будет генерировать исключение. Этот параметр ошибки для string.decode делает это.
def decode(s, encodings=('ascii', 'utf8', 'latin1')):
for encoding in encodings:
try:
return s.decode(encoding)
except UnicodeDecodeError:
pass
return s.decode('ascii', 'ignore')
Ответ 2
Вам может быть интересен Универсальный детектор кодирования.
Ответ 3
+1 для модуля chardet (предлагается @insin
).
Это не в стандартной библиотеке, но вы можете легко установить ее с помощью следующей команды:
$ pip install chardet
Пример:
>>> import chardet
>>> import urllib
>>> detect = lambda url: chardet.detect(urllib.urlopen(url).read())
>>> detect('http://stackoverflow.com')
{'confidence': 0.85663169917190185, 'encoding': 'ISO-8859-2'}
>>> detect('https://stackoverflow.com/questions/269060/is-there-a-python-lib')
{'confidence': 0.98999999999999999, 'encoding': 'utf-8'}
Смотрите Установка протокола, если у вас его нет.
Ответ 4
Лучший способ сделать это, который я нашел, - итеративно попробовать декодировать проспективное с каждым из наиболее распространенных кодировок внутри try, кроме блока.