Pythonでダウンロードした画像が壊れているのはgzipのせいかも

はじめに

Pythonでスクレイピングをして、画像ダウンロードのテストをしていました。
その中で、特定のサイトからダウンロードしてきた画像だけが全て壊れてしまう現象が発生していました。

 

長い間放置していたのですが、UdemyでAWSの教材をみている時にふと天啓が降ってきました。

画像が壊れてしまう原因は、gzipじゃないだろうか?

 

gzipとは

HTTP 1.1にはデータを圧縮し転送量を減らす機能があるが、gzipはその際の圧縮フォーマットの一つとしても使われている。

出典 - WIKI
https://ja.wikipedia.org/wiki/Gzip

サーバーからクライアントへHTMLやCSSなどの生データを送るより、圧縮した方が早く届きます(容量が少ないので。
その為の圧縮形式の一つがgzipです。

 

Choromeなどのデベロッパーツールを使って、ネットワークを見てもらうと確認することができます。

例えばYahooなどもgzipでHTMLデータを送信しています。

 

最近だとどこのサーバーでも使われているのではないでしょうか?

ところで、このgzipですが画像などには効果が薄いので、使う機会はほとんど無いと思います。
そもそもJPEGなどは予め圧縮されてますしねー。

 

gzipでダウンロード画像が壊れる

さて上で説明した通り、画像にgzipをかけるのは効果が薄いです。

しかし、知ってか知らずか該当のサイトは、画像をgzipかけてました。

 

あちゃー(ノ▽`;)

確かに予兆はあったんですよね。
ブラウザで直接ダウンロードしてくるのと容量に差があったんですよね。

おそらくPythonでダウンロードしてくると、gzipのファイルをダウンロードしていたんでしょうね。
拡張子が.jpgや.pngなので壊れてた扱いなのかなと。

 

対応

ぐだぐだと話をしてきましたが、対応方法になります。

shutil.copyfileobj  の前に res.raw.decode_content = True を設定しましょう。
これで解凍した画像を保存することができます。

path = r'/Users/admin/Public/project/MyImages/image'
all_images = [
    'https://i1.wp.com/s1.wp.com/wp-content/themes/h4/landing/marketing/pages/hp-jan-2020-v2/media/desktop/desktop-website-v2-2x.jpg?ssl=1',
    'https://i1.wp.com/s1.wp.com/wp-content/themes/h4/landing/marketing/pages/hp-jan-2020-v2/media/desktop/theme-coutoire-2x.jpg?ssl=1',
]

try:
    for index, image in enumerate(all_images):
        filename = "image_" + str(index) + ".jpg"
        local_path = os.path.join(path, filename)
        res = requests.get(image, stream=True)
        with open(local_path, "wb") as file:
            res.raw.decode_content = True
            shutil.copyfileobj(res.raw, file)
except Exception as e:
    print(e)
    print(str(index) + "番目の画像ダウンロードに失敗しました")
    print("画像のURL" + image)

 

 

さいごに

ぐだぐだと偉そうに記事を書きましたが、かなり薄い知識で記事にしています。
gzipの他にbrotliの場合もあるので、デベロッパーツールで都度確認してもらえたら良いと思います。

検討外れなところや、改善出来そうなところがあったら教えてください。

今日はこの辺でー

 

  • この記事を書いた人

カバノキ

印刷会社のWEB部隊に所属してます。 WEB制作に携わってから、もう時期10年になります。 普段の業務では、PHPをメインにサーバーサイドの言語を扱っています。 最近のお気に入りはJavascriptです。 Vue.jsを狂喜乱舞しながら、社内に布教中です。

-Python
-,