2012-09-21 12 views
6

Estoy tratando de hacer algo de automatización en un script de Python y me he encontrado con un problema. Estoy tratando de hacer una POST a un servidor.Pasando el carácter '+' en una solicitud POST en Python

url = 'http://www.example.com' 
params = {'arg0': 'value', 'arg1': '+value'} 

f = urllib.urlopen(url, urllib.urlencode(params)) 
print f.read() 

me han hecho una captura de Wireshark de la operación navegador equivalente en el caso de la segunda arg, arg1 se pasa como +value, sin embargo, cuando lo hago con Python la + se cambia a %2B, es decir

Line-based text data: application/x-www-form-urlencoded 
arg0=value&arg1=%2Bvalue 

cuando debería ser:

Line-based text data: application/x-www-form-urlencoded 
arg0=value&arg1=+value 

también he utilizado el módulo de peticiones y que parecen s hacer lo mismo.

url = 'http://www.example.com' 
params = {'arg0': 'value', 'arg1': '+value'} 

f = requests.post(url, params) 

Google no es su amigo cuando se tiene un problema relacionado con '+', ya que parece ser un cajón de sastre para tantas otras cosas.

+0

¿qué versión de solicitudes estás utilizando? – root

+0

Hice una pip install solicitudes de hoy - 0.14.0 –

+5

"Google no es tu amigo cuando tienes un problema relacionado con '+'" - Para buscar caracteres especiales, hay motores de búsqueda especiales como http://symbolhound.com/ – l4mpi

Respuesta

7

El carácter + es la codificación adecuada para un espacio al citar datos GET o POST. Por lo tanto, también se debe escapar un carácter literal +, para evitar que se descodifique a un espacio en el otro extremo. Consulte RFC 2396, section 2.2, section 3.4 y la HTML specification, application/x-www-form-urlencoded section:

nombres y valores de control se escaparon. Los caracteres espaciales se reemplazan por `+ ', y luego los caracteres reservados se escapan como se describe en [RFC1738], sección 2.2.

Si envías datos a una aplicación que no decodifica un carácter + a un espacio, sino que trata los datos como literal signos más lugar, es necesario codificar los parámetros de sí mismo utilizando la urllib.quote function lugar, especificando que la + personaje no se va a codificar:

import urllib 
def urlencode_withoutplus(query): 
    if hasattr(query, 'items'): 
     query = query.items() 
    l = [] 
    for k, v in query: 
     k = urllib.quote(str(k), safe=' /+') 
     v = urllib.quote(str(v), safe=' /+') 
     l.append(k + '=' + v) 
    return '&'.join(l) 

demostración:

>>> urlencode_withoutplus({'arg0': 'value', 'arg1': '+value'}) 
'arg0=value&arg1=+value' 

al utilizar requests, sólo tiene que pasar en el resultado de la función anterior como el valor data, pero en ese caso es necesario establecer manualmente el tipo de contenido:

requests.post(url, urlencode_withoutplus(query), 
    headers={'Content-Type': 'application/x-www-form-urlencoded'}) 
+0

Parece que va por el camino opuesto al que yo quería. ¿Estás diciendo que debería estar haciendo un urllib.quote (params ['arg1']) antes de hacer un urllib.urlencode ?, porque eso solo arroja '% 252Bvalue' cuando capturo en wireshark. –

+0

@DouglasKastle: No, usa esto * en su lugar * de urllib.urlencode. –

+0

Lamento haber visto su respuesta antes de que se completara –

4
urllib2.quote(' ')  # '%20' 
urllib2.unquote('%20') # ' ' 

¿Por qué no acaba de fin de la cita la parte de parámetros:

f = urllib.urlopen(url, urllib.unquote(urllib.urlencode(params))) 
+0

Interesante, para este caso que probablemente sea suficiente, imagino que hay algunos tipos de params que deben ser protegidos. –

Cuestiones relacionadas