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