簡體   English   中英

如何使用請求下載圖像

[英]How to download image using requests

我正在嘗試使用 python 的requests模塊從 web 下載並保存圖像。

這是我使用的(工作)代碼:

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中使用響應中的哪些屬性嗎?

您可以使用response.raw文件對象,也可以迭代響應。

默認情況下,使用response.raw文件對象不會解碼壓縮響應(使用 GZIP 或 deflate)。 您可以通過將decode_content屬性設置為Truerequests將其設置為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以便requests不會先將整個圖像下載到內存中。

從請求中獲取一個類文件對象並將其復制到文件中。 這也將避免一次將整個內容讀入內存。

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

怎么樣,一個快速的解決方案。

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)

我對使用請求下載圖像有同樣的需求。 我首先嘗試了 Martijn Pieters 的答案,效果很好。 但是當我對這個簡單的函數做一個配置文件時,我發現與 urllib 和 urllib2 相比,它使用了如此多的函數調用。

然后我嘗試了requests模塊作者推薦方式

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

這可能比使用requests更容易。 這是我唯一一次建議不要使用requests來做 HTTP 的事情。

使用urllib兩個班輪:

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

還有一個很好的 Python 模塊wget ,它非常易於使用。 這里找到。

這證明了設計的簡單性:

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

以下代碼片段下載一個文件。

該文件以其文件名保存在指定的 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)

主要有2種方式:

  1. 使用.content (最簡單/官方)(見Zhenyi Zhang 的回答):

     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 的回答):

     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.

時間兩者都沒有明顯差異。

就像導入圖像和請求一樣簡單

from PIL import Image
import requests

img = Image.open(requests.get(url, stream = True).raw)
img.save('img1.jpg')

這是一個更用戶友好的答案,仍然使用流媒體。

只需定義這些函數並調用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的膽量getImage()是基於答案在這里和膽量getImageFast()是基於答案以上

這就是我做到的

import requests
from PIL import Image
from io import BytesIO

url = 'your_url'
files = {'file': ("C:/Users/shadow/Downloads/black.jpeg", open('C:/Users/shadow/Downloads/black.jpeg', 'rb'),'image/jpg')}
response = requests.post(url, files=files)

img = Image.open(BytesIO(response.content))
img.show()

我將發布一個答案,因為我沒有足夠的代表發表評論,但是使用 Blairg23 發布的 wget,您還可以為路徑提供一個 out 參數。

 wget.download(url, out=path)

這是谷歌搜索關於如何下載帶有請求的二進制文件的第一個響應。 如果您需要下載帶有請求的任意文件,您可以使用:

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)

我的方法是使用 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 項目,它根據關鍵字從 unsplash.com 下載圖像。

你可以這樣做:

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)

同意Blairg23 的觀點,即使用urllib.request.urlretrieve是最簡單的解決方案之一。

我想在這里指出一個注意事項。 有時它不會下載任何東西,因為請求是通過腳本(bot)發送的,如果你想從谷歌圖片或其他搜索引擎解析圖片,你需要先通過user-agent請求headers ,然后下載圖片, 否則請求將被阻塞並拋出錯誤。

通過user-agent並下載圖像:

opener=urllib.request.build_opener()
opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582')]
urllib.request.install_opener(opener)

urllib.request.urlretrieve(URL, 'image_name.jpg')

在線 IDE 中的代碼使用requestsbs4urllib.requests 從 Google 圖片中bs4 和下載圖片


或者,如果您的目標是從 Google、Bing、Yahoo!、DuckDuckGo(和其他搜索引擎)等搜索引擎中抓取圖像,那么您可以使用SerpAPi 這是一個帶有免費計划的付費 API。

最大的區別是不需要弄清楚如何繞過搜索引擎的塊或如何從 HTML 或 JavaScript 中提取某些部分,因為它已經為最終用戶完成了。

要集成的示例代碼:

import os, urllib.request
from serpapi import GoogleSearch

params = {
  "api_key": os.getenv("API_KEY"),
  "engine": "google",
  "q": "pexels cat",
  "tbm": "isch"
}

search = GoogleSearch(params)
results = search.get_dict()

print(json.dumps(results['images_results'], indent=2, ensure_ascii=False))

# download images 
for index, image in enumerate(results['images_results']):

    # print(f'Downloading {index} image...')
    
    opener=urllib.request.build_opener()
    opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582')]
    urllib.request.install_opener(opener)

    # saves original res image to the SerpApi_Images folder and add index to the end of file name
    urllib.request.urlretrieve(image['original'], f'SerpApi_Images/original_size_img_{index}.jpg')

-----------
'''
]
  # other images
  {
    "position": 100, # 100 image
    "thumbnail": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK62dIkDjNCvEgmGU6GGFZcpVWwX-p3FsYSg&usqp=CAU",
    "source": "homewardboundnj.org",
    "title": "pexels-helena-lopes-1931367 - Homeward Bound Pet Adoption Center",
    "link": "https://homewardboundnj.org/upcoming-event/black-cat-appreciation-day/pexels-helena-lopes-1931367/",
    "original": "https://homewardboundnj.org/wp-content/uploads/2020/07/pexels-helena-lopes-1931367.jpg",
    "is_product": false
  }
]
'''

免責聲明,我為 SerpApi 工作。

這是一個非常簡單的代碼

import requests

response = requests.get("https://i.imgur.com/ExdKOOz.png") ## Making a variable to get image.

file = open("sample_image.png", "wb") ## Creates the file for image
file.write(response.content) ## Saves file content
file.close()

下載圖片

import requests
Picture_request = requests.get(url)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM