Come codificare in percentuale i parametri URL in Python?


299

Se lo faccio

url = "http://example.com?p=" + urllib.quote(query)
  1. Non codifica /in %2F(interrompe la normalizzazione OAuth)
  2. Non gestisce Unicode (genera un'eccezione)

C'è una biblioteca migliore?


1
Questi non sono parametri URL, FYI. Dovresti chiarire.
Jamie Marshall,

Risposte:


390

Python 2

Dai documenti :

urllib.quote(string[, safe])

Sostituisci i caratteri speciali nella stringa usando l'escape% xx. Lettere, cifre e caratteri '_.-' non vengono mai citati. Per impostazione predefinita, questa funzione è intesa per citare la sezione del percorso dell'URL. Il parametro sicuro opzionale specifica caratteri aggiuntivi che non devono essere citati - il suo valore predefinito è '/'

Ciò significa che passare '' per sicurezza risolverà il tuo primo problema:

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

Circa la seconda questione, v'è una segnalazione di bug su di esso qui . Apparentemente è stato risolto in Python 3. Puoi aggirarlo codificando come utf8 in questo modo:

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

A proposito, dai un'occhiata a urlencode

Python 3

Lo stesso, tranne sostituire urllib.quotecon urllib.parse.quote.


1
Grazie, entrambi hanno funzionato alla grande. urlencode chiama quoteplus molte volte in un ciclo, che non è la normalizzazione corretta per il mio compito (oauth).
Paul Tarjan,

6
la specifica: rfc 2396 definisce questi come riservati. Di reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","cosa si occupa urllib.quote.
Jeff Sheffield,

63
urllib.quotespostato a urlib.parse.quote, da Python3.
Hibou57,

5
urllib.parse.quote documenti
Andreas Haferburg,

Inoltre, nel caso della codifica di una query di ricerca, forse è meglio usare quote_plus: docs.python.org/3/library/… 1. Codifica le barre per impostazione predefinita 2. Codifica anche gli spazi
Pavel Vergeev

174

In Python 3, urllib.quoteè stato spostato urllib.parse.quotee gestisce unicode per impostazione predefinita.

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

2
Il nome quoteè piuttosto vago come globale. Potrebbe essere più bello di usare qualcosa come UrlEncode: from urllib.parse import quote as urlencode.
Luc

Si noti che non v'è una funzione chiamata urlencodein urllib.parsegià che fa qualcosa di completamente diverso, quindi faresti meglio a prendere un altro nome o rischi seriamente confondere i lettori futuri del codice.
Jaymmer - Ripristina Monica il

48

La mia risposta è simile alla risposta di Paolo.

Penso che il modulo requestssia molto meglio. Si basa su urllib3. Puoi provare questo:

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

5
requests.utils.quoteè il collegamento a Python quote. Vedi fonti di richiesta .
Cjkjvfnby,

16
requests.utils.quoteè un wrapper di compatibilità sottile urllib.quoteper Python 2 e urllib.parse.quotePython 3
Jeff Sheffield

13

Se stai usando Django, puoi usare urlquote:

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

Si noti che le modifiche a Python da quando è stata pubblicata questa risposta significano che ora è un wrapper legacy. Dal codice sorgente Django 2.1 per django.utils.http:

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

2

È meglio usare urlencodequi. Non molta differenza per singolo parametro, ma IMHO rende il codice più chiaro. (Sembra confuso vedere una funzione quote_plus! Soprattutto quelli che provengono da altri linguaggi)

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

Documenti

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.