使用 PIL 和请求下载图像 [英] Downloading image with PIL and requests

查看:112
本文介绍了使用 PIL 和请求下载图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 url 下载原始图像(png 格式),即时转换(不保存到光盘)并另存为 jpg.

I am trying to download an original image (png format) by url, convert it on the fly (without saving to disc) and save as jpg.

代码如下:

import os
import io
import requests
from PIL import Image
...
r = requests.get(img_url, stream=True)
if r.status_code == 200:
    i = Image.open(io.BytesIO(r.content))
    i.save(os.path.join(out_dir, 'image.jpg'), quality=85)

它可以工作,但是当我尝试使用 r.iter_content() 监视下载进度(为将来的进度条)时:

It works, but when I try to monitor the download progress (for the future progress bar) with r.iter_content() like this:

r = requests.get(img_url, stream=True)
if r.status_code == 200:
    for chunk in r.iter_content():
        print(len(chunk))
    i = Image.open(io.BytesIO(r.content))
    i.save(os.path.join(out_dir, 'image.jpg'), quality=85)

我收到此错误:

Traceback (most recent call last):
  File "E:/GitHub/geoportal/quicklookScrape/temp.py", line 37, in <module>
    i = Image.open(io.BytesIO(r.content))
  File "C:\Python35\lib\site-packages\requests\models.py", line 736, in content
    'The content for this response was already consumed')
RuntimeError: The content for this response was already consumed

那么是否可以监控下载进度并在获取数据后自行监控?

So is it possible to monitor the download progress and after get the data itself?

推荐答案

使用 r.iter_content() 时,需要将结果缓存在某处.不幸的是,我找不到任何将内容附加到内存中的对象的示例——通常,当文件不能或不应该一次完全加载到内存中时,会使用 iter_content.但是,您可以使用 tempfile.SpooledTemporaryFile 缓冲它,如本答案中所述:https://stackoverflow.com/a/18550652/4527093.这将阻止将图像保存到磁盘(除非图像大于指定的 max_size).然后,您可以从 tempfile 创建 Image.

When using r.iter_content(), you need to buffer the results somewhere. Unfortunately, I can't find any examples where the contents get appended to an object in memory--usually, iter_content is used when a file can't or shouldn't be loaded entirely in memory at once. However, you buffer it using a tempfile.SpooledTemporaryFile as described in this answer: https://stackoverflow.com/a/18550652/4527093. This will prevent saving the image to disk (unless the image is larger than the specified max_size). Then, you can create the Image from the tempfile.

import os
import io
import requests
from PIL import Image
import tempfile

buffer = tempfile.SpooledTemporaryFile(max_size=1e9)
r = requests.get(img_url, stream=True)
if r.status_code == 200:
    downloaded = 0
    filesize = int(r.headers['content-length'])
    for chunk in r.iter_content(chunk_size=1024):
        downloaded += len(chunk)
        buffer.write(chunk)
        print(downloaded/filesize)
    buffer.seek(0)
    i = Image.open(io.BytesIO(buffer.read()))
    i.save(os.path.join(out_dir, 'image.jpg'), quality=85)
buffer.close()

编辑为包含 chunk_size,这将限制更新为每 1kb 而不是每字节发生一次.

Edited to include chunk_size, which will limit the updates to occurring every 1kb instead of every byte.

这篇关于使用 PIL 和请求下载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