2010-08-25 21 views
45

Sto cercando di codificare e archiviare e decodificare gli argomenti in Python e di perdersi da qualche parte lungo il percorso. Ecco i miei passi:Codifica/decodifica URL con Python

1) Io uso google toolkit's gtm_stringByEscapingForURLArgument per convertire correttamente un NSString per passare agli argomenti HTTP.

2) Sul mio server (python), memorizzo questi argomenti di stringa come qualcosa come u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\\|~<>\u20ac\xa3\xa5\u2022.,?!\'' (nota che questi sono i tasti standard su una tastiera iphone nella vista "123" e la vista "# + =", la \u e \x caratteri a che vi sia alcuni prefissi monetarie come sterlina, yen, ecc)

3) che io chiamo urllib.quote(myString,'') su quel valore memorizzato, presumibilmente per% -escape loro per il trasporto al cliente in modo che il cliente possa unpercent loro fuga.

Il risultato è che sto ricevendo un'eccezione quando provo a registrare il risultato di% escape. C'è qualche passo cruciale che sto trascurando che deve essere applicato al valore memorizzato con il formato \ u e \ x al fine di convertirlo correttamente per l'invio su http?

Aggiornamento: il suggerimento contrassegnato come la risposta di seguito ha funzionato per me. Sto fornendo alcuni aggiornamenti per affrontare i commenti qui sotto per essere completo, però.

L'eccezione che ho ricevuto ha citato un problema con \u20ac. Non so se sia stato un problema specifico, piuttosto che il fatto che fosse il primo carattere unicode nella stringa.

Che il carattere \u20ac è l'unicode per il simbolo "euro". Fondamentalmente ho trovato che avrei avuto problemi con esso a meno che non ho usato il metodo urllib2 quote.

+1

Fornire i dettagli di eccezione e una traccia, se possibile. –

+0

Sembra che la stringa non sia una stringa unicode valida. Ho provato a stamparlo semplicemente e mi dà errore di codifica per il carattere di \ u20ac. –

risposta

69

la codifica dell'URL di un "raw" unicode non ha molto senso. Quello che devi fare è .encode("utf8") prima in modo da avere una codifica di byte nota e quindi .quote().

L'output non è molto carino ma dovrebbe essere una codifica uri corretta.

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

Ricordate che è necessario sia unquote() e decode() questo per stamparlo correttamente se si sta debug o qualsiasi altra cosa.

>>> 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-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!' 

Questo è, infatti, quello che il django functions citato in un'altra risposta fare.

Le funzioni django.utils.http.urlquote() e django.utils.http.urlquote_plus() sono versioni dello standard urllib.quote di Python() e urllib.quote_plus() che funzionano con caratteri non ASCII. (I dati vengono convertiti in UTF-8 prima di codifica.)

stare attenti se si sta applicando ulteriori citazioni o codifiche di non storpiare le cose.

+2

Hai appena salvato la mia giornata con djang.utils.http.urlquote/unquote! Molte grazie. –

2

Sei sfortunato con stdlib, urllib.quote non funziona con unicode. Se usi django puoi usare django.utils.http.urlquote che funziona correttamente con unicode

4

voglio secondare l'osservazione di pycruft. i protocolli web si sono evoluti nel corso dei decenni e trattare con le varie serie di convenzioni può essere complicato. ora gli URL capita di essere esplicitamente non definiti per i caratteri, ma solo per i byte (ottetti). come coincidenza storica, gli URL sono uno dei luoghi in cui puoi solo assumere, ma non far rispettare o non aspettarti che una codifica sia presente. tuttavia, esiste una convenzione per preferire latin-1 e utf-8 rispetto ad altre codifiche qui. per un po ', sembrava che' unicode percent escapes 'sarebbe il futuro, ma non hanno mai preso piede.

è di fondamentale importanza per essere pedante schizzinosi in questo settore circa la differenza tra unicode oggetti e ottetto str Ings (in Python < 3.0; questo è, confusamente, str oggetti Unicode e bytes/bytearray oggetti in Python> = 3.0) . sfortunatamente, nella mia esperienza è abbastanza difficile separare in modo pulito i due concetti in Python 2.x.

ancora più OT, quando si desidera ricevere le richieste di terze parti HTTP, non si può assolutamente fare affidamento su URL di essere inviato in, ottetti utf-8-codificati per cento-sfuggito: ci possono essere entrambi l'occasionale %uxxxx fuga in là , e almeno firefox 2.x usato per codificare gli URL come latin-1 ove possibile, e come utf-8 solo dove necessario.