Як відсотково кодувати параметри URL-адреси в Python?


299

Якщо я це роблю

url = "http://example.com?p=" + urllib.quote(query)
  1. Він не кодує /до %2F(порушує нормалізацію OAuth)
  2. Він не обробляє Unicode (він кидає виняток)

Чи є краща бібліотека?


1
Це не параметри URL-адреси, FYI. Вам слід уточнити.
— Джеймі Маршалл

Відповіді:


390

Пітон 2

З документів :

urllib.quote(string[, safe])

Замініть спеціальні символи в рядку, використовуючи% xx escape. Букви, цифри та символи "_.-" ніколи не цитуються. За замовчуванням ця функція призначена для цитування розділу шляху URL-адреси. Необов’язковий безпечний параметр вказує додаткові символи, які не слід цитувати - його значення за замовчуванням - '/'

Це означає, що передача "" для безпечного вирішить вашу першу проблему:

>>> 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

Пітон 3

Те саме, крім заміни urllib.quoteна urllib.parse.quote.


1
Дякую, обидва працювали чудово. urlencode просто викликає quoplus багато разів у циклі, що не є правильною нормалізацією для мого завдання (oauth).
— Пол Тарджан

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

63
urllib.quoteпереміщено до urlib.parse.quotePython3.
— Hibou57


Також у випадку кодування пошукового запиту вам, можливо, краще скористатися quo_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уже, робить щось зовсім інше, тому вам краще вибрати інше ім’я або ризикнути серйозно заплутати майбутніх читачів вашого коду.
— джеймер

48

Моя відповідь схожа на відповідь Паоло.

Я думаю, що модуль requestsнабагато краще. Це засновано на urllib3. Ви можете спробувати це:

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

5
requests.utils.quoteє посиланням на python quote. Дивіться джерела запиту .
— Cjkjvfnby

16
requests.utils.quote- це тонка обгортка сумісності urllib.quoteдля python 2 та urllib.parse.quotepython 3
— Jeff Sheffield

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.