web-dev-qa-db-ja.com

python urllib2はWebページから取得したgzipデータを自動的に解凍しますか?

私は使っています

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

私は知りたいです:

  1. URLのデータがgzip圧縮されているかどうかを確認するにはどうすればよいですか?

  2. Urllib2は、データがgzip圧縮されている場合、自動的に圧縮解除されますか?データは常に文字列ですか?

69
mlzboy
  1. URLのデータがgzip圧縮されているかどうかを確認するにはどうすればよいですか?

これにより、コンテンツがgzip圧縮されているかどうかが確認され、解凍されます。

_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は、データがgzip圧縮されている場合、自動的に圧縮解除されますか?データは常に文字列ですか?

いいえ。'Accept-Encoding 'ヘッダーはurllib2ではなく、次を使用して設定されるため、urllib2は自動的にデータを解凍しません:request.add_header('Accept-Encoding','gzip, deflate')

146
ars

単純な.gzファイルについて話している場合、いいえ、urllib2はそれをデコードせず、変更されていない.gzファイルを出力として取得します。

Content-Encoding: gzipまたはdeflateを使用した自動HTTPレベル圧縮について話している場合は、Accept-Encodingヘッダーを使用して、クライアントから意図的に要求する必要があります。

urllib2はこのヘッダーを設定しないため、返される応答は圧縮されません。圧縮を心配することなく、リソースを安全に取得できます(ただし、圧縮はサポートされていないため、リクエストに時間がかかる場合があります)。

7
bobince

あなたの質問には答えましたが、より包括的な実装については、 Mark Pilgrimの実装 をご覧ください。gzip、deflate、安全なURL解析など、広く使用されているRSSパーサー、それでも便利なリファレンス。

5
RuiDC

Urllib3はこれを自動的に処理するようになりました。

参照ヘッダー:

HTTPHeaderDict({'ETag': '"112d13e-574c64196bcd9-gzip"'、 'Vary': 'Accept-Encoding'、 'C​​ontent-Encoding': 'gzip'、 'X-Frame-Options': 'sameorigin'、 'サーバー ':' Apache '、'最終変更 ':'土、2018年9月1日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 __== '__main__':
    print("Fetching files from eddb.io")
    fetcher = EDDBMultiDataFetcher()
    fetcher.fetch_all()
0
RobotHumans