Python, função oposta urllib.urlencode

88

Como posso converter dados após o processamento urllib.urlencodepara dict? urllib.urldecodenão existe.

Artyom
fonte

Respostas:

124

Como os docs para urlencodedigamos,

O módulo urlparse fornece as funções parse_qs () e parse_qsl () que são usadas para analisar strings de consulta em estruturas de dados Python.

(Em versões mais antigas do Python, eles estavam no cgimódulo). Então, por exemplo:

>>> 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']}

A diferença óbvia entre o dicionário original de o "round trip" d1é que o último tem (item único, neste caso) listas como valores - isso porque não há garantia de exclusividade nas strings de consulta, e pode ser importante ao seu aplicativo para saber quais valores múltiplos foram dados para cada chave (ou seja, as listas nem sempre serão de um único item ;-).

Como uma alternativa:

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

você pode obter uma sequência de pares (urlencode também aceita tal argumento - neste caso ele preserva a ordem, enquanto no caso dict não há ordem para preservar ;-). Se você sabe que não há "chaves" duplicadas ou não se importa se há, então (como mostrei) você pode ligar dictpara obter um dicionário com valores não listados. Em geral, no entanto, você precisa considerar o que você quer fazer se duplicatas são presentes (Python não decidir que em seu nome ;-).

Alex Martelli
fonte
1
Resposta muito completa. Impressionante!
Hartley Brody
Votação positiva para Python 2, no entanto, Python 3 está todo no urllibmódulo. Veja a resposta @phobie.
openwonk em
18

Código Python 3 para a solução 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']}

A alternativa:

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

parse_qsl é reversível:

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

urllib.unquote_plus()faz o que você quiser. Ele substitui escapes% xx por seus equivalentes de caractere único e substitui os sinais de mais por espaços.

Exemplo:

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

rendimentos

'/~candidates/?name=john connolly'.
Andrew Farrell
fonte
2
Ele disse que queria um ditado. Portanto, sua resposta está errada.
Balrok
4
sim, isso é o que eu estava procurando.
Joe