Python для отображения специальных символов

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

Я пытаюсь напечатать строку, но при печати она не показывает специальные символы (например, æ, ø, å, ö и ü). Когда я печатаю строку, используя repr(), я получаю следующее:

u'Von D\xc3\xbc' и u'\xc3\x96berg'

Кто-нибудь знает, как я могу преобразовать это в Von Dü и Öberg? Для меня важно, чтобы эти символы не были проигнорированы, например. myStr.encode("ascii", "ignore").

ИЗМЕНИТЬ

Это код, который я использую. Я использую BeautifulSoup для очистки веб-сайта. Содержимое ячейки (<td>) в таблице (<table>) помещается в переменную name. Это переменная, которая содержит специальные символы, которые я не могу распечатать.

web = urllib2.urlopen(url);
soup = BeautifulSoup(web)
tables = soup.find_all("table")
scene_tables = [2, 3, 6, 7, 10]
scene_index = 0
# Iterate over the <table>s we want to work with
for scene_table in scene_tables:
    i = 0
    # Iterate over < td> to find time and name
    for td in tables[scene_table].find_all("td"):
        if i % 2 == 0:  # td contains the time
            time = remove_whitespace(td.get_text())
        else:           # td contains the name
            name = remove_whitespace(td.get_text()) # This is the variable containing "nonsense"
            print "%s: %s" % (time, name,)
        i += 1
    scene_index += 1

person simonbs    schedule 02.04.2012    source источник
comment
Ваша консоль настроена на режим UTF-8?   -  person Fabian    schedule 02.04.2012
comment
Я использую терминал по умолчанию в Mac OS X, и UTF-8 включен.   -  person simonbs    schedule 02.04.2012


Ответы (3)


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

your_unicode_string =  original_utf8_encoded_bytestring.decode('latin1')

Лекарство состоит в том, чтобы просто обратить процесс вспять, а затем расшифровать.

correct_unicode_string = your_unicode_string.encode('latin1').decode('utf8')

Обновить Судя по предоставленному вами коду, вероятной причиной является то, что веб-сайт заявляет, что он закодирован в ISO-8859-1 (он же latin1), но на самом деле он закодирован в UTF-8. Пожалуйста, обновите свой вопрос, чтобы показать нам URL.

Если вы не можете это показать, прочтите документацию BS; похоже, вам нужно будет использовать:

BeautifulSoup(web, from_encoding='utf8')
person John Machin    schedule 02.04.2012
comment
Я обновил свой вопрос, чтобы показать код, который я использую. Я использую BeautifulSoup для очистки веб-сайта. Затем содержимое ячейки таблицы выбрасывается в переменную name. Это переменная, которая содержит специальные символы, которые я не могу распечатать. - person simonbs; 02.04.2012
comment
Использование name.encode('latin1').decode('utf8') решает все мои проблемы. Персонажи выглядят идеально, но вы говорите, что это неправильный способ? - person simonbs; 02.04.2012
comment
@SimonBS: перечитайте первое предложение моего ответа. Всегда лучше понимать свою реальную проблему и устранять ее в источнике, а не ниже по течению. Это кодирование/декодирование просто устраняет основную проблему. - person John Machin; 02.04.2012
comment
BeautifulSoup(web, from_encoding='utf8') сделал свое дело. Большое спасибо! - person simonbs; 02.04.2012

Поддержка Unicode на многих языках сбивает с толку, поэтому ваша ошибка здесь понятна. Эти строки представляют собой байты UTF-8, которые будут работать правильно, если вы отбросите u впереди:

>>> err = u'\xc3\x96berg'
>>> print err
Ã?berg
>>> x = '\xc3\x96berg'
>>> print x
Öberg
>>> u = x.decode('utf-8')
>>> u
u'\xd6berg'
>>> print u
Öberg

Для получения дополнительной информации:

http://www.joelonsoftware.com/articles/Unicode.html

http://docs.python.org/howto/unicode.html


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

def convert_fake_unicode_to_real_unicode(string):
    return ''.join(map(chr, map(ord, string))).decode('utf-8')
