Как процентное кодирование параметров URL в Python?


299

Если я сделаю

url = "http://example.com?p=" + urllib.quote(query)
  1. Это не закодировать /к %2F(перерывы OAuth нормализация)
  2. Он не обрабатывает Unicode (он выдает исключение)

Есть ли лучшая библиотека?


1
Это не параметры URL, к вашему сведению. Вы должны уточнить.
Джейми Маршалл

Ответы:


390

Python 2

Из документов :

urllib.quote(string[, safe])

Замените специальные символы в строке, используя escape-символ% xx. Буквы, цифры и символы «_.-» никогда не заключаются в кавычки. По умолчанию эта функция предназначена для цитирования раздела пути URL-адреса. Необязательный параметр safe указывает дополнительные символы, которые не следует заключать в кавычки - его значение по умолчанию равно '/'

Это означает, что прохождение '' для безопасного решения вашей первой проблемы:

>>> urllib.quote('/test')
'/test'
>>> urllib.quote('/test', safe='')
'%2Ftest'

О втором вопросе, есть ошибка отчет об этом здесь . Очевидно, это было исправлено в python 3. Вы можете обойти это, кодируя как utf8 так:

>>> query = urllib.quote(u"Müller".encode('utf8'))
>>> print urllib.unquote(query).decode('utf8')
Müller

Кстати, посмотрите на urlencode

Python 3

То же самое, кроме замены urllib.quoteна urllib.parse.quote.


1
Спасибо вам, оба работали отлично. urlencode просто вызывает quoteplus много раз в цикле, что не является правильной нормализацией для моей задачи (oauth).
Пол Тарьян

6
spec: rfc 2396 определяет их как зарезервированные. reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","Это то, с чем имеет дело urllib.quote.
Джефф Шеффилд,

63
urllib.quoteперешел на urlib.parse.quote, начиная с Python3.
Hibou57


Кроме того, в случае кодирования поискового запроса, возможно, лучше использовать quote_plus: docs.python.org/3/library/… 1. Он по умолчанию кодирует косую черту 2. Он также кодирует пробелы
Павел Вергеев

174

В Python 3 urllib.quoteбыл перемещен в urllib.parse.quoteи он по умолчанию обрабатывает Unicode.

>>> from urllib.parse import quote
>>> quote('/test')
'/test'
>>> quote('/test', safe='')
'%2Ftest'
>>> quote('/El Niño/')
'/El%20Ni%C3%B1o/'

2
Название quoteдовольно расплывчато как глобальное. Может быть , лучше использовать что - то вроде UrlEncode: from urllib.parse import quote as urlencode.
Люк

Обратите внимание , что существует функция с именем urlencodeв urllib.parseуже , что делает что - то совсем другое, так что вы бы лучше выбирать другое имя или риск серьезно заблуждение читателей в будущем вашего кода.
Jaymmer - Восстановить Монику

48

Мой ответ похож на ответ Паоло.

Я думаю, что модуль requestsнамного лучше. Это основано на urllib3. Вы можете попробовать это:

>>> from requests.utils import quote
>>> quote('/test')
'/test'
>>> quote('/test', safe='')
'%2Ftest'

5
requests.utils.quoteэто ссылка на питона quote. Смотрите источники запросов .
Cjkjvfnby

16
requests.utils.quoteтонкая оболочка совместимости urllib.quoteдля Python 2 и urllib.parse.quotePython 3
Джефф Шеффилд

13

Если вы используете django, вы можете использовать urlquote:

>>> from django.utils.http import urlquote
>>> urlquote(u"Müller")
u'M%C3%BCller'

Обратите внимание, что изменения в Python после публикации этого ответа означают, что теперь это устаревшая оболочка. Из исходного кода Django 2.1 для django.utils.http:

A legacy compatibility wrapper to Python's urllib.parse.quote() function.
(was used for unicode handling on Python 2)

2

Лучше использовать urlencodeздесь. Не большая разница для одного параметра, но IMHO делает код более понятным. (Это выглядит сбивающим с толку, чтобы увидеть функцию quote_plus! Особенно те, которые приходят от других томится)

In [21]: query='lskdfj/sdfkjdf/ksdfj skfj'

In [22]: val=34

In [23]: from urllib.parse import urlencode

In [24]: encoded = urlencode(dict(p=query,val=val))

In [25]: print(f"http://example.com?{encoded}")
http://example.com?p=lskdfj%2Fsdfkjdf%2Fksdfj+skfj&val=34

Документы

urlencode: https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlencode

quote_plus: https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote_plus

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.