преобразование строки, содержащей строки кода в кодировке utf-8 и кодовые точки, в строку в кодировке utf-8 - PullRequest
3 голосов
/ 30 апреля 2011

Я получаю ответ JSON от API, который выглядит следующим образом:

{"excerpt":"...where we\u00e2\u0080\u0099ll just have to wait and see, I\u00e2\u0080\u0099m sure official announcements with start flowing in the coming months \u2013special\u2013..."}

Это необработанный ответ JSON, возвращаемый из вызова API.Теперь, как вы видите, в этом документе JSON есть кодовые точки, которые должны быть при передаче данных Unicode.Но ответ API возвращает неправильные кодовые точки, потому что «выдержка» начинается как «... где мы будем ...» в исходном источнике, которому принадлежит этот выдержка.Как вы видите, последовательность используется для представления символа '-правильная кавычка справа', но кодовая точка этого символа на самом деле \ u2019, а эквивалентная строка, закодированная как utf-8, равна \ xe2 \ x80 \ x99.Таким образом, он возвращает соответствующую строку байтов вместо кодовой точки.Другая проблема состоит в том, что этот ответ содержит правильные кодовые точки, такие как \ u2013 (символ тире), как и в предыдущем ответе, и это делает мой код неспособным обрабатывать обе ситуации.

Я должен в конечном итоге получить некоторые поля из этого ответа(возможно, с использованием json.loads, который преобразует \ u00e2 \ u0080 \ u0099 в \ xe2 \ x80 \ x99, но ничего не делает с \ u2013), объединяет эти поля и отправляет результат в другую библиотеку, которая в конечном итоге использует кодировку urllib.urlencode для кодирования этогоприведите к действительному параметру url utf-8 для отправки ему другого API.

Итак, вот мой вопрос: есть ли способ кодировать строку, которая содержит как строки байтов utf-8, так и кодовые точки Юникода (это результат выполнения json.loads), в другую строку, которая содержит только кодовые точки или utf-8 байтов, чтобы я мог использовать его в urllib.urlencode или, может быть, есть решение, прежде чем делать json.loads?Примечание: я использую Python 2.6.1

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

Любая помощь будет оценена.

1 Ответ

6 голосов
/ 30 апреля 2011

Вы можете использовать регулярное выражение для идентификации последовательностей Unicode типа UTF-8 и обработки их в правильный символ Unicode:

import re
D = {"excerpt":"...where we\u00e2\u0080\u0099ll just have to wait and see, I\u00e2\u0080\u0099m sure official announcements with start flowing in the coming months \u2013special\u2013..."}
s = D['excerpt']
print s
s = s.decode('unicode-escape')
print s
print re.sub(ur'[\xc2-\xf4][\x80-\xbf]+',lambda m: m.group(0).encode('latin1').decode('utf8'),s)

Выход:

...where we\u00e2\u0080\u0099ll just have to wait and see, I\u00e2\u0080\u0099m sure official announcements with start flowing in the coming months \u2013special\u2013...
...where weâll just have to wait and see, Iâm sure official announcements with start flowing in the coming months –special–...
...where we’ll just have to wait and see, I’m sure official announcements with start flowing in the coming months –special–...

Обновить...

Из вашего комментария словарь уже является строкой Юникода, поэтому символы \ u2013 печатаются правильно (см. Первый вывод печати ниже), поэтому decode('unicode-escape') можно пропустить.Оператор re.sub все еще работает:

import re
D = {u'excerpt':u'...where we\xe2\x80\x99ll just have to wait and see, I\xe2\x80\x99m sure official announcements with start flowing in the coming months \u2013special\u2013...'}
s = D[u'excerpt']
print s
print re.sub(ur'[\xc2-\xf4][\x80-\xbf]+',lambda m: m.group(0).encode('latin1').decode('utf8'),s)

Вывод:

...where weâll just have to wait and see, Iâm sure official announcements with start flowing in the coming months –special–...
...where we’ll just have to wait and see, I’m sure official announcements with start flowing in the coming months –special–...
...