Python, función opuesta urllib.urlencode

88

¿Cómo puedo convertir datos después de procesarlos urllib.urlencodea dict? urllib.urldecodeno existe.

Artyom
fuente

Respuestas:

124

Como los documentos de urlencodeejemplo,

El módulo urlparse proporciona las funciones parse_qs () y parse_qsl () que se utilizan para analizar cadenas de consulta en estructuras de datos de Python.

(En versiones anteriores de Python, estaban en el cgimódulo). Así por ejemplo:

>>> import urllib
>>> import urlparse
>>> d = {'a':'b', 'c':'d'}
>>> s = urllib.urlencode(d)
>>> s
'a=b&c=d'
>>> d1 = urlparse.parse_qs(s)
>>> d1
{'a': ['b'], 'c': ['d']}

La diferencia obvia entre el diccionario original dy el de "ida y vuelta" d1es que este último tiene listas (de un solo elemento, en este caso) como valores; eso se debe a que no hay garantía de unicidad en las cadenas de consulta, y puede ser importante a su aplicación para saber qué valores múltiples se han dado para cada clave (es decir, las listas no siempre serán de un solo elemento ;-).

Como alternativa:

>>> sq = urlparse.parse_qsl(s)
>>> sq  
[('a', 'b'), ('c', 'd')]
>>> dict(sq)
{'a': 'b', 'c': 'd'}

puede obtener una secuencia de pares (urlencode también acepta ese argumento; en este caso, conserva el orden, mientras que en el caso de dict no hay orden para conservar ;-). Si sabe que no hay "claves" duplicadas, o no le importa si las hay, entonces (como he mostrado) puede llamar dictpara obtener un diccionario con valores que no estén en la lista. En general, sin embargo, debe considerar lo que desea hacer si hay duplicados presentes (Python no decide eso en su nombre ;-).

Alex Martelli
fuente
1
Respuesta muy completa. ¡Increíble!
Hartley Brody
1
Voto a favor de Python 2, sin embargo, Python 3 está todo en el urllibmódulo. Vea la respuesta de @phobie.
openwonk
19

Código de Python 3 para la solución de Alex:

>>> import urllib.parse
>>> d = {'a':'b', 'c':'d'}
>>> s = urllib.parse.urlencode(d)
>>> s
'a=b&c=d'
>>> d1 = urllib.parse.parse_qs(s)
>>> d1
{'a': ['b'], 'c': ['d']}

La alternativa:

>>> sq = urllib.parse.parse_qsl(s)
>>> sq
[('a', 'b'), ('c', 'd')]
>>> dict(sq)
{'a': 'b', 'c': 'd'}

parse_qsl es reversible:

>>> urllib.parse.urlencode(sq)
'a=b&c=d'
phobie
fuente
16

urllib.unquote_plus()hace lo que quiere. Reemplaza los escapes% xx por su equivalente de un solo carácter y reemplaza los signos más con espacios.

Ejemplo:

unquote_plus('/%7Ecandidates/?name=john+connolly') 

rendimientos

'/~candidates/?name=john connolly'.
Andrew Farrell
fuente
2
Dijo que quería un dictamen. Entonces tu respuesta es incorrecta.
balrok
4
yay, esto es lo que estaba buscando.
Joe