Come urlencode una stringa di query in Python?


552

Sto cercando di urlencode questa stringa prima di inviare.

queryString = 'eventName=' + evt.fields["eventName"] + '&' + 'eventDescription=' + evt.fields["eventDescription"]; 

Risposte:


561

Devi passare i tuoi parametri in urlencode()una mappatura (dict) o in una sequenza di 2 tuple, come:

>>> import urllib
>>> f = { 'eventName' : 'myEvent', 'eventDescription' : 'cool event'}
>>> urllib.urlencode(f)
'eventName=myEvent&eventDescription=cool+event'

Python 3 o versioni successive

Uso:

>>> urllib.parse.urlencode(f)
eventName=myEvent&eventDescription=cool+event

Nota che questo non fa la codifica dell'URL nel senso comunemente usato (guarda l'output). Per quell'uso urllib.parse.quote_plus.


12
"Si noti che urllib.urlencode non sempre risolve il problema. Il problema è che alcuni servizi si preoccupano dell'ordine degli argomenti, che si perde quando si crea il dizionario. In questi casi, urllib.quote_plus è migliore, come ha suggerito Ricky. "
Blairg23,

16
Tecnicamente, questo è un bug nei servizi, non è vero?
holdenweb,

5
e come si farebbe se si volesse solo rendere sicuro un URL di stringa, senza creare una stringa di argomento di query completa?
Mike 'Pomax' Kamermans,

1
@ Mike'Pomax'Kamermans - si veda ad esempio stackoverflow.com/questions/12082314/... o la risposta di Ricky a questa domanda.
bgporter,

1
@ bk0 sembra che il tuo metodo sia valido solo per i dizionari e non per le stringhe.
JD Gamboa,

1021

Python 2

Quello che stai cercando è urllib.quote_plus:

>>> urllib.quote_plus('string_of_characters_like_these:$#@=?%^Q^$')
'string_of_characters_like_these%3A%24%23%40%3D%3F%25%5EQ%5E%24'

Python 3

In Python 3, il urllibpacchetto è stato suddiviso in componenti più piccoli. Utilizzerai urllib.parse.quote_plus(nota il parsemodulo figlio)

import urllib.parse
urllib.parse.quote_plus(...)

4
Grazie! Nel mio caso però devo mettere:import urllib.parse ... urllib.parse.quote_plus(query)
ivkremer,

3
molto bene, ma perché non viene utilizzato per Unicode? se la stringa dell'URL è Unicode, devo codificarla in UTF-8. Esiste un altro modo per farlo?
Karl Doenitz,

7
Funziona benissimo, ma non ho potuto accedere ad alcuni servizi online (REST) ​​fino a quando non ho aggiunto questo parametro safe = '; /?: @ & = + $,'
rovyko

L'ho provato in Python 3 ma non sono stato in grado di: stackoverflow.com/questions/40557606/…
amphibient

1
python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1])) "string to encode"per una riga sulla riga di comando
Amos Joshua

52

Prova le richieste invece di urllib e non devi preoccuparti di urlencode!

import requests
requests.get('http://youraddress.com', params=evt.fields)

MODIFICARE:

Se hai bisogno di coppie nome-valore ordinate o di più valori per un nome, imposta i parametri in questo modo:

params=[('name1','value11'), ('name1','value12'), ('name2','value21'), ...]

invece di usare un dizionario.


5
Questo non affronta il problema di ordinare le coppie valore-valore, inoltre richiede l'autorizzazione per installare librerie esterne che potrebbero non essere realizzabili per il progetto.
dreftymac,

Ho pubblicato il codice minimo che avrebbe funzionato per l'OP. L'OP non ha richiesto coppie ordinate, ma è anche possibile, vedi il mio aggiornamento.
Barney,

@dreftymac: questo risolve l'ordine (anche se non faceva parte della domanda), leggi la mia risposta aggiornata.
Barney,

36

Contesto

  • Python (versione 2.7.2)

Problema

  • Si desidera generare una stringa di query codificata url.
  • Hai un dizionario o un oggetto contenente le coppie nome-valore.
  • Volete essere in grado di controllare l'ordinamento di output delle coppie nome-valore.

Soluzione

  • urllib.urlencode
  • urllib.quote_plus

insidie

Esempio

Quella che segue è una soluzione completa, incluso come affrontare alcune insidie.

### ********************
## init python (version 2.7.2 )
import urllib

