Python urllib2 автоматически распаковывает данные gzip, полученные с веб-страницы? - PullRequest
69 голосов
/ 16 октября 2010

Я использую

 data=urllib2.urlopen(url).read()

Я хочу знать:

  1. Как узнать, что данные по URL-адресу сжаты?

  2. Разве urllib2 автоматически распаковывает данные, если они сжаты? Будут ли данные всегда строкой?

Ответы [ 4 ]

146 голосов
/ 16 октября 2010
  1. Как определить, что данные по URL-адресу сжаты в архиве?

Это проверяет, является ли содержимое сжатым и распаковывает его:

from StringIO import StringIO
import gzip

request = urllib2.Request('http://example.com/')
request.add_header('Accept-encoding', 'gzip')
response = urllib2.urlopen(request)
if response.info().get('Content-Encoding') == 'gzip':
    buf = StringIO(response.read())
    f = gzip.GzipFile(fileobj=buf)
    data = f.read()
Будет ли urllib2 автоматически распаковывать данные, если они распакованы?Будут ли данные всегда представлять собой строку?

Нет.Urllib2 не распаковывает данные автоматически, поскольку заголовок «Accept-Encoding» задается не urllib2, а с помощью: request.add_header('Accept-Encoding','gzip, deflate')

7 голосов
/ 16 октября 2010

Если вы говорите о простом .gz файле, нет, urllib2 не будет его декодировать, вы получите неизменный .gz файл в качестве вывода.

Если вы говорите об автоматическом уровне HTTPсжатие с использованием Content-Encoding: gzip или deflate, тогда клиент должен сознательно запрашивать его с помощью заголовка Accept-Encoding.

urllib2 не устанавливает этот заголовок, поэтому ответ, который он получает, не будетсжат.Вы можете безопасно извлечь ресурс, не беспокоясь о сжатии (хотя сжатие не поддерживается, запрос может занять больше времени).

5 голосов
/ 10 августа 2011

На ваш вопрос ответили, но для более полной реализации взгляните на Марк Пилигрим реализовал эту , она охватывает gzip, deflate, безопасный анализ URL и многое, многое другое, для широкого применения.используемый RSS-парсер, но тем не менее полезная ссылка.

0 голосов
/ 01 сентября 2018

Похоже, что urllib3 теперь обрабатывает это автоматически.

Ссылочные заголовки:

HTTPHeaderDict ({'ETag': '"112d13e-574c64196bcd9-gzip"', 'Vary': 'Accept-Encoding', 'Content-Encoding': 'gzip', 'X-Frame-Options': 'sameorigin', 'Server': 'Apache', 'Last-Modified': 'Sat, 01 Sep 2018 02:42:16 GMT', 'X-Content-Параметры типа ':' nosniff ',' X-XSS-Protection ':' 1; mode = block ',' Content-Type ':' text / plain; charset = utf-8 ',' Strict-Transport-Security ': 'max-age = 315360000; includeSubDomains', 'X-UA-совместимый': 'IE = edge', 'Date': 'Sat, 01 Sep 2018 14:20:16 GMT', 'Accept-Ranges': 'bytes ',' Transfer-Encoding ':' chunked '})

Код ссылки:

import gzip
import io
import urllib3

class EDDBMultiDataFetcher():
    def __init__(self):
        self.files_dict = {
            'Populated Systems':'http://eddb.io/archive/v5/systems_populated.jsonl',
            'Stations':'http://eddb.io/archive/v5/stations.jsonl',
            'Minor factions':'http://eddb.io/archive/v5/factions.jsonl',
            'Commodities':'http://eddb.io/archive/v5/commodities.json'
            }
        self.http = urllib3.PoolManager()
    def fetch_all(self):
        for item, url in self.files_dict.items():
            self.fetch(item, url)

    def fetch(self, item, url, save_file = None):
        print("Fetching: " + item)
        request = self.http.request(
            'GET',
            url,
            headers={
                'Accept-encoding': 'gzip, deflate, sdch'
                })
        data = request.data.decode('utf-8')
        print("Fetch complete")
        print(data)
        print(request.headers)
        quit()


if __name__ == '__main__':
    print("Fetching files from eddb.io")
    fetcher = EDDBMultiDataFetcher()
    fetcher.fetch_all()
...