Python urllib2 автоматически распаковывает данные gzip, полученные с веб-страницы?

Я использую

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

Я хочу знать:

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

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

4 ответа

Решение
  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()
  1. Разве urllib2 автоматически распаковывает данные, если они сжаты? Будут ли данные всегда строкой?

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

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

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

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

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

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

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

HTTPHeaderDict ({'ETag': '"112d13e-574c64196bcd9-gzip"', 'Vary': 'Accept-Encoding', 'Content-Encoding': 'gzip', 'X-Frame-Options': 'sameorigin', ' Сервер ': 'Apache', 'Last-Modified': 'Sat, 01 Sep 2018 02:42:16 GMT', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Content-Type': 'text/plain; charset=utf-8', 'Strict-Transport-Security': 'max-age=315360000; includeSubDomains', 'X-UA-Compatible': '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()
Другие вопросы по тегам