Что не так с этим форматом GZIP? - PullRequest
3 голосов
/ 06 сентября 2010

Я использую следующий код Python для загрузки веб-страниц с серверов со сжатием gzip:

url = "http://www.v-gn.de/wbb/"
import urllib2
request = urllib2.Request(url)
request.add_header('Accept-encoding', 'gzip')
response = urllib2.urlopen(request)
content = response.read()
response.close()

import gzip
from StringIO import StringIO
html = gzip.GzipFile(fileobj=StringIO(content)).read()

Обычно это работает, но для указанного URL происходит сбой с исключением struct.error.Я получаю аналогичный результат, если я использую wget с заголовком «Accept-encoding».Однако браузеры, похоже, могут распаковать ответ.

Поэтому мой вопрос: есть ли способ заставить мой код Python распаковать HTTP-ответ, не прибегая к отключению сжатия, удалив "Accept-encoding"header?

Для полноты вот строка, которую я использую для wget:

wget --user-agent="Mozilla" --header="Accept-Encoding: gzip,deflate" http://www.v-gn.de/wbb/

Ответы [ 3 ]

4 голосов
/ 06 сентября 2010

Похоже, вы можете вызвать readline() для объекта gzip.GzipFile, но read() повышает struct.error, потому что файл внезапно заканчивается.

Поскольку readline работает (кроме самого конца), вы можете сделать что-то вроде этого:

import urllib2
import StringIO
import gzip
import struct

url = "http://www.v-gn.de/wbb/"
request = urllib2.Request(url)
request.add_header('Accept-encoding', 'gzip')
response = urllib2.urlopen(request)
content = response.read()
response.close()
fh=StringIO.StringIO(content)
html = gzip.GzipFile(fileobj=StringIO.StringIO(content))
try:
    for line in html:
        line=line.rstrip()
        print(line)
except struct.error:
    pass
3 голосов
/ 14 июля 2011

Создайте свой обработчик, наследуя от urllib2.HTTPHandler и переопределяя http_open ().

import gzip
from StringIO import StringIO
import httplib, urllib, urllib2
class GzipHandler(urllib2.HTTPHandler):
    def http_open(self, req):
        req.add_header('Accept-encoding', 'gzip')
        r = self.do_open(httplib.HTTPConnection, req)
        if (
            'Content-Encoding'in r.headers and
            r.headers['Content-Encoding'] == 'gzip'
        ):
            fp = gzip.GzipFile(fileobj=StringIO(r.read()))
        else:
            fp = r
        response = urllib.addinfourl(fp, r.headers, r.url, r.code)
        response.msg = r.msg
        return respsone

затем собери свой нож.

def retrieve(url):
    request = urllib2.Request(url)
    opener = urllib2.build_opener(GzipHandler)
    return opener.open(request)

Различия в том, что этот метод проверяет, возвращает ли сервер ответ gzip и выполняется ли он во время запроса, а не после.

Для получения дополнительной информации см .:

3 голосов
/ 06 сентября 2010

Я выполнил указанную вами команду.Он загрузил данные в формате gzip в index.html.Я переименовал index.html в index.html.gz.Я попытался gzip -d inedx.html.gz, что привело к ошибке: gzip: index.html.gz: unexpected end of file.

Вторая попытка была zcat index.html.gz, которая сработала нормально, за исключением того, что после тега </html> выводилась та же ошибкавыше.

$ zcat index.html.gz
...
  </td>
 </tr>
</table>


</body>
</html>
gzip: index.html.gz: unexpected end of file

Сервер неисправен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...