2012-09-21 13 views
6

Próbuję wykonać trochę automatyzacji w skrypcie w języku Python i wystąpił problem. Próbuję wykonać POST na serwerze.Przekazywanie znaku "+" w żądaniu POST w języku Python

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

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

Zrobiłem zrzut wireshark równoważnej pracy przeglądarki, gdzie drugi Arg, arg1 jest przekazywana jako +value, jednak kiedy robię to z Python + zostaje zmieniona na %2B, tj

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

gdy powinno być:

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

mam również używany moduł wnioski i wydaje s zrobić to samo.

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

f = requests.post(url, params) 

Google nie jest twoim przyjacielem, gdy masz problem związany z "+", ponieważ wydaje się, że jest to haczyk dla tak wielu innych rzeczy.

+0

jakiej wersji zgłoszeń używasz? – root

+0

Zrobiłem instalację pip dziś żądania - 0.14.0 –

+5

"Google nie jest twoim przyjacielem, gdy masz problem związany z" + "" - Do wyszukiwania znaków specjalnych, istnieją specjalne wyszukiwarki, takie jak http://symbolhound.com/ – l4mpi

Odpowiedz

7

Znak + jest właściwym kodowaniem dla spacji podczas cytowania danych GET lub POST. Zatem, literalny znak + również musi zostać zmieniony, aby nie został zdekodowany do przestrzeni na drugim końcu. Patrz RFC 2396, section 2.2, section 3.4 i HTML specification, application/x-www-form-urlencoded section:

nazwy sterujące i wartości są uciekł. Znaki spacji są zastępowane znakami "+", a znaki zastrzeżone są usuwane zgodnie z opisem w sekcji 02., sekcja 2.2.

Jeśli Piszesz danych do wniosku, że nie zdekodować + znak spacji lecz traktuje takie dane jak dosłowne znaki plus zamiast tego trzeba zakodować parametry siebie używając urllib.quote function zamiast, określając, że + postać nie ma być zakodowane:

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) 

Demo:

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

Podczas korzystania requests, można po prostu przejść w wyniku powyższej funkcji jako wartości data, ale w tym przypadku trzeba ręcznie ustawić rodzaj zawartości:

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

To wydaje się iść w przeciwną stronę, niż chciałem. Czy mówisz, że powinienem zrobić urllib.quote (parametry ['arg1']) zanim zrobię kod urllib.urlen ?, ponieważ to tylko daje "% 252Bvalue" kiedy przechwytuję na wireshark. –

+0

@DouglasKastle: Nie, używaj tego * zamiast * z urllib.urlencode. –

+0

Przepraszam, widziałem twoją odpowiedź, zanim została zakończona. –

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

Więc dlaczego nie tylko koniec cytatu część parametrów:

+0

Ciekawe, że w tym przypadku, który prawdopodobnie będzie wystarczający, wyobrażam sobie, że istnieją pewne typy parametrów, które muszą być chronione. –