person A B    schedule 02.04.2012
comment
Когда я печатаю строки без repr(), я получаю следующее: Ãberg, но я хотел бы иметь Öberg. Если я использую decode('utf-8'), я получу UnicodeEncodeError. Если строки UTF-8, не следует ли писать Ö вместо Ã? - person simonbs; 02.04.2012
comment
Прежде всего вам нужно выяснить, как эти переменные должны иметь тип unicode. На самом деле они имеют кодировку UTF-8 в ascii, поэтому они должны иметь тип str. - person A B; 02.04.2012
comment
-1 для (1) сообщения join/map/chr/map/ord mess (2) UTF-8, закодированного в ascii - person John Machin; 02.04.2012

Содержимое строк не в юникоде, а в кодировке UTF-8.

>>> print u'Von D\xc3\xbc'
Von Dü
>>> print 'Von D\xc3\xbc'
Von Dü

>>> print unicode('Von D\xc3\xbc', 'utf-8')
Von Dü
>>> 

Редактировать:

>>> print '\xc3\x96berg' # no unicode identifier, works as expected because it's an UTF-8 encoded string
Öberg
>>> print u'\xc3\x96berg' # has unicode identifier, means print uses the unicode charset now, outputs weird stuff
Ãberg

# Look at the differing object types:
>>> type('\xc3\x96berg')
<type 'str'>
>>> type(u'\xc3\x96berg')
<type 'unicode'>

>>> '\xc3\x96berg'.decode('utf-8') # this command converts from UTF-8 to unicode, look at the unicode identifier in the output
u'\xd6berg'
>>> unicode('\xc3\x96berg', 'utf-8') # this does the same thing
u'\xd6berg'
>>> unicode(u'foo bar', 'utf-8') # trying to convert a unicode string to unicode will fail as expected
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: decoding Unicode is not supported
person Fabian    schedule 02.04.2012
comment
Когда я печатаю строки без repr(), я получаю следующее: Ãberg, но я хотел бы иметь Öberg. Если строки UTF-8, не следует ли писать Ö вместо Ã? Если я использую unicode, я получаю следующую ошибку: TypeError: decoding Unicode is not supported. - person simonbs; 02.04.2012
comment
Вы по-прежнему используете идентификатор Unicode (u'foo'). Это строка в кодировке UTF-8, и, используя идентификатор юникода, вы говорите, что это юникод там, где это не так. Вот почему вы получаете Ã вместо Ö. Сбросьте идентификатор, и все будет в порядке. Я обновлю свой ответ, чтобы прояснить его. - person Fabian; 02.04.2012
comment
@SimonBS Я обновил свой ответ. Вы все равно должны прочитать эту ссылку: docs.python.org/howto/unicode.html - person Fabian; 02.04.2012
comment
Я только что прочитал ссылку. Я все еще немного сбит с толку. У меня есть строка myStr, которая имеет тип unicode, что означает, что она имеет идентификатор Unicode. Я хочу удалить этот идентификатор и получить строку в кодировке UTF-8. Как бы я это сделал? Я думал, что это будет просто, как myStr.encode("utf-8"), который возвращает объект типа str, но это вызывает ошибку UnicodeDecodeError. - person simonbs; 02.04.2012
comment
@SimonBS Это должно сработать. Можете ли вы опубликовать этот пример в своем вопросе или на странице pastebin.com? - person Fabian; 02.04.2012
comment
-1 Эти строки не являются юникодными -- repr(those_strings) имеет u впереди; они Юникод, они испорченный Юникод. У него есть ДАННЫЕ, а не литералы исходного кода. u помещается туда с помощью repr(); он не может сбросить идентификатор. - person John Machin; 02.04.2012
comment
@JohnMachin Верно. Сама строка имеет юникод, но содержимое в ней — нет. Под сбросом идентификатора я имел в виду, что он не должен трактовать строку как юникод, потому что текст в ней UTF-8. Я обновил свой ответ. - person Fabian; 02.04.2012