### ********************
## first setup a dictionary of name-value pairs
dict_name_value_pairs = {
  "bravo"   : "True != False",
  "alpha"   : "http://www.example.com",
  "charlie" : "hello world",
  "delta"   : "1234567 !@#$%^&*",
  "echo"    : "user@example.com",
  }

### ********************
## setup an exact ordering for the name-value pairs
ary_ordered_names = []
ary_ordered_names.append('alpha')
ary_ordered_names.append('bravo')
ary_ordered_names.append('charlie')
ary_ordered_names.append('delta')
ary_ordered_names.append('echo')

### ********************
## show the output results
if('NO we DO NOT care about the ordering of name-value pairs'):
  queryString  = urllib.urlencode(dict_name_value_pairs)
  print queryString 
  """
  echo=user%40example.com&bravo=True+%21%3D+False&delta=1234567+%21%40%23%24%25%5E%26%2A&charlie=hello+world&alpha=http%3A%2F%2Fwww.example.com
  """

if('YES we DO care about the ordering of name-value pairs'):
  queryString  = "&".join( [ item+'='+urllib.quote_plus(dict_name_value_pairs[item]) for item in ary_ordered_names ] )
  print queryString
  """
  alpha=http%3A%2F%2Fwww.example.com&bravo=True+%21%3D+False&charlie=hello+world&delta=1234567+%21%40%23%24%25%5E%26%2A&echo=user%40example.com
  """ 


23

Prova questo:

urllib.pathname2url(stringToURLEncode)

urlencodenon funzionerà perché funziona solo sui dizionari. quote_plusnon ha prodotto l'output corretto.


È davvero utile! Nel mio caso, ho solo una parte di stringa che voglio codifica URL, ad esempio voglio trasformare my stringa my%20string. La tua soluzione funziona come un fascino per quello!
TanguyP,

Ha funzionato per me %20invece di +. Grazie
Jossef Harush,

21

Si noti che urllib.urlencode non fa sempre il trucco. Il problema è che alcuni servizi hanno a cuore l'ordine degli argomenti, che si perde quando si crea il dizionario. In questi casi, urllib.quote_plus è migliore, come ha suggerito Ricky.


2
Funziona bene e conserva l'ordine se si passa un elenco di tuple:>>> import urllib >>> urllib.urlencode([('name', 'brandon'), ('uid', 1000)]) 'name=brandon&uid=1000'
Brandon Rodi

8

In Python 3, ha funzionato con me

import urllib

urllib.parse.quote(query)

6

per riferimenti futuri (es: per python3)

>>> import urllib.request as req
>>> query = 'eventName=theEvent&eventDescription=testDesc'
>>> req.pathname2url(query)
>>> 'eventName%3DtheEvent%26eventDescription%3DtestDesc'

1
di solito vuoi solo url codificare i valori, quello che hai fatto qui farebbe una query GET non valida
Codewithcheese

L'output per 'c:/2 < 3'su Windows è '///C://2%20%3C%203'. Voglio qualcosa che sarebbe appena uscita 'c:/2%20%3C%203'.
binki,

3

Per l'uso in script / programmi che devono supportare sia Python 2 che 3, il modulo sei fornisce funzioni di citazione e urlencode:

>>> from six.moves.urllib.parse import urlencode, quote
>>> data = {'some': 'query', 'for': 'encoding'}
>>> urlencode(data)
'some=query&for=encoding'
>>> url = '/some/url/with spaces and %;!<>&'
>>> quote(url)
'/some/url/with%20spaces%20and%20%25%3B%21%3C%3E%26'

2

Se urllib.parse.urlencode () ti dà errori, prova il modulo urllib3.

La sintassi è la seguente:

import urllib3
urllib3.request.urlencode({"user" : "john" }) 

1

Un'altra cosa che potrebbe non essere già stata menzionata è che urllib.urlencode()codificherà i valori vuoti nel dizionario come stringa Noneinvece di avere quel parametro come assente. Non so se questo è tipicamente desiderato o meno, ma non si adatta al mio caso d'uso, quindi devo usare quote_plus.


0

Per Python 3 urllib3 funziona correttamente, puoi usare come segue secondo i suoi documenti ufficiali :

import urllib3

http = urllib3.PoolManager()
response = http.request(
     'GET',
     'https://api.prylabs.net/eth/v1alpha1/beacon/attestations',
     fields={  # here fields are the query params
          'epoch': 1234,
          'pageSize': pageSize 
      } 
 )
response = attestations.data.decode('UTF-8')
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.