Беспроблемная работа с кодировкой в ​​Python

Вопрос про юникод в Python2.

Насколько я знаю об этом, я всегда должен decode все, что я читаю извне (файлы, сеть). decode преобразует внешние байты во внутренние строки Python, используя кодировку, указанную в параметрах. Таким образом, decode("utf8") означает, что внешние байты представляют собой строку юникода, и они будут декодированы в строки python.

Также я всегда должен encode все, что я пишу снаружи. Я указываю кодировку в параметрах функции encode и она конвертирует в правильную кодировку и записывает.

Эти утверждения верны, не так ли?

Но иногда, когда я разбираю html-документы, я получаю ошибки декодирования. Насколько я понимаю, документ в другой кодировке (например cp1252) и ошибка возникает, когда я пытаюсь декодировать это с помощью кодировки utf8. Так что вопрос в том, как написать пуленепробиваемое приложение?

Я обнаружил, что есть хорошая библиотека для угадывания кодировки chardet, и это единственный способ написать пуленепробиваемый Приложения. Верно?


person Community    schedule 03.12.2013    source источник
comment
Документ часто будет сопровождаться заявлением о его кодировке. Проверьте, указана ли кодировка. Если у вас нет кодировки или указана кодировка неверна, вы можете столкнуться с неизбежными ошибками. Лучшее, на что вы можете рассчитывать, — это обрабатывать ошибки с помощью некоторой политики и получать результат, который, возможно, будет похож на то, что вы хотите.   -  person user2357112 supports Monica    schedule 03.12.2013
comment
Я считаю, что лучшим обзором проблем кодирования в Python является следующая страница: sebsauvage.net/python/snyppets/ #unicode Кроме того, в вашем посте есть одно маленькое заблуждение: функция «декодировать» всегда будет давать вам Unicode. Я согласен с предыдущим комментарием, то есть: в первую очередь полагайтесь на объявление кодировки. На самом деле не существует надежного способа справиться с неправильно закодированными документами.   -  person Fred Osterrath    schedule 03.12.2013
comment
stackoverflow.com/questions/606191/ также может помочь в этом.   -  person anatoly techtonik    schedule 16.01.2017


Ответы (3)


... decode("utf8") означает, что внешние байты представляют собой строку юникода, и они будут декодированы в строки python.

...

Эти утверждения верны, не так ли?

Нет, внешние байты — это двоичные данные, а не строка юникода. Таким образом, <str>.decode("utf8") создаст объект Python unicode, интерпретируя байты в <str> как UTF-8; это может вызвать ошибку, если байты не могут быть декодированы как UTF-8.

Определение кодировки любого данного документа не обязательно является простой задачей. Вам либо нужен какой-то внешний источник информации, который сообщает вам кодировку, либо вам нужно что-то знать о том, что находится в документе. Например, если вы знаете, что это HTML-документ с внутренней кодировкой, то вы можете проанализировать документ, используя такой алгоритм, как тот, который описан в стандарте HTML, чтобы найти кодировку, а затем использовать эту кодировку для анализа документа (это двухпроходная операция). Однако только потому, что HTML-документ указывает кодировку, это не означает, что его можно декодировать с помощью этой кодировки. Вы по-прежнему можете получать ошибки, если данные повреждены или документ изначально не был закодирован должным образом.

Существуют библиотеки, такие как chardet (я вижу, вы уже упоминали об этом), которые попытаются угадать кодировку документа для вас (это всего лишь предположение, не обязательно верное). Но у них могут быть свои проблемы, такие как производительность, и они могут не распознать кодировку вашего документа.

person millerdev    schedule 08.12.2013
comment
Этот получает мой голос; но, возможно, подчеркнем, что chardet является эвристическим угадывающим, который не пытается проверить, является ли результат, который он сообщает, действительным - вам нужно будет подготовиться к ошибкам декодирования и, возможно, вернуться к второму лучшему предположению или просто сдаться ( например, неправильно сконфигурированный веб-сервер может обслуживать вас набором байтов JPEG, которые просто не имеют язык). - person tripleee; 16.12.2015

Попробуйте обернуть свои функции в вызовы try:except:.

  • Попробуйте декодировать как utf-8:
  • Поймать исключение, если не utf-8:
  • если возникло исключение, попробуйте следующую кодировку:
  • и тд и тп...

Сделайте это функцией, которая возвращает str, когда (и если) она находит кодировку, которая не была исключена, и возвращает None или пустую строку, когда она исчерпывает свой список кодировок и возникает последнее исключение.

Как говорили другие, кодировка должна быть где-то записана, поэтому сначала проверьте это.

Неэффективно и, откровенно говоря, из-за моего уровня навыков, может быть далеко, но, на мой взгляд новичка, это может облегчить некоторые проблемы при работе с неизвестным или недокументированным кодированием.

person WeRelic    schedule 08.12.2013

Преобразование в unicode из cp437. Таким образом, вы получаете право на юникод и обратно.

person anatoly techtonik    schedule 16.12.2015
comment
Если вы -1, скажите, нужно ли вам объяснение, почему cp437. Если вам просто не нравится cp437, потому что unicode модно, ничего не поделаешь. - person anatoly techtonik; 17.12.2015