Python IRC бот и проблема с кодировкой - PullRequest
3 голосов
/ 02 июня 2009

В настоящее время у меня есть простой IRC-бот, написанный на python.

Так как я перенес его на python 3.0, который различает байты и строки юникода, у меня начались проблемы с кодированием. В частности, с другими, не отправляющими UTF-8.

Теперь я мог бы просто сказать всем отправлять UTF-8 (что они должны делать независимо), но еще лучшим решением было бы попытаться заставить python по умолчанию использовать другую кодировку или что-то подобное.

Пока код выглядит так:

data = str(irc.recv(4096),"UTF-8", "replace")

Что, по крайней мере, не вызывает исключений. Однако я хочу пройти мимо этого: я хочу, чтобы мой бот по умолчанию использовал другую кодировку, или попытался как-то обнаружить «проблемные символы».

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

Как мне поступить так?

Ответы [ 4 ]

3 голосов
/ 02 июня 2009

chardet должно помочь - это каноническая библиотека Python для обнаружения неизвестных кодировок.

0 голосов
/ 11 июля 2012

Использование только chardet приводит к плохим результатам для ситуаций, когда сообщения короткие (что имеет место в IRC).

Chardet в сочетании с запоминанием кодировки для конкретного пользователя в сообщениях может иметь смысл. Однако для простоты я бы использовал некоторые предполагаемые кодировки (кодировки зависят от культуры и эпохи, см. http://en.wikipedia.org/wiki/Internet_Relay_Chat#Character_encoding), и если они потерпят неудачу, я перейду к chardet (если кто-то использует некоторые восточноазиатские кодировки, это поможет нас нет).

Например:

def decode_irc(raw, preferred_encs = ["UTF-8", "CP1252", "ISO-8859-1"]):
    changed = False
    for enc in preferred_encs:
        try:
            res = raw.decode(enc)
            changed = True
            break
        except:
            pass
    if not changed:
        try:
            enc = chardet.detect(raw)['encoding']
            res = raw.decode(enc)
        except:
            res = raw.decode(enc, 'ignore')
return res
0 голосов
/ 21 апреля 2012

Chardet, вероятно, будет вашим лучшим решением, как упомянул RichieHindle. Однако, если вы хотите охватить около 90% текста, вы увидите, что вы можете использовать то, что я использую:

def decode(bytes):
    try:
        text = bytes.decode('utf-8')
    except UnicodeDecodeError:
        try:
            text = bytes.decode('iso-8859-1')
        except UnicodeDecodeError:
            text = bytes.decode('cp1252')
    return text


def encode(bytes):
    try:
        text = bytes.encode('utf-8')
    except UnicodeEncodeError:
        try:
            text = bytes.encode('iso-8859-1')
        except UnicodeEncodeError:
            text = bytes.encode('cp1252')
    return text
0 голосов
/ 02 июня 2009

Хорошо, после некоторых исследований выяснилось, что у chardet проблемы с python 3. Решение, как оказалось, проще, чем я думал. Я решил вернуться к CP1252, если UTF-8 не обрезает его:

data = irc.recv ( 4096 )
try: data = str(data,"UTF-8")
except UnicodeDecodeError: data = str(data,"CP1252")

Что, кажется, работает. Хотя он не определяет кодировку, и поэтому, если кто-то пришел с кодировкой, которая не является ни UTF-8, ни CP1252, у меня снова возникнет проблема.

Это действительно просто временное решение.

...