2012-03-18 15 views
11

Ho creato un'architettura client/server in python, prendo la richiesta HTTP dal client che viene servita richiedendo un altro server HTTP attraverso il mio codice.Come decodificare i dati compressi gzip restituiti in una risposta HTTP in python?

Quando ottengo la risposta dal terzo server non sono in grado di decodificare i dati compressi con gzip, prima divido i dati di risposta usando \r\n come carattere di separazione che mi ha ottenuto i dati come ultimo elemento nell'elenco, quindi ho provato decomprimerlo con

zlib.decompress(data[-1]) 

ma mi sta dando un errore di intestazioni errate. Come dovrei andare con questo problema?

Codice

client_reply = '' 
       while 1: 
        chunk = server2.recv(512) 
        if len(chunk) : 
         client.send(chunk) 
         client_reply += chunk 
        else: 
         break 
       client_split = client_reply.split("\r\n") 
       print client_split[-1].decode('zlib') 

voglio leggere i dati che vengono stati trasferiti tra il client e il secondo server.

+1

Mostraci il codice! Sei sicuro che i dati non siano stati codificati/decodificati in modo errato (cioè dovrebbero essere trattati come dati binari)? – Cameron

+0

Potrebbe essere che i dati siano suddivisi in più blocchi e che sia necessario analizzare l'intestazione per ottenere la giusta lunghezza. L'intestazione gzip ha informazioni sulla lunghezza –

+0

e se i dati compressi stessi contengono "\ r \ n" al suo interno e lo si interrompe e si decodifica solo una parte anziché tutti i dati compressi? Cercherò di trovare "\ r \ n" nel server prima di inviarlo per convalidare se è il problema. –

risposta

1

Secondo https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html le intestazioni e il corpo sono separati da una riga vuota contenente solo caratteri CRLF. Si potrebbe provare

client_split = client_reply.split("\r\n\r\n",1) 
print client_split[1].decode('zlib') 

La scissione trova la riga vuota e il parametro aggiuntivo limita il numero di suddivisioni - il risultato è array con due articoli, intestazioni e corpo. Ma è difficile consigliare qualsiasi cosa senza sapere di più sul tuo codice e sulla stringa effettiva che viene divisa.

4

Specificare il wbits quando si utilizza zlib.decompress(string, wbits, bufsize) vedere la fine della "risoluzione dei problemi" ad esempio.

Risoluzione dei problemi

lascia l'inizio con aa comando ricciolo che scarica una risposta byte-gamma con una "content-encoding" sconosciuto (nota: sappiamo di prima mano che è una sorta di cose compressa, mabye deflate forse gzip):

export URL="https://commoncrawl.s3.amazonaws.com/crawl-data/CC-MAIN-2016-18/segments/1461860106452.21/warc/CC-MAIN-20160428161506-00007-ip-10-239-7-51.ec2.internal.warc.gz" 
curl -r 266472196-266527075 $URL | gzip -dc | tee hello.txt 

con le seguenti intestazioni di risposta:

HTTP/1.1 206 Partial Content 
x-amz-id-2: IzdPq3DAPfitkgdXhEwzBSwkxwJRx9ICtfxnnruPCLSMvueRA8j7a05hKr++Na6s 
x-amz-request-id: 14B89CED698E0954 
Date: Sat, 06 Aug 2016 01:26:03 GMT 
Last-Modified: Sat, 07 May 2016 08:39:18 GMT 
ETag: "144a93586a13abf27cb9b82b10a87787" 
Accept-Ranges: bytes 
Content-Range: bytes 266472196-266527075/711047506 
Content-Type: application/octet-stream 
Content-Length: 54880 
Server: AmazonS3 

Quindi al punto.

Consente visualizzare l'output esadecimale dei primi 10 byte: uscita curl -r 266472196-266472208 $URL | xxd

esadecimale:

0000000: 1f8b 0800 0000 0000 0000 ecbd eb 

possiamo vedere alcune basi di ciò stiamo lavorando con i valori esadecimali.

Circa il che significa la sua, probabilmente un gzip (1f8b) utilizzando sgonfiare (0800) senza un tempo di modifica (0000 0000), o qualsiasi flag extra set (00), utilizzando un sistema di fat32 (00).

Fare riferimento alla sezione 2.3/2.3.1: https://tools.ietf.org/html/rfc1952#section-2.3.1

Così sul pitone:

>>> import requests 
>>> url = 'https://commoncrawl.s3.amazonaws.com/crawl-data/CC-MAIN-2016-18/segments/1461860106452.21/warc/CC-MAIN-20160428161506-00006-ip-10-239-7-51.ec2.internal.warc.gz' 
>>> response = requests.get(url, params={"range":"bytes=257173173-257248267"}) 
>>> unknown_compressed_data = response.content 

preavviso qualcosa di simile ?:

>>> unknown_compressed_data[:10] 
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00' 

E al di decompressione facciamo solo provare a caso sulla base del (documentation):

>>> import zlib 

"zlib.error: errore -2 durante la prepa ring per decomprimere i dati: incoerente flusso stato ":

>>> zlib.decompress(unknown_compressed_data, -31) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
zlib.error: Error -2 while preparing to decompress data: inconsistent stream state 

"Errore -3 mentre decompressione dei dati: controllo intestazione non corretto":

>>> zlib.decompress(unknown_compressed_data) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
zlib.error: Error -3 while decompressing data: incorrect header check 

" zlib.error: Errore -3 mentre dati decompressione: distanza valida troppo indietro":

>>> zlib.decompress(unknown_compressed_data, 30) 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
zlib.error: Error -3 while decompressing data: invalid distance too far back 

possibili s oluzione:

>>> zlib.decompress(unknown_compressed_data, 31) 
'WARC/1.0\r\nWARC-Type: response\r\nWARC-Date: 2016-04-28T20:14:16Z\r\nWARC-Record-ID: <urn:uu 
+0

Fantastico. Questo ha funzionato per me. – bibbsey

Problemi correlati