2012-03-18 10 views
11

He creado una arquitectura cliente/servidor en python, tomo la solicitud HTTP del cliente que se sirve al solicitar otro servidor HTTP a través de mi código.Cómo decodificar los datos comprimidos gzip devueltos en una respuesta HTTP en python?

Cuando obtengo la respuesta del tercer servidor no puedo descifrar los datos comprimidos de gzip, primero dividí los datos de respuesta usando \r\n como carácter de separación que me dio los datos como el último elemento de la lista y luego probé descomprimiéndolo con

zlib.decompress(data[-1]) 

pero me está dando un error de encabezados incorrectos. ¿Cómo debo ir con este problema?

Código

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

quiero leer los datos que se han transferido entre el cliente y el segundo servidor.

+1

¡Muéstranos el código! ¿Estás seguro de que los datos no han sido codificados/decodificados de forma incorrecta (es decir, deberían tratarse como datos binarios)? – Cameron

+0

Podría ser que sus datos se dividan en múltiples fragmentos y que deba analizar el encabezado para obtener la longitud correcta. El encabezado gzipped tiene información de longitud –

+0

¿qué sucede si los datos comprimidos en sí tienen "\ r \ n" en él, y los descompone y decodifica solo una parte en lugar de todos los datos comprimidos? Intentaría encontrar "\ r \ n" en el servidor antes de enviarlo para validar si es el problema. –

Respuesta

1

De acuerdo con https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html, los encabezados y el cuerpo están separados por una línea vacía que contiene solo caracteres CRLF. Usted podría intentar

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

La división se encuentra la línea de vacío y el parámetro adicional limita el número de divisiones - siendo el resultado matriz con dos artículos, los encabezados y cuerpo. Pero es difícil recomendar algo sin saber más acerca de su código y la secuencia real que se divide.

4

Especifique wbits al usar zlib.decompress(string, wbits, bufsize) consulte el final de "solución de problemas", por ejemplo.

Solución de problemas

Vamos a empezar con aa comando curl que descarga una respuesta de rango de bytes con un desconocido "Content-Encoding" (nota: se sabe de antemano que es una especie de cosa comprimido, mabye deflate quizá 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 las siguientes cabeceras de respuesta:

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 

Así que al grano.

Permite visualizar la salida hexagonal de los primeros 10 bytes: salida curl -r 266472196-266472208 $URL | xxd

hexagonal:

0000000: 1f8b 0800 0000 0000 0000 ecbd eb 

podemos ver algunos fundamentos de lo que estamos trabajando con los valores hex.

es decir el equivalente a su probablemente un gzip (1f8b) usando desinflar (0800) sin un tiempo de modificación (0000 0000), o cualquier banderas adicionales establecido (00), utilizando un sistema FAT32 (00).

Consulte la sección 2.3/2.3.1: https://tools.ietf.org/html/rfc1952#section-2.3.1

Así que hacia la pitón:

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

aviso algo similar ?:

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

Y a la descompresión vamos a tratar de forma aleatoria en base a la (documentation):

>>> import zlib 

"zlib.error: Error -2 while prepa anillo para descomprimir datos: estado incoherente corriente ":

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

"Error -3 mientras que la descompresión de datos: comprobación de cabecera incorrecto":

>>> 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: Error -3 mientras descomprimir los datos: distancia inválida demasiado atrás":

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

posibles s Solución:

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

Impresionante. Esto funcionó para mí. – bibbsey

Cuestiones relacionadas