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.