¿Cómo urlencode una cadena de consulta en Python?


552

Estoy tratando de codificar esta cadena antes de enviarla.

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

Respuestas:


561

Debe pasar sus parámetros urlencode()como una asignación (dict) o una secuencia de 2 tuplas, como:

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

Python 3 o superior

Utilizar:

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

Tenga en cuenta que esto no hace la codificación de URL en el sentido comúnmente utilizado (mire la salida). Para ese uso urllib.parse.quote_plus.


12
"Tenga en cuenta que urllib.urlencode no siempre funciona. El problema es que algunos servicios se preocupan por el orden de los argumentos, que se pierden al crear el diccionario. Para tales casos, urllib.quote_plus es mejor, como sugirió Ricky. "
Blairg23

16
Técnicamente, eso es un error en los servicios, ¿no?
holdenweb

55
y ¿cómo podría uno hacer esto si solo desea que una URL de cadena sea segura, sin construir una cadena de argumento de consulta completa?
Mike 'Pomax' Kamermans

1
@ Mike'Pomax'Kamermans: consulte, por ejemplo, stackoverflow.com/questions/12082314/… o la respuesta de Ricky a esta pregunta.
bgporter

1
@ bk0 parece que su método solo es válido para diccionarios y no para cadenas.
JD Gamboa

1021

Python 2

Lo que estás buscando es 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

En Python 3, el urllibpaquete se ha dividido en componentes más pequeños. Usarás urllib.parse.quote_plus(ten en cuenta el parsemódulo secundario)

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

44
¡Gracias! En mi caso, sin embargo tengo que poner:import urllib.parse ... urllib.parse.quote_plus(query)
ivkremer

3
muy bueno, pero ¿por qué no se usa para Unicode? Si la cadena de url es Unicode, debo codificarla en UTF-8. ¿Hay alguna otra forma de hacerlo?
Karl Doenitz

77
Esto funciona muy bien, pero no pude acceder a algunos servicios en línea (REST) ​​hasta que agregué este parámetro safe = '; /?: @ & = + $,'
rovyko

Lo intenté en Python 3 pero no pude: stackoverflow.com/questions/40557606/…
anfibio

1
python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1])) "string to encode"para un trazador de líneas en la línea de comando
Amos Joshua

52

¡Pruebe las solicitudes en lugar de urllib y no necesita molestarse con urlencode!

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

EDITAR:

Si necesita pares ordenados de nombre-valor o valores múltiples para un nombre, configure los parámetros de la siguiente manera:

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

en lugar de usar un diccionario.


55
Esto no resuelve el problema de ordenar los pares de nombre y valor, también requiere el permiso para instalar bibliotecas externas que podrían no ser factibles para el proyecto.
dreftymac

Publiqué el código mínimo que funcionaría para el OP. El OP no solicitó pares ordenados, sin embargo, también es factible, consulte mi actualización.
Barney

@dreftymac: esto aborda el pedido (aunque no era parte de la pregunta), lea mi respuesta actualizada.
Barney

36

Contexto

  • Python (versión 2.7.2)

Problema

  • Desea generar una cadena de consulta urlencoded.
  • Tiene un diccionario u objeto que contiene los pares nombre-valor.
  • Desea poder controlar el orden de salida de los pares nombre-valor.

Solución

  • urllib.urlencode
  • urllib.quote_plus

Trampas

Ejemplo

La siguiente es una solución completa, que incluye cómo lidiar con algunas dificultades.

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

Prueba esto:

urllib.pathname2url(stringToURLEncode)

urlencodeno funcionará porque solo funciona en diccionarios. quote_plusno produjo la salida correcta.


Eso es realmente útil! En mi caso, tengo solamente una porción de cadena que quiero cifrar la URL de, por ejemplo, quiero transformar my stringa my%20string. ¡Su solución funciona de maravilla para eso!
TanguyP

Trabajó para mí para obtener en %20lugar de +. Gracias
Jossef Harush

21

Tenga en cuenta que el urllib.urlencode no siempre funciona. El problema es que algunos servicios se preocupan por el orden de los argumentos, que se pierden al crear el diccionario. Para tales casos, urllib.quote_plus es mejor, como sugirió Ricky.


2
Funciona bien y conserva el orden si pasa una lista de tuplas:>>> import urllib >>> urllib.urlencode([('name', 'brandon'), ('uid', 1000)]) 'name=brandon&uid=1000'
Brandon Rhodes

8

En Python 3, esto funcionó conmigo

import urllib

urllib.parse.quote(query)

6

para futuras referencias (ej .: para python3)

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

1
por lo general, solo desea codificar los valores de la URL, lo que ha hecho aquí haría una consulta GET no válida
Codewithcheese

El resultado para 'c:/2 < 3'en Windows es '///C://2%20%3C%203'. Quiero algo que solo salga 'c:/2%20%3C%203'.
binki

3

Para su uso en scripts / programas que necesitan ser compatibles con python 2 y 3, el módulo seis proporciona funciones de comillas y códigos de urlen:

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

Si urllib.parse.urlencode () le está dando errores, intente con el módulo urllib3.

La sintaxis es la siguiente:

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

1

Otra cosa que podría no haberse mencionado ya es que urllib.urlencode()codificará valores vacíos en el diccionario como la cadena en Nonelugar de tener ese parámetro como ausente. No sé si esto normalmente se desea o no, pero no se ajusta a mi caso de uso, por lo tanto, tengo que usarlo quote_plus.


0

Para Python 3, urllib3 funciona correctamente, puede usar lo siguiente según sus documentos oficiales :

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')
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.