Каков наилучший способ распаковать ответ gzip-сервера в Python 3? - PullRequest
7 голосов
/ 06 апреля 2009

Я ожидал, что это сработает:

>>> import urllib.request as r
>>> import zlib
>>> r.urlopen( r.Request("http://google.com/search?q=foo", headers={"User-Agent": "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11", "Accept-Encoding": "gzip"}) ).read()
b'af0\r\n\x1f\x8b\x08...(long binary string)'
>>> zlib.decompress(_)
Traceback (most recent call last):
  File "<pyshell#87>", line 1, in <module>
    zlib.decompress(x)
zlib.error: Error -3 while decompressing data: incorrect header check

Но это не так. Dive Into Python использует StringIO в этом примере, но этого, похоже, не хватает в Python 3. Как правильно это сделать?

Ответы [ 3 ]

18 голосов
/ 20 декабря 2009

Работает нормально с gzip (gzip и zlib - это одинаковое сжатие, но с разными заголовками / «обёртками». Ваша ошибка содержит эту информацию в сообщении).

import gzip
import urllib.request

request = urllib.request.Request(
    "http://google.com/search?q=foo",
    headers={
        "Accept-Encoding": "gzip",
        "User-Agent": "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11", 
    })
response = urllib.request.urlopen(request)
gzipFile = gzip.GzipFile(fileobj=response)
gzipFile.read()
5 голосов
/ 06 апреля 2009

В Python 3 StringIO - это класс в модуле io.

Так что для примера, на который вы ссылались, если вы измените:

import StringIO
compressedstream = StringIO.StringIO(compresseddata)

до:

import io
compressedstream = io.StringIO(compresseddata)

это должно сработать.

4 голосов
/ 30 января 2016

Для тех, кто использует Python 3.2 или более позднюю версию, существует более простой способ распаковать ответ, чем любой из ответов здесь:

import gzip
import urllib.request

request = urllib.request.Request(
    "http://example.com/",
    headers={"Accept-Encoding": "gzip"})
response = urllib.request.urlopen(request)
result = gzip.decompress(response.read())
...