Подтвердить что ты не робот

Кодирование/декодирование URL с помощью Python

Я пытаюсь кодировать и хранить и декодировать аргументы в Python и теряться где-то на этом пути. Вот мои шаги:

1) Я использую google toolkit gtm_stringByEscapingForURLArgument для правильного преобразования NSString для передачи аргументов HTTP.

2) На моем сервере (python) я храню эти строковые аргументы как нечто вроде u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\\|~<>\u20ac\xa3\xa5\u2022.,?!\'' (обратите внимание, что это стандартные клавиши на клавиатуре iphone в представлении "123" и "# + =", символы \u и \x в нем есть некоторые денежные префиксы, такие как фунт, иена и т.д.)

3) Я вызываю urllib.quote(myString,'') по этому сохраненному значению, предположительно, чтобы% -escape их для транспорта на клиенте, чтобы клиент мог ускользнуть от них.

В результате я получаю исключение, когда пытаюсь записать результат% escaping. Есть ли какой-то важный шаг, который я упускаю из виду, который должен применяться к сохраненному значению с помощью формата \u и\x, чтобы правильно преобразовать его для отправки по http?

Обновление. Предложение, помеченное как ответ ниже, работало для меня. Тем не менее, я предоставляю некоторые обновления для удовлетворения приведенных ниже комментариев.

Исключение, которое я получил, вызвало проблему с \u20ac. Я не знаю, была ли проблема с этим конкретно, а не тем фактом, что это был первый символ юникода в строке.

То, что \u20ac char является юникодом для символа "евро". В основном я обнаружил, что у меня были бы проблемы с ним, если бы я не использовал метод urllib2 quote.

4b9b3361

Ответ 1

URL-код, кодирующий "сырой" юникод, на самом деле не имеет смысла. Сначала вам нужно .encode("utf8"), чтобы у вас была известная байтовая кодировка, а затем .quote().

Результат не очень красивый, но он должен быть правильной кодировкой uri.

>>> s = u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\|~<>\u20ac\xa3\xa5\u2022.,?!\''
>>> urllib2.quote(s.encode("utf8"))
'1234567890-/%3A%3B%28%29%24%26%40%22.%2C%3F%21%27%5B%5D%7B%7D%23%25%5E%2A%2B%3D_%5C%7C%7E%3C%3E%E2%82%AC%C2%A3%C2%A5%E2%80%A2.%2C%3F%21%27'

Помните, что вам понадобится как unquote(), так и decode(), чтобы правильно распечатать его, если вы отлаживаете или что-то еще.

>>> print urllib2.unquote(urllib2.quote(s.encode("utf8")))
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'
>>> # oops, nasty  means we've got a utf8 byte stream being treated as an ascii stream
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))).decode("utf8")
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'

Это, по сути, то, что делают функции django, упомянутые в другом ответе.

Функции django.utils.http.urlquote() и django.utils.http.urlquote_plus() являются версии стандарта Pythons urllib.quote() и urllib.quote_plus() которые работают с символами, отличными от ASCII. (Данные преобразуются в UTF-8 ранее для кодирования.)

Будьте осторожны, если вы применяете какие-либо дополнительные кавычки или кодировки, чтобы не мешать вещам.

Ответ 2

Я хочу повторить второе замечание. веб-протоколы развивались в течение десятилетий, и работа с различными наборами конвенций может быть громоздкой. теперь URL-адреса явно не определены для символов, но только для байтов (октетов). как историческое совпадение, URL-адреса являются одним из мест, где вы можете только предположить, но не применять или надежно ожидать, что кодировка будет присутствовать. тем не менее, существует соглашение о предпочтительности латинских-1 и utf-8 по сравнению с другими кодировками. какое-то время это выглядело так: " unicode percent escapes 'будет будущим, но они никогда не попадались.

в этой области крайне важно быть педантично придирчивым к различию между объектами unicode и октетом str (в Python < 3.0, то есть смутно, str объектами unicode и bytes/bytearray объектов в Python >= 3.0). к сожалению, по моему опыту, по ряду причин довольно сложно провести чистое разделение двух концепций в Python 2.x.

еще больше OT, когда вы хотите получать сторонние HTTP-запросы, вы не можете полностью полагаться на URL-адреса, отправляемые в октетах с процентным экранированием, с октетами с utf-8: может быть и случайный %uxxxx escape в там, и по крайней мере firefox 2.x используется для кодирования URL-адресов как латинский-1, где это возможно, и как utf-8 только там, где это необходимо.

Ответ 3

Вам не повезло с stdlib, urllib.quote не работает с unicode. Если вы используете django, вы можете использовать django.utils.http.urlquote, который работает правильно с unicode