naritoブログ

このブログはDjangoとBootstrap4で作成されました
ソースコード

Python、requestsを使ったダウンロード

プログラミング関連 Requests shutilモジュール Python 約577日前
2016年3月20日11:37
requestsを使ったファイルダウンロードの方法です。

方法1、shutilのcopyfileobjを使う例です。
内部で16*1024バイトに分けてデータを書き込んでいるので、メモリがパンクするということはありません。
import os
import shutil

import requests


def download(url):
    file_name = os.path.basename(url)
    res = requests.get(url, stream=True)
    if res.status_code == 200:
        with open(file_name, 'wb') as file:
            res.raw.decode_content = True
            shutil.copyfileobj(res.raw, file)


if __name__ == '__main__':
    url = 'https://torina.top/media/316/result.png'
    download(url)


チャンクのサイズを変えたい場合は、オブション引数のlengthを使います。
shutil.copyfileobj(res.raw, file, length=1024)



方法2です。res.iter_contentを使い、データを数回に分けて書き込んでいきます。
こちらもメモリがパンクすることはないでしょう。
import os

import requests


def download(url):
    file_name = os.path.basename(url)
    res = requests.get(url, stream=True)
    if res.status_code == 200:
        with open(file_name, 'wb') as file:
            for chunk in res.iter_content(chunk_size=1024):
                file.write(chunk)


if __name__ == '__main__':
    url = 'https://torina.top/media/316/result.png'
    download(url)



ダウンロードの場合は、stream=Trueとしましょう
こうすることで、大きいファイルが一気に読み込まれることがなくなります
res = requests.get(url, stream=True)


リクエストが成功した場合です
if res.status_code == 200:


ttp://torina.top/image.pngなら、file_nameにはimage.pngが
ttp://torina.top/bgm.mp3なら、file_nameにはbgm.mp3が入ります
file_name = os.path.basename(url)



これは1024バイトにわけて書き込んでいます。
for chunk in res.iter_content(chunk_size=1024):
    file.write(chunk)



ちなみにですが、iter_contentを使わずfor chunk in res:とした場合、128バイトずつになります。
(これは__iter__メソッドで、return self.iter_content(128)としているため)
for chunk in res:
    file.write(chunk)


参考
http://docs.python-requests.org/en/master/
http://stackoverflow.com/questions/16694907/how-to-download-large-file-in-python-with-requests-py
http://stackoverflow.com/questions/13137817/how-to-download-image-using-requests