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

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

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

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

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

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

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

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

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

47
задан bluish 8 September 2011 в 11:54
поделиться

3 ответа

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.utils.http.urlquote() и django.utils.http.urlquote_plus() являются версии стандарта Python urllib.quote() и urllib.quote_plus() которые работают с символами, отличными от ASCII. (данные конвертируются в UTF-8 перед к кодировке.)

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

70
ответ дан 26 November 2019 в 19:45
поделиться

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

2
ответ дан 26 November 2019 в 19:45
поделиться

Я хочу поддержать замечание Пикруфта. Веб-протоколы развивались десятилетиями, и работа с различными наборами соглашений может быть обременительной. теперь URL-адреса явно не определены для символов, а только для байтов (октетов). как историческое совпадение, URL-адреса являются одним из мест, где вы можете только предполагать, но не применять или безопасно ожидать присутствия кодировки. однако здесь принято отдавать предпочтение latin-1 и utf-8 другим кодировкам. какое-то время казалось, что «процентные побеги юникода» будут в будущем, но они так и не прижились.

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

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

4
ответ дан 26 November 2019 в 19:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: