Юникод Python акцентирует (а) гекс - PullRequest
0 голосов
/ 17 октября 2018

У меня есть строка из bs4, которая

s = "vinili-disponibili/311-canzoniere-del-lazio-lassa-st\u00c3\u00a0-la-me-creatura.html"

\u00c3\u00a0 должна быть с ударением a (а) Я получил ее, чтобы она отображалась в консоли частично корректно как

vinili-disponibili/311-canzoniere-del-lazio-lassa-stà -la-me-creatura.html

с

str2 = u'%s' % s
print(str2.encode('utf-8').decode('unicode-escape'))

, но он декодирует c3 и a0 отдельно, поэтому я получаю тильду А вместо акцента а.Я знаю, что c3 a0 - это шестнадцатеричное utf-8 для акцента a.Я понятия не имею, что происходит, и я попал сюда, используя Google и комбинаторный подход к полученным ответам.Вся эта штука с кодированием символов кажется мне большим беспорядком.

То, как это должно быть,

311-canzoniere-del-lazio-lassa-stà-la-me-creatura.html

РЕДАКТИРОВАТЬ: метод Андрея работал при печати, но пытается использоватьurlopen со строкой, которую я получаю UnicodeEncodeError: 'ascii' codec can't encode character '\xe0' in position 60: ordinal not in range(128)

После использования unquote(str,":/") это дает UnicodeEncodeError: 'ascii' codec can't encode characters in position 56-57: ordinal not in range(128).

Ответы [ 2 ]

0 голосов
/ 20 октября 2018

Преобразуйте строку обратно в байты, используя .encode('latin-1'), затем декодируйте unicode-escapes \u, снова преобразуйте все в байты, используя "неправильную" кодировку 'latin-1', и, наконец, правильно декодируйте как 'utf-8':

s = "vinili-disponibili/311-canzoniere-del-lazio-lassa-st\u00c3\u00a0-la-me-creatura.html"
s.encode('latin-1').decode('raw_unicode_escape').encode('latin-1').decode('utf-8')

дает:

'vinili-disponibili/311-canzoniere-del-lazio-lassa-stà-la-me-creatura.html'

Это работает по той же причине, что и объясненная в этот ответ .

0 голосов
/ 18 октября 2018

Предполагается, что Python 2:

Это байтовая строка с экранированием Unicode.Экранирование Unicode было сгенерировано неправильно для некоторых данных в кодировке UTF-8:

>>> s = "vinili-disponibili/311-canzoniere-del-lazio-lassa-st\u00c3\u00a0-la-me-creatura.html"
>>> s.decode('unicode-escape')
u'vinili-disponibili/311-canzoniere-del-lazio-lassa-st\xc3\xa0-la-me-creatura.html'

Теперь это строка Unicode, но теперь она выглядит неправильно декодированной, поскольку кодовые точки напоминают байты UTF-8.Выходной кодек latin1 (также iso-8859-1) отображает первые 256 кодовых точек непосредственно в байты 0-255, поэтому используйте этот трюк для преобразования обратно в строку байтов:

>>> s.decode('unicode-escape').encode('latin1')
'vinili-disponibili/311-canzoniere-del-lazio-lassa-st\xc3\xa0-la-me-creatura.html'

Теперьможет быть правильно декодирован как UTF-8:

>>> s.decode('unicode-escape').encode('latin1').decode('utf8')
u'vinili-disponibili/311-canzoniere-del-lazio-lassa-st\xe0-la-me-creatura.html'

Это строка Unicode, поэтому Python отображает значение repr(), которое показывает кодовые точки выше U + 007F в качестве escape-кодов.print чтобы увидеть фактическое значение, предполагая, что ваш терминал правильно сконфигурирован с кодировкой, которая поддерживает печатные символы:

>>> print(s.decode('unicode-escape').encode('latin1').decode('utf8'))
vinili-disponibili/311-canzoniere-del-lazio-lassa-stà-la-me-creatura.html

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

...