Kodowanie/dekodowanie URL za pomocą Pythona

Próbuję kodować i przechowywać, i dekodować argumenty w Pythonie i gubię się gdzieś po drodze. Oto moje kroki:

1) używam Google toolkit ' s gtm_stringByEscapingForURLArgument Aby przekonwertować NSString poprawnie do przekazywania argumentów HTTP.

2) na moim serwerze (python) przechowuję te argumenty łańcuchowe jako coś w rodzaju u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\\|~<>\u20ac\xa3\xa5\u2022.,?!\'' (zauważ, że są to standardowe klawisze na klawiaturze iphone ' a w widoku "123" i widoku"#+=", znaki \u i \x, w których znajdują się prefiksy monetarne jak funt, jen itp.)

3) wywoĹ 'am urllib.quote(myString,'') na tej przechowywanej wartoĹ" ci, prawdopodobnie do %-escape them do transportu do klienta, aby Klient nie mogĹ ' ich uniknÄ ... ć.

Wynik jest taki, że otrzymuję wyjątek, gdy próbuję zapisać wynik ucieczki%. Czy jest jakiś kluczowy krok, który przeoczyłem, który musi być zastosowany do przechowywanej wartości w formacie \u i \ x, aby poprawnie przekonwertować ją do wysyłania przez http?

Update : sugestia oznaczona jako odpowiedź poniżej zadziałała dla mnie. Zapewniam jednak pewne aktualizacje, aby odnieść się do poniższych komentarzy, aby były kompletne.

Wyjątek, który otrzymałem zacytował problem z \u20ac. Nie wiem, czy to był problem z tym konkretnie, a nie fakt, że był to pierwszy znak unicode w łańcuchu.

Ten znak \u20ac jest unicode dla symbolu "euro". W zasadzie stwierdziłem, że będę miał z tym problemy, chyba że użyję metody urllib2 quote.

Author: bluish, 2010-08-25

3 answers

Kodowanie Url " raw " unicode nie ma sensu. To, co musisz zrobić, to .encode("utf8") najpierw, aby mieć znane kodowanie bajtów, a następnie .quote() to.

Wyjście nie jest zbyt ładne, ale powinno być poprawne kodowanie uri.

>>> s = u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\|~<>\u20ac\xa3\xa5\u2022.,?!\''
>>> urllib2.quote(s.encode("utf8"))
'1234567890-/%3A%3B%28%29%24%26%40%22.%2C%3F%21%27%5B%5D%7B%7D%23%25%5E%2A%2B%3D_%5C%7C%7E%3C%3E%E2%82%AC%C2%A3%C2%A5%E2%80%A2.%2C%3F%21%27'

Pamiętaj, że będziesz musiał zarówno unquote() jak i decode() to, aby wydrukować to poprawnie, jeśli debugujesz lub cokolwiek innego.

>>> print urllib2.unquote(urllib2.quote(s.encode("utf8")))
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'
>>> # oops, nasty  means we've got a utf8 byte stream being treated as an ascii stream
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))).decode("utf8")
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'

Tak robią funkcje django wymienione w innej odpowiedzi.

The funkcje django.utils.http.urlquote () i django.utils.http.urlquote_plus () są wersje standardu Pythona urllib.quote () I urllib.quote_plus() które działają ze znakami Nie-ASCII. (Dane są konwertowane do UTF-8 przed do kodowania.)

Bądź ostrożny, jeśli stosujesz jakieś dalsze cudzysłowy lub kodowania, aby nie zmanipulować rzeczy.

 70
Author: pycruft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-19 15:10:31

Chcę poprzeć uwagę pycrufta. protokoły internetowe ewoluowały przez dziesięciolecia, a radzenie sobie z różnymi zestawami Konwencji może być kłopotliwe. teraz adresy URL nie są jawnie zdefiniowane dla znaków, ale tylko dla bajtów (oktetów). jako historyczny zbieg okoliczności, adresy URL są jednym z miejsc, w których można tylko zakładać, ale nie wymuszać ani bezpiecznie oczekiwać obecności kodowania. istnieje jednak konwencja, która preferuje latin-1 i utf-8 nad innymi kodowaniami. przez jakiś czas wyglądało to tak 'Unicode percent escapes ' byłoby przyszłością, ale nigdy się nie załapały.

Niezwykle ważne jest, aby być pedantycznie wybrednym w tej dziedzinie, jeśli chodzi o różnicę między obiektami unicode i oktetem strings (w Pythonie str obiektami unicode i bytes/bytearray obiektów w Pythonie >= 3.0). niestety, z mojego doświadczenia jest to z wielu powodów dość trudne do czystego oddzielenia tych dwóch pojęć w Pythonie 2.x.

Jeszcze bardziej OT, gdy ty jeśli chcesz otrzymywać żądania HTTP innych firm, nie możesz całkowicie polegać na adresach URL wysyłanych w procentach, kodowanych utf-8: mogą tam być zarówno sporadyczne %uxxxx escape, jak i przynajmniej firefox 2.x używany do kodowania adresów URL jako latin-1, gdzie to możliwe, i jako utf-8 tylko wtedy, gdy jest to konieczne.

 4
Author: flow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-25 14:40:28

Nie masz szczęścia z stdlib, urllib.quote nie działa z unicode. Jeśli używasz django możesz użyć django.utils.http.urlquote, który działa poprawnie z unicode

 2
Author: almir karic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-25 06:33:23