Unescape / unquote stringhe binarie a (esteso) codifica URL in Python
Domanda
per l'analisi avrei dovuto Unescape codifica URL stringhe binarie (caratteri non stampabili più probabile). Le stringhe purtroppo si presentano sotto forma estesa URL-codifica, ad esempio "% U616f". Voglio memorizzarli in un file che poi contiene i valori binari grezzi, ad esempio. 0x61 0x6F qui.
Come faccio ad avere questo in dati binari in pitone? (Urllib.unquote gestisce solo il -form "% HH")
Soluzione
Credo che si dovrà scrivere la funzione di decoder da soli. Ecco un'implementazione per iniziare:
def decode(file):
while True:
c = file.read(1)
if c == "":
# End of file
break
if c != "%":
# Not an escape sequence
yield c
continue
c = file.read(1)
if c != "u":
# One hex-byte
yield chr(int(c + file.read(1), 16))
continue
# Two hex-bytes
yield chr(int(file.read(2), 16))
yield chr(int(file.read(2), 16))
Utilizzo:
input = open("/path/to/input-file", "r")
output = open("/path/to/output-file", "wb")
output.writelines(decode(input))
output.close()
input.close()
Altri suggerimenti
Le stringhe purtroppo sono disponibili in forma URL-encoding esteso, per esempio "% U616f"
Tra l'altro questo non è nulla a che fare con l'URL-codifica. Si tratta di un formato arbitrario truccata prodotto dalla funzione escape () di JavaScript e praticamente nient'altro. Se è possibile, la cosa migliore da fare sarebbe quella di cambiare il supporto JavaScript per utilizzare la funzione encodeURIComponent invece. Questo vi darà una, UTF-8 stringa con codifica URL standard di corretta.
es. "% U616f". Voglio memorizzarli in un file che poi contiene i valori binari grezzi, ad esempio. 0x61 0x6F qui.
Sei sicuro 0x61 0x6F (le lettere "AO") è il flusso di byte che si desidera memorizzare? Ciò implicherebbe la codifica UTF-16 BE; stai trattando tutte le corde in quel modo?
In genere ci si vuole trasformare l'input in Unicode poi scrivere utilizzando una codifica appropriato, ad esempio UTF-8 o UTF-16. Ecco un modo rapido per farlo, basandosi su l'hack di fare Python leggere '% u1234' come formato stringa di escape u '\ u1234':
>>> ex= 'hello %e9 %u616f'
>>> ex.replace('%u', r'\u').replace('%', r'\x').decode('unicode-escape')
u'hello \xe9 \u616f'
>>> print _
hello é 慯
>>> _.encode('utf-8')
'hello \xc2\xa0 \xe6\x85\xaf'
Ecco un approccio regex-based:
# the replace function concatenates the two matches after
# converting them from hex to ascii
repfunc = lambda m: chr(int(m.group(1), 16))+chr(int(m.group(2), 16))
# the last parameter is the text you want to convert
result = re.sub('%u(..)(..)', repfunc, '%u616f')
print result
dà
ao