web-dev-qa-db-fra.com

En Python, comment décoder l'encodage GZIP?

J'ai téléchargé une page Web dans mon script python. Dans la plupart des cas, cela fonctionne bien.

Cependant, celui-ci avait un en-tête de réponse: encodage GZIP, et quand j'ai essayé d'imprimer le code source de cette page Web, il y avait tous les symboles dans mon PuTTY.

Comment décoder cela en texte normal?

39
TIMEX

J'utilise zlib pour décompresser le contenu gzippé du Web.

import zlib

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

Décompressez votre flux d'octets à l'aide du module gzip intégré.

Si vous avez des problèmes, affichez le code minimal exact que vous avez utilisé, le message d'erreur exact et traceback, ainsi que le résultat de print repr(your_byte_stream[:100])

Plus d'informations

1. Pour une explication de la confusion gzip/zlib/dégonflage, lisez la section "Autres utilisations" de cet article Wikipedia .

2. Il peut être plus facile d'utiliser le module zlib que le module gzip si vous avez une chaîne plutôt qu'un fichier. Malheureusement, les documents Python sont incomplets/erronés:

"" "zlib.decompress (string [ wbits [ bufsize]]) ... La valeur absolue de wbits est le logarithme de base deux de la taille du tampon d'historique (la" taille de fenêtre ") utilisé lors de la compression des données. la valeur absolue doit être comprise entre 8 et 15 pour les versions les plus récentes de la bibliothèque zlib, des valeurs plus grandes entraînant une meilleure compression au détriment d'une plus grande utilisation de la mémoire. La valeur par défaut est 15. Lorsque wbits est négatif, l'en-tête gzip standard est supprimé; il s'agit d'une fonctionnalité non documentée de la bibliothèque zlib, utilisée pour la compatibilité avec le format de fichier de compression de décompression. "" "

Tout d'abord, 8 <= log2_window_size <= 15, avec la signification donnée ci-dessus. Ensuite, ce qui devrait être un argument séparé est placé en haut:

arg == log2_window_size signifie que la chaîne est au format zlib (RFC 1950; ce que le HTTP 1.1 RFC 2616 appelle confusément "dégonfler").

arg == -log2_window_size signifie que la chaîne est au format dégonflé (RFC 1951; ce que les gens qui n'ont pas lu le RFC HTTP 1.1 ont soigneusement mis en œuvre)

arg == 16 + log_2_window_size signifie que la chaîne est au format gzip (RFC 1952). Vous pouvez donc utiliser 31.

Les informations ci-dessus sont documentées dans le manuel de la bibliothèque zlib C ... Ctrl-F recherche de windowBits.

30
John Machin

J'utilise quelque chose comme ça:

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
11
Michał Niklas

Pour Python 3

Essayez ceci:

import gzip

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

Similaire à la réponse de Shatu pour python3, mais arrangé un peu différemment:

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

Cette méthode permet d'encapsuler gzip.decompress () dans un essai/sauf pour capturer et transmettre l'OSError qui entraîne des situations où vous pouvez obtenir des données mixtes compressées et non compressées. Certaines petites chaînes deviennent en fait plus grosses si elles sont encodées, donc les données simples sont envoyées à la place.

2
whitebeard

Si vous utilisez le module Requests, alors vous n'avez pas besoin d'utiliser d'autres modules car les gzip et deflate transfer-encodings sont automatiquement décodés pour vous.

Exemple:

>>> import requests
>>> custom_header = {'Accept-Encoding': 'gzip'}
>>> response = requests.get('https://api.github.com/events', headers=custom_header)
>>> response.headers
{'Content-Encoding': 'gzip',...}
>>> response.text
'[{"id":"9134429130","type":"IssuesEvent","actor":{"id":3287933,...

Le .text La propriété du réponse sert à lire le contenu dans le contexte texte.

Le .content La propriété de la réponse sert à lire le contenu dans le contexte binaire.

Voir la section Binary Response Content sur docs.python-requests.org

1
simhumileco