如何使用请求下载图像

时间:2012-10-30 11:14:26

标签: python urllib2 python-requests

我正在尝试使用python的requests模块从网上下载并保存图像。

这是我使用的(工作)代码:

img = urllib2.urlopen(settings.STATICMAP_URL.format(**data))
with open(path, 'w') as f:
    f.write(img.read())

以下是使用requests的新(非工作)代码:

r = requests.get(settings.STATICMAP_URL.format(**data))
if r.status_code == 200:
    img = r.raw.read()
    with open(path, 'w') as f:
        f.write(img)

您能否帮助我了解使用requests的响应中的哪个属性?

15 个答案:

答案 0 :(得分:447)

您可以使用response.raw file object,也可以迭代响应。

默认情况下,使用response.raw类文件对象不会解码压缩响应(使用GZIP或deflate)。您可以通过将decode_content属性设置为True来强制它为您解压缩(requests将其设置为False以控制解码本身)。然后,您可以使用shutil.copyfileobj()让Python将数据流传输到文件对象:

import requests
import shutil

r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
    with open(path, 'wb') as f:
        r.raw.decode_content = True
        shutil.copyfileobj(r.raw, f)        

要迭代响应,请使用循环;像这样迭代可确保数据在此阶段解压缩:

r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
    with open(path, 'wb') as f:
        for chunk in r:
            f.write(chunk)

这将以128字节块的形式读取数据;如果您觉得另一个块大小效果更好,请使用带有自定义块大小的Response.iter_content() method

r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
    with open(path, 'wb') as f:
        for chunk in r.iter_content(1024):
            f.write(chunk)

请注意,您需要以二进制模式打开目标文件,以确保python不会尝试为您翻译换行符。我们还设置了stream=True,以便requests不会先将整个图像下载到内存中。

答案 1 :(得分:194)

从请求中获取类似文件的对象并将其复制到文件中。这也可以避免一次将整个内容读入内存。

import shutil

import requests

url = 'http://example.com/img.png'
response = requests.get(url, stream=True)
with open('img.png', 'wb') as out_file:
    shutil.copyfileobj(response.raw, out_file)
del response

答案 2 :(得分:137)

这是一个快速解决方案。

import requests

url = "http://craphound.com/images/1006884_2adf8fc7.jpg"
response = requests.get(url)
if response.status_code == 200:
    with open("/Users/apple/Desktop/sample.jpg", 'wb') as f:
        f.write(response.content)

答案 3 :(得分:68)

我同样需要使用请求下载图像。我首先尝试了Martijn Pieters的答案,但效果很好。但是当我在这个简单的函数上做了一个配置文件时,我发现它与urllib和urllib2相比使用了很多函数调用。

然后我尝试了请求模块的作者way recommended

import requests
from PIL import Image
from StringIO import StringIO

r = requests.get('https://example.com/image.jpg')
i = Image.open(StringIO(r.content))

这大大减少了函数调用的次数,从而加快了我的应用程序。 这是我的探查器的代码和结果。

#!/usr/bin/python
import requests
from StringIO import StringIO
from PIL import Image
import profile

def testRequest():
    image_name = 'test1.jpg'
    url = 'http://example.com/image.jpg'

    r = requests.get(url, stream=True)
    with open(image_name, 'wb') as f:
        for chunk in r.iter_content():
            f.write(chunk)

def testRequest2():
    image_name = 'test2.jpg'
    url = 'http://example.com/image.jpg'

    r = requests.get(url)

    i = Image.open(StringIO(r.content))
    i.save(image_name)

if __name__ == '__main__':
    profile.run('testUrllib()')
    profile.run('testUrllib2()')
    profile.run('testRequest()')

testRequest的结果:

343080 function calls (343068 primitive calls) in 2.580 seconds

testRequest2的结果:

3129 function calls (3105 primitive calls) in 0.024 seconds

答案 4 :(得分:39)

这可能比使用requests更容易。这是我唯一一次建议不使用requests来执行HTTP操作。

使用urllib的两个班轮:

>>> import urllib
>>> urllib.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

还有一个很好用的Python模块wget。找到here

这证明了设计的简单性:

>>> import wget
>>> url = 'http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'
>>> filename = wget.download(url)
100% [................................................] 3841532 / 3841532>
>> filename
'razorback.mp3'

享受。

修改:您还可以添加out参数来指定路径。

>>> out_filepath = <output_filepath>    
>>> filename = wget.download(url, out=out_filepath)

答案 5 :(得分:20)

以下代码段下载文件。

保存文件的文件名与指定的网址一样。

import requests

url = "http://beispiel.dort/ichbineinbild.jpg"
filename = url.split("/")[-1]
r = requests.get(url, timeout=0.5)

if r.status_code == 200:
    with open(filename, 'wb') as f:
        f.write(r.content)

答案 6 :(得分:13)

主要有两种方式:

  1. 使用.content(最简单/官方)(请参阅Zhenyi Zhang's answer):

    import io  # Note: io.BytesIO is StringIO.StringIO on Python2.
    import requests
    
    r = requests.get('http://lorempixel.com/400/200')
    r.raise_for_status()
    with io.BytesIO(r.content) as f:
        with Image.open(f) as img:
            img.show()
    
  2. 使用.raw(请参阅Martijn Pieters's answer):

    import requests
    
    r = requests.get('http://lorempixel.com/400/200', stream=True)
    r.raise_for_status()
    r.raw.decode_content = True  # Required to decompress gzip/deflate compressed responses.
    with PIL.Image.open(r.raw) as img:
        img.show()
    r.close()  # Safety when stream=True ensure the connection is released.
    
  3. 时间两者都没有显示出明显的差异。

答案 7 :(得分:9)

就像导入图像和请求一样简单

$('.btn').click(function() {

  //remove the selected attr from all btns
  $('.btn[title]').removeAttr('title');

  //add the title attr to the current btn
    $(this).attr('title', 'selected');

});

答案 8 :(得分:4)

这是一个更加用户友好的答案,仍然使用流媒体。

只需定义这些功能并调用getImage()即可。它将使用与url相同的文件名并默认写入当前目录,但两者都可以更改。

import requests
from StringIO import StringIO
from PIL import Image

def createFilename(url, name, folder):
    dotSplit = url.split('.')
    if name == None:
        # use the same as the url
        slashSplit = dotSplit[-2].split('/')
        name = slashSplit[-1]
    ext = dotSplit[-1]
    file = '{}{}.{}'.format(folder, name, ext)
    return file

def getImage(url, name=None, folder='./'):
    file = createFilename(url, name, folder)
    with open(file, 'wb') as f:
        r = requests.get(url, stream=True)
        for block in r.iter_content(1024):
            if not block:
                break
            f.write(block)

def getImageFast(url, name=None, folder='./'):
    file = createFilename(url, name, folder)
    r = requests.get(url)
    i = Image.open(StringIO(r.content))
    i.save(file)

if __name__ == '__main__':
    # Uses Less Memory
    getImage('http://www.example.com/image.jpg')
    # Faster
    getImageFast('http://www.example.com/image.jpg')

request的{​​{1}}胆量基于答案heregetImage()的胆量基于答案above

答案 9 :(得分:2)

我将发布一个答案,因为我没有足够的代表发表评论,但是如Blairg23发布的wget,您还可以为路径提供输出参数。

 wget.download(url, out=path)

答案 10 :(得分:2)

这就是我的做法

module_name = 'my_package'

答案 11 :(得分:2)

我的方法是使用response.content(blob)并以二进制模式保存到文件中

img_blob = requests.get(url, timeout=5).content
     with open(destination + '/' + title, 'wb') as img_file:
         img_file.write(img_blob)

查看我的python project,它根据关键字从unsplash.com下载图像。

答案 12 :(得分:1)

这是谷歌搜索有关如何下载带有请求的二进制文件的第一个响应。如果您需要下载包含请求的任意文件,可以使用:

import requests
url = 'https://s3.amazonaws.com/lab-data-collections/GoogleNews-vectors-negative300.bin.gz'
open('GoogleNews-vectors-negative300.bin.gz', 'wb').write(requests.get(url, allow_redirects=True).content)

答案 13 :(得分:-1)

您可以执行以下操作:

import requests
import random

url = "https://images.pexels.com/photos/1308881/pexels-photo-1308881.jpeg? auto=compress&cs=tinysrgb&dpr=1&w=500"
name=random.randrange(1,1000)
filename=str(name)+".jpg"
response = requests.get(url)
if response.status_code.ok:
   with open(filename,'w') as f:
    f.write(response.content)

答案 14 :(得分:-1)

下载图片

import requests
Picture_request = requests.get(url)