Как скачать изображение с помощью запросов

Я пытаюсь загрузить и сохранить изображение из Интернета с помощью модуля 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?

Ответ 1

Вы можете либо использовать файл response.raw файл, либо перебрать ответ.

Для использования 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() с пользовательским размером блока:

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 не загружало все изображение в память в первую очередь.

Ответ 2

Получить файл-подобный объект из запроса и скопировать его в файл. Это также позволит не сразу считывать все это в памяти.

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

Ответ 3

Как насчет этого, быстрое решение.

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)

Ответ 4

У меня такая же потребность в загрузке изображений с использованием запросов. Сначала я попробовал ответ 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

Ответ 5

Это может быть проще, чем использование requests. Это единственный раз, когда я предлагаю не использовать requests для работы с HTTP файлами.

Два вкладыша с использованием urllib:

>>> import urllib
>>> urllib.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'

Enjoy.

Изменить: Вы также можете добавить параметр out, чтобы указать путь.

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

Ответ 6

Следующий фрагмент кода загружает файл.

Файл сохраняется с его именем файла, как указано в указанном URL.

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)

Ответ 7

Существует 2 основных способа:

  • Используя .content (простейший/официальный) (см. Ответ Жени Чжана):

    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()
    
  • Используя .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.
    

Сроки оба не показывают заметной разницы.

Ответ 8

Так же просто, как импортировать изображения и запросы

from PIL import Image
import requests

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

Ответ 9

Вот более удобный ответ, который по-прежнему использует потоковое вещание.

Просто определите эти функции и вызовите 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() основаны на ответе выше.

Ответ 10

Я собираюсь опубликовать ответ, так как у меня недостаточно комментариев, чтобы сделать комментарий, но с помощью wget, который был отправлен Blairg23, вы также можете указать параметр out для пути.

 wget.download(url, out=path)

Ответ 11

Когда я пытаюсь запустить приведенный ниже код, изображение становится устаревшим, но его размер всегда ограничен 34 КБ.

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)  

И также, пожалуйста, дайте мне знать, что такое settings.STATICMAP_URL.format(** data), я использую мой usl вместо settings.STATICMAP_URL.format(** data)

Ответ 12

Это первый ответ, который появляется в поиске Google о том, как загрузить двоичный файл с запросами. Если вам нужно скачать произвольный файл с запросами, вы можете использовать:

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

Я использую метод ниже, чтобы загрузить изображения

                    newlink = image.img['src']
                    print('Downloading image', index)
                    try:
                        response = requests.get(newlink, stream=True)
                        sleep(1)
                        with open(image_path, 'wb') as file:
                            sleep(1)
                            shutil.copyfileobj(response.raw, file)
                    except Exception as e:

                        print(e)
                        print('Could not download image number ', index)

Все работает хорошо, но я заметил, что когда я запускаю скрипт каждый день, через несколько дней (5-7), загрузка каждого изображения занимает много времени. Когда это произошло, я закрыл pycharm и перезапустил свой ПК. После этого снова работает хорошо.

Я хотел бы знать, если кто-то знает, почему это произошло.

Спасибо

Ответ 14

Вы можете сделать что-то вроде этого:

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)

Ответ 15

Вот как я это сделал

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