如何使用請求下載圖像

本文翻譯自:How to download image using requests

I'm trying to download and save an image from the web using python's requests module. 我正在嘗試使用python的requests模塊從網絡下載並保存圖像。

Here is the (working) code I used: 這是我使用的(工作)代碼:

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

Here is the new (non-working) code using requests : 這是使用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)

Can you help me on what attribute from the response to use from requests ? 您可以幫助我瞭解響應中的哪些屬性以供requests使用嗎?


#1樓

參考:https://stackoom.com/question/t7kH/如何使用請求下載圖像


#2樓

You can either use the response.raw file object , or iterate over the response. 您可以使用response.raw文件對象 ,也可以遍歷響應。

To use the response.raw file-like object will not, by default, decode compressed responses (with GZIP or deflate). 默認情況下,要使用類似response.raw文件的對象,不會解碼壓縮的響應(使用GZIP或deflate)。 You can force it to decompress for you anyway by setting the decode_content attribute to True ( requests sets it to False to control decoding itself). 您可以通過將decode_content屬性設置爲True來強制爲您解壓縮( requests將其設置爲False以控制解碼本身)。 You can then use shutil.copyfileobj() to have Python stream the data to a file object: 然後,您可以使用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)        

To iterate over the response use a loop; 要遍歷響應,請使用循環; iterating like this ensures that data is decompressed by this stage: 這樣迭代可確保在此階段對數據進行解壓縮:

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)

This'll read the data in 128 byte chunks; 這將以128字節的塊讀取數據; if you feel another chunk size works better, use the Response.iter_content() method with a custom chunk size: 如果您覺得其他塊大小更好,請使用帶有自定義塊大小的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)

Note that you need to open the destination file in binary mode to ensure python doesn't try and translate newlines for you. 請注意,您需要以二進制模式打開目標文件,以確保python不會嘗試爲您翻譯換行符。 We also set stream=True so that requests doesn't download the whole image into memory first. 我們還設置stream=True以便requests不會首先將整個圖像下載到內存中。


#3樓

Get a file-like object from the request and copy it to a file. 從請求中獲取類似文件的對象,然後將其複製到文件中。 This will also avoid reading the whole thing into memory at once. 這也將避免將整個事情立即讀入內存。

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

#4樓

I have the same need for downloading images using requests. 我同樣需要使用請求下載圖像。 I first tried the answer of Martijn Pieters, and it works well. 我首先嚐試了Martijn Pieters的答案,並且效果很好。 But when I did a profile on this simple function, I found that it uses so many function calls compared to urllib and urllib2. 但是,當我對這個簡單的函數進行概要分析時,我發現與urllib和urllib2相比,它使用了許多函數調用。

I then tried the way recommended by the author of requests module: 然後,我嘗試了請求模塊的作者推薦方式

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

This much more reduced the number of function calls, thus speeded up my application. 這大大減少了函數調用的次數,從而加快了我的應用程序的速度。 Here is the code of my profiler and the result. 這是我的探查器的代碼和結果。

#!/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()')

The result for testRequest: testRequest的結果:

343080 function calls (343068 primitive calls) in 2.580 seconds

And the result for testRequest2: 以及testRequest2的結果:

3129 function calls (3105 primitive calls) in 0.024 seconds

#5樓

How about this, a quick solution. 怎麼樣,一個快速的解決方案。

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)

#6樓

Here is a more user-friendly answer that still uses streaming. 這是一個更加用戶友好的答案,仍然使用流式傳輸。

Just define these functions and call getImage() . 只需定義這些函數並調用getImage() It will use the same file name as the url and write to the current directory by default, but both can be changed. 默認情況下,它將使用與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')

The request guts of getImage() are based on the answer here and the guts of getImageFast() are based on the answer above . getImage()request基於此處的答案getImageFast()的內容基於以上答案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章