我试图使用python的请求模块从网络下载并保存一张图像。

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

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

下面是使用请求的新(无效)代码:

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)

你能帮我从请求中使用响应的什么属性吗?


当前回答

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

然后我尝试了请求模块作者推荐的方法:

import requests
from PIL import Image
# python2.x, use this instead  
# from StringIO import StringIO
# for python3.x,
from io 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

其他回答

这可能比使用请求更容易。这是我唯一一次建议不要使用请求来做HTTP的事情。

使用urllib的两个内衬:

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

还有一个叫做wget的Python模块,它非常容易使用。在这里找到。

这说明了设计的简单性:

>>> 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)

你可以使用响应。原始文件对象,或遍历响应。

使用响应。默认情况下,raw类文件对象不会解码压缩后的响应(使用GZIP或deflate)。您可以通过将decode_content属性设置为True(请求将其设置为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()方法自定义块大小:

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,这样请求就不会先把整个图像下载到内存中。

下载图像

import requests
Picture_request = requests.get(url)

我的方法是使用回应。内容(blob)并以二进制模式保存到文件中

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

看看我的python项目,根据关键字从unsplash.com下载图像。

下面的代码片段下载一个文件。

该文件以其文件名保存为指定的url。

import requests

url = "http://example.com/image.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)