WedX - журнал о программировании и компьютерных науках

Лучший способ декодировать неизвестную кодировку unicoding в Python 2.5

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

import logging
import codecs
from utils.error import Error

class UnicodingError(Error):
    pass

# these encodings should be in most likely order to save time
encodings = [ "ascii", "utf_8", "big5", "big5hkscs", "cp037", "cp424", "cp437", "cp500", "cp737", "cp775", "cp850", "cp852", "cp855", 
    "cp856", "cp857", "cp860", "cp861", "cp862", "cp863", "cp864", "cp865", "cp866", "cp869", "cp874", "cp875", "cp932", "cp949", 
    "cp950", "cp1006", "cp1026", "cp1140", "cp1250", "cp1251", "cp1252", "cp1253", "cp1254", "cp1255", "cp1256", "cp1257", "cp1258", 
    "euc_jp", "euc_jis_2004", "euc_jisx0213", "euc_kr", "gb2312", "gbk", "gb18030", "hz", "iso2022_jp", "iso2022_jp_1", "iso2022_jp_2", 
    "iso2022_jp_2004", "iso2022_jp_3", "iso2022_jp_ext", "iso2022_kr", "latin_1", "iso8859_2", "iso8859_3", "iso8859_4", "iso8859_5", 
    "iso8859_6", "iso8859_7", "iso8859_8", "iso8859_9", "iso8859_10", "iso8859_13", "iso8859_14", "iso8859_15", "johab", "koi8_r", "koi8_u", 
    "mac_cyrillic", "mac_greek", "mac_iceland", "mac_latin2", "mac_roman", "mac_turkish", "ptcp154", "shift_jis", "shift_jis_2004", 
    "shift_jisx0213", "utf_32", "utf_32_be", "utf_32_le", "utf_16", "utf_16_be", "utf_16_le", "utf_7", "utf_8_sig" ]

def unicode(string):
    '''make unicode'''
    for enc in self.encodings:
        try:
            logging.debug("unicoder is trying " + enc + " encoding")
            utf8 = unicode(string, enc)
            logging.info("unicoder is using " + enc + " encoding")
            return utf8
        except UnicodingError:
            if enc == self.encodings[-1]:
                raise UnicodingError("still don't recognise encoding after trying do guess.")

  • Автоматическое обнаружение абсолютно ничего не знает о вашем тексте, но если вы знаете хотя бы язык, на котором находится текст, вариантов будет очень мало. Вот почему определение кодировки в основном означает попытку угадать язык на основе частоты букв. 11.11.2009
  • Эмм, unicode () возвращает Unicode, а не UTF-8. 11.11.2009

Ответы:


1

Существуют две библиотеки общего назначения для обнаружения неизвестных кодировок:

chardet должен быть портом способа, которым это делает firefox

Вы можете использовать следующее регулярное выражение для обнаружения utf8 из байтовых строк:

import re

utf8_detector = re.compile(r"""^(?:
     [\x09\x0A\x0D\x20-\x7E]            # ASCII
   | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
   |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
   | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
   |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
   |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
   | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
   |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
  )*$""", re.X)

На практике, если вы имеете дело с английским языком, в 99,9% случаев я обнаружил, что следующие работают:

  1. если он передает указанное выше регулярное выражение, это ascii или utf8
  2. если он содержит какие-либо байты из 0x80-0x9f, но не 0xa4, это Windows-1252
  3. если он содержит 0xa4, предположим, что это latin-15
  4. в противном случае предположим, что это latin-1
11.11.2009
  • Я закодировал это и поместил сюда pastebin.com/f76609aec 12.11.2009
  • Возникла проблема с вставленным вами кодом: ^(?:\xA4)*$ будет соответствовать, если строка содержит полностью \xA4 и не содержит других символов. Вам просто нужны re.compile(r'\xA4') и re.compile(r'[\x80-\xBF]') для двух других регулярных выражений. 12.11.2009

  • 2

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

    Мой единственный дополнительный совет к тому, что вы сделали: вместо того, чтобы упорядочивать список возможных кодировок в наиболее вероятном порядке, вы должны упорядочивать его по специфичности. Я обнаружил, что определенные наборы символов являются подмножествами других, поэтому, если вы отметите utf_8 в качестве второго варианта, вы пропустите когда-либо обнаружение подмножеств utf_8 (я думаю, что один из корейских наборов символов использует то же числовое пространство, что и utf ).

    11.11.2009
  • Верно. ascii является подмножеством utf-8 и также будет правильно декодироваться как utf-8, поэтому ascii можно не указывать. 8-битные кодировки, такие как latin-1, во всех случаях будут декодировать в что-то, поэтому поместите одно из них последним. 11.11.2009

  • 3

    Поскольку вы используете Python, вы можете попробовать UnicodeDammit. Это часть Beautiful Soup, которая также может оказаться вам полезной.

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

    11.11.2009
  • Пытался это сделать на раннем этапе, но это немного не получилось. 11.11.2009
  • Действительно! Какие были проблемы? Возможно, будет легче добиться того, чтобы это работало, чем кататься самостоятельно. 11.11.2009
  • Дерьмо, которое вы можете найти в этом мире? 06.05.2012
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]