Как я могу декодировать эту строку utf-8, выбранную на случайном веб-сайте и сохраненную Django ORM, используя Python? - PullRequest
5 голосов
/ 07 июля 2011

Я проанализировал файл и сохранил его содержимое в базе данных, используя Django.Веб-сайт был на 100% на английском, поэтому я наивно предполагал, что это будет ASCII все время, и счастливо сохранил текст как Unicode.

Вы догадываетесь до конца истории: -)

КогдаЯ печатаю, получаю обычную ошибку кодирования:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' in position 48: ordinal not in range(128)

Быстрый поиск говорит мне, что u '\ u2019' - это UTF-8 представление .

repr(string)отображает мне это:

"u'his son\\u2019s friend'"

Затем, конечно, я попробовал django.utils.encoding.smart_str и более прямой подход с использованием string.encode ('utf-8'), и я получил что-то для печати.К сожалению, в моем терминале (linux UTF-8) он печатает так:

In [76]: repr(string.encode('utf-8'))
Out[76]: "'his son\\xe2\\x80\\x99s friend '"

In [77]: print string.encode('utf-8')
his son�s friend

Не то, что я ожидал.Я подозреваю, что дважды что-то закодировал или пропустил важный момент.

Конечно, оригинальная кодировка файла не указывается вместе с файлом.Думаю, я мог бы прочитать HTTP-заголовки или спросить веб-мастера, но так как \ u2019s выглядит как UTF-8, я предположил, что это был utf-8.Я могу быть очень неправ, скажите мне, если я прав.

Решения, очевидно, оценены, но глубокое объяснение причины и того, что нужно сделать, чтобы этого не случилось снова, было бы еще больше.Меня часто укушает кодировка, которая показывает, что я до сих пор не полностью освоил предмет.

Ответы [ 3 ]

6 голосов
/ 07 июля 2011

Вы в порядке.У вас есть правильные данные.Да, исходные данные - UTF-8 (основанный на контексте u2019 имеет смысл как апостроф между «сыном» и «с»).Странный ? символ ошибки, вероятно, просто означает, что шрифт конфигурации вашего терминала не имеет глифа для этого символа (причудливый апостроф).Ничего страшного.Данные будут правильными там, где они рассчитывают.Если вы нервничаете, попробуйте несколько различных комбинаций терминала / ОС (я использую iTerm для OS X).Я потратил много времени, объясняя своим ребятам из QA, что страшный знак вопроса ? просто означает, что у них не установлен китайский шрифт на их окнах (в моем случае мы тестировали с китайскими данными).Вот некоторые комментарии

#Create a Python Unicode object
#(abstract code points, independent of any encoding)
#single backslash tells python we want to represent
#a code point by its unicode code point number, typed out with ASCII numbers
>>> s1 = u'his son\u2019s friend'

#If you just type it at the prompt,
#the interpreter does the equivalent of `print repr(s1)`
#and since repr means "show it like a string typed into a python source file",
#you get your ASCII escaped version back
>>> s1
u'his son\u2019s friend'
>>> print repr(s1)
u'his son\u2019s friend'

#This isn't ASCII, so encoding into ASCII generates your original
#error as expected
>>> s1.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character
 u'\u2019' in position 7: 
ordinal not in range(128)

# Encode in UTF-8 and now we have a string,
# which gets displayed as hex escapes.     
#Unicode code point 2019 looks like it gets 3 bytes in UTF-8 (yup, it does)
>>> s1.encode('utf-8')
'his son\xe2\x80\x99s friend'

#My terminal DOES have a different glyph (symbol) to use here,
#so it displays OK for me.
#Note that my terminal has a different glyph for a normal ASCII apostrophe
#(straight vertical)
>>> print s1
his son’s friend
>>> repr(s1)
"u'his son\\u2019s friend'"
>>> str(s1.encode('utf-8'))
'his son\xe2\x80\x99s friend'

См. Также: http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html

См. Также для символа 2019 (e28099 в шестнадцатеричном формате, поиск «2019» на этой странице): http://www.utf8-chartable.de/unicode-utf8-table.pl?start=8000

См. также: http://www.joelonsoftware.com/articles/Unicode.html

1 голос
/ 07 июля 2011

Попробуйте вызвать оболочку Python следующим образом:

python2 -S -i -c 'import sys;sys.setdefaultencoding("utf-8");import site'

Тогда:

>>> s = u'his son\u2019s friend'
>>> print s.encode("utf-8")
his son’s friend

Тогда кодировкой по умолчанию является utf-8, и она должна печататься нормально.

1 голос
/ 07 июля 2011

Может быть, я наивен, но ... разве ваша проблема не в том, что вы избежали лидирующей \ кодовой точки Unicode?

Ваша исходная строка ведет себя так:*

Но удаление убегающего \ дает:

>>> s = u'his son\u2019s friend'
>>> print(s)
his son’s friend
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...