Comment encoder des paramètres d'URL en pourcentage en Python?


299

Si je fais

url = "http://example.com?p=" + urllib.quote(query)
  1. Il n'encode /pas %2F(rompt la normalisation OAuth)
  2. Il ne gère pas Unicode (il lève une exception)

Existe-t-il une meilleure bibliothèque?


1
Ce ne sont pas des paramètres d'URL, pour info. Vous devez clarifier.
Jamie Marshall

Réponses:


390

Python 2

De la documentation :

urllib.quote(string[, safe])

Remplacez les caractères spéciaux dans la chaîne à l'aide de l'échappement% xx. Les lettres, les chiffres et les caractères '_.-' ne sont jamais cités. Par défaut, cette fonction est destinée à la citation de la section de chemin de l'URL. Le paramètre optionnel sûr spécifie des caractères supplémentaires qui ne doivent pas être cités - sa valeur par défaut est '/'

Cela signifie que le fait de passer '' en toute sécurité résoudra votre premier problème:

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

À propos du deuxième problème, il y a un rapport de bogue à ce sujet ici . Apparemment, il a été corrigé en python 3. Vous pouvez le contourner en encodant en utf8 comme ceci:

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

Au fait, jetez un oeil à urlencode

Python 3

La même chose, sauf remplacer urllib.quotepar urllib.parse.quote.


1
Merci, les deux ont très bien fonctionné. urlencode appelle simplement quoteplus plusieurs fois dans une boucle, ce qui n'est pas la normalisation correcte pour ma tâche (oauth).
Paul Tarjan

6
la spécification: rfc 2396 les définit comme réservés. reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","C'est à cela que traite urllib.quote.
Jeff Sheffield

63
urllib.quotedéplacé vers urlib.parse.quote, depuis Python3.
Hibou57

5
urllib.parse.quote docs
Andreas Haferburg

De plus, dans le cas de l'encodage d'une requête de recherche, il vaut peut-être mieux utiliser quote_plus: docs.python.org/3/library/… 1. Il encode les barres obliques par défaut 2. Il encode également les espaces
Pavel Vergeev

174

En Python 3, urllib.quotea été déplacé vers urllib.parse.quoteet il gère unicode par défaut.

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

2
Le nom quoteest plutôt vague en tant que global. Il pourrait être plus agréable d'utiliser quelque chose comme urlencode: from urllib.parse import quote as urlencode.
Luc

Notez qu'il ya une fonction nommée urlencodedans urllib.parsedéjà fait quelque chose de complètement différent, vous feriez mieux de choisir un autre nom ou un risque de confusion au sérieux les lecteurs futurs de votre code.
jaymmer

48

Ma réponse est similaire à la réponse de Paolo.

Je pense que le module requestsest beaucoup mieux. C'est basé sur urllib3. Vous pouvez essayer ceci:

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

5
requests.utils.quoteest un lien vers python quote. Voir les sources de demande .
Cjkjvfnby

16
requests.utils.quoteest un wrapper de compatibilité mince urllib.quotepour python 2 et urllib.parse.quotepour python 3
Jeff Sheffield

13

Si vous utilisez django, vous pouvez utiliser urlquote:

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

Notez que les modifications apportées à Python depuis la publication de cette réponse signifient qu'il s'agit désormais d'un wrapper hérité. Du code source de Django 2.1 pour django.utils.http:

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

2

Il vaut mieux l'utiliser urlencodeici. Pas beaucoup de différence pour un seul paramètre mais à mon humble avis, le code est plus clair. (Cela semble déroutant de voir une fonction quote_plus! En particulier ceux provenant d'autres langueurs)

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

Documents

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.