目次
はじめに
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の場合もあるので、デベロッパーツールで都度確認してもらえたら良いと思います。
検討外れなところや、改善出来そうなところがあったら教えてください。
今日はこの辺でー