Как загрузить изображение с помощью запросов
Я пытаюсь загрузить и сохранить изображение из интернета с помощью python's 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?
11 ответов:
вы можете использовать
response.rawfile object, или повторите ответ.использовать
response.rawфайлоподобный объект по умолчанию не будет декодировать сжатые ответы (с помощью GZIP или deflate). Вы можете заставить его распаковать для вас в любом случае, установив до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не загружает все изображение в память в первую очередь.
получите файл-как объект из запроса и скопировать его в файл. Это также позволит избежать чтения всего этого в память сразу.
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.
Я тогда попробовал способ рекомендуется автор модуля запросов:
import requests from PIL import Image from StringIO 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.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'наслаждайтесь.
Edit: вы также можете добавить
outпараметр to укажите путь.>>> out_filepath = <output_filepath> >>> filename = wget.download(url, out=out_filepath)
следующий фрагмент кода загружает файл.
файл сохраняется с именем файла, как указано в указанном 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)
есть 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(см. Мартин Питерс-х):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.время оба не показывает заметной разницы.
вот более удобный ответ, который по-прежнему использует потоковое.
просто определите эти функции и вызовите
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')The
requestкишкиgetImage()основаны на ответ здесь и внутренностяхgetImageFast()основаны на ответ выше.
Я собираюсь опубликовать ответ, поскольку у меня недостаточно репутации, чтобы сделать комментарий, но с wget, опубликованным Blairg23, вы также можете предоставить параметр out для пути.
wget.download(url, out=path)
когда я пытаюсь запустить приведенный ниже код, изображение становится downaloded, но размер всегда ограничивается 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)и также, пожалуйста, дайте мне знать, что это настройки.STATICMAP_URL.формат (**данные), я использую свой usl вместо настроек.STATICMAP_URL.формат (**данные)
так же просто, как импортировать изображения и запросы
from PIL import Image import requests img = Image.open(requests.get(url, stream = True).raw) img.save('img1.jpg')
Comments