2010-04-22 31 views
29

Ho scaricato una pagina web nel mio script python. Nella maggior parte dei casi, questo funziona correttamente.In Python, come decodificare la codifica GZIP?

Tuttavia, questo aveva un'intestazione di risposta: codifica GZIP, e quando ho provato a stampare il codice sorgente di questa pagina web, aveva tutti i simboli nel mio stucco.

Come decodificarlo come testo normale?

risposta

64

Uso zlib per decomprimere il contenuto gzip dal web.

import zlib 

... 
# f=urllib2.urlopen(url) 
decompressed_data=zlib.decompress(f.read(), 16+zlib.MAX_WBITS) 
+0

mi hai salvato la vita) – Oduvan

+3

potresti per favore commentare quale è il secondo argomento per decomprimere? E perché è così ... beh ... strano? – DataGreed

+1

@DataGreed, il secondo argomento riguarda la dimensione della finestra, fare riferimento alla risposta di John Machin riportata di seguito. – YOU

25

Decomprime il flusso di byte utilizzando il modulo gzip incorporato.

Se avete problemi, non mostrano il codice minimo esatto che è stato utilizzato, il messaggio di errore esatto e traceback, insieme con il risultato di print repr(your_byte_stream[:100])

Ulteriori informazioni

1. Per una spiegazione della confusione di gzip/zlib/deflate, leggere la sezione "Altri usi" di this Wikipedia article.

2. Può essere più facile da utilizzare il modulo zlib che il modulo gzip se si dispone di una stringa piuttosto che un file. Purtroppo il Python docs sono incompleti/errato:

""" zlib.decompress (stringa [, wbits [, bufsize]]) ... Il valore assoluto della wbits è il logaritmo in base due dimensioni del buffer di cronologia (la "dimensione della finestra") utilizzato durante la compressione dei dati. Il suo valore assoluto dovrebbe essere compreso tra 8 e 15 per le versioni più recenti della libreria zlib, valori più grandi risultanti in una compressione migliore a spese di un maggiore utilizzo della memoria. 15. Quando wbits è negativo, l'intestazione gzip standard viene soppressa, si tratta di una funzionalità non documentata della libreria zlib, utilizzata per la compatibilità con il formato del file di compressione di unzip "" "

In primo luogo, 8 < = log2_window_size < = 15, con il significato sopra indicato. Quindi quello che dovrebbe essere un argomento distinto è in cima:

arg == log2_window_size significa che la stringa è in formato zlib (RFC 1950, ciò che l'HTTP 1.1 RFC 2616 chiama confusionmente "deflate").

arg == -log2_window_size significa assumere stringa è in formato deflate (RFC 1951; ciò che le persone che non hanno letto il HTTP 1.1 RFC attentamente effettivamente attuato)

arg == 16 + log_2_window_size significa assumere corda è formato gzip (RFC 1952). Quindi è possibile utilizzare 31.

Le informazioni di cui sopra sono documentate nello zlib C library manual ... Ctrl-F ricerca windowBits.

+0

Grazie per le informazioni esaurienti sull'argomento. – temoto

8

io uso qualcosa di simile:

f = urllib2.urlopen(request) 
data = f.read() 
try: 
    from cStringIO import StringIO 
    from gzip import GzipFile 
    data2 = GzipFile('', 'r', 0, StringIO(data)).read() 
    data = data2 
except: 
    #print "decompress error %s" % err 
    pass 
return data 
3

per python3

provare questo

import gzip 

    fetch = opener.open(request) # basically get a response object 
    data = gzip.decompress(fetch.read()) 
    data = str(data,'utf-8') 
-1

È possibile utilizzare urllib3 per decodificare facilmente gzip.

urllib3.response.decode_gzip(response.data) 
+0

Perché è stato downvoted? –

+1

@SamP Penso che poiché non funziona così com'è, non spiega nulla. L'ho provato, avrò pochi errori di sicuro. Questa non è una risposta valida. – erm3nda

+0

Mi piace il pacchetto 'requests', che può gestire' gzip' automaticamente – WeizhongTu

1

simili risposta di Shatu per python3, ma disposti in modo leggermente diverso:

import gzip 

s = Request("https://someplace.com", None, headers) 
r = urlopen(s, None, 180).read() 
try: r = gzip.decompress(r) 
except OSError: pass 
result = json_load(r.decode()) 

Questo metodo consente di avvolgimento del gzip.decompress() in un try/tranne per catturare e passare l'OSError che porta a situazioni in cui è possibile ottenere dati misti compressi e non compressi. Alcune piccole stringhe diventano effettivamente più grandi se sono codificate, quindi vengono inviati i dati semplici.

Problemi correlati