Cómo descargar imágenes usando solicitudes
Estoy intentando descargar y guardar una imagen de la web usando el módulo requests
de python.
Aquí está el código (de trabajo) que usé:
img = urllib2.urlopen(settings.STATICMAP_URL.format(**data))
with open(path, 'w') as f:
f.write(img.read())
Aquí está el nuevo código (que no funciona) usando 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)
¿Puedes ayudarme en qué atributo de la respuesta usar de requests
?
11 answers
Puede utilizar el response.raw
file object , o iterar sobre la respuesta.
Usar el objeto similar a un archivo response.raw
no decodificará, por defecto, las respuestas comprimidas (con GZIP o deflate). Puede forzar que se descomprima por usted de todos modos estableciendo el atributo decode_content
a True
(requests
lo establece en False
para controlar la decodificación por sí mismo). A continuación, puede utilizar shutil.copyfileobj()
para que Python transmita los datos a un objeto file:
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)
Para iterar sobre la respuesta use un bucle; iterar de esta manera asegura que los datos se descompriman en esta etapa:
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)
Esto leerá los datos en fragmentos de 128 bytes; si siente que otro tamaño de fragmento funciona mejor, use el Response.iter_content()
método con un tamaño de fragmento personalizado:
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)
Tenga en cuenta que debe abrir el archivo de destino en modo binario para asegurarse de que python no intente traducir nuevas líneas por usted. También configuramos stream=True
para que requests
no descargue la imagen completa en memoria primero.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-25 10:38:34
Obtenga un objeto similar a un archivo de la solicitud y cópielo en un archivo. Esto también evitará leer todo en la memoria a la vez.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-13 21:24:48
Qué tal esto, una solución rápida.
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-11 01:25:41
Tengo la misma necesidad de descargar imágenes usando peticiones. Primero probé la respuesta de Martijn Pieters, y funciona bien. Pero cuando hice un perfil en esta función simple, encontré que utiliza tantas llamadas de función en comparación con urllib y urllib2.
Luego probé la forma recomendada por el autor del módulo de solicitudes:
import requests
from PIL import Image
from StringIO import StringIO
r = requests.get('https://example.com/image.jpg')
i = Image.open(StringIO(r.content))
Esto redujo mucho más el número de llamadas a funciones, por lo tanto aceleró mi aplicación. Aquí está el código de mi perfilador y el resultado.
#!/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()')
El resultado de testRequest:
343080 function calls (343068 primitive calls) in 2.580 seconds
Y el resultado de testRequest2:
3129 function calls (3105 primitive calls) in 0.024 seconds
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-07 15:52:16
Esto podría ser más fácil que usar requests
. Esta es la única vez que sugeriré no usar requests
para hacer cosas HTTP.
Dos líneas usando urllib
:
>>> import urllib
>>> urllib.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
También hay un bonito módulo de Python llamado wget
que es bastante fácil de usar. Se encuentra aquí.
Esto demuestra la simplicidad del diseño:
>>> import wget
>>> url = 'http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'
>>> filename = wget.download(url)
100% [................................................] 3841532 / 3841532>
>> filename
'razorback.mp3'
Disfruta.
Edit: También puede agregar un parámetro out
para especificar una ruta de acceso.
>>> out_filepath = <output_filepath>
>>> filename = wget.download(url, out=out_filepath)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-15 05:41:36
El siguiente fragmento de código descarga un archivo.
El archivo se guarda con su nombre de archivo como en la url especificada.
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-07 19:42:01
Hay 2 maneras principales:
-
Usando
.content
(más simple / oficial) (ver Respuesta de 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()
-
Usando
.raw
(ver Respuesta de 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.
La sincronización de ambos no muestra una diferencia notable.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:26
Aquí hay una respuesta más fácil de usar que todavía usa streaming.
Simplemente defina estas funciones y llame a getImage()
. Utilizará el mismo nombre de archivo que la url y escribirá en el directorio actual de forma predeterminada, pero ambos se pueden cambiar.
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')
El request
entrañas de getImage()
se basan en la respuesta aquí y el valor de getImageFast()
se basan en la respuesta arriba.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:47
Voy a publicar una respuesta ya que no tengo suficiente rep para hacer un comentario, pero con wget como publicado por Blairg23, también puede proporcionar un parámetro de salida para la ruta.
wget.download(url, out=path)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-24 13:50:40
Cuando intento ejecutar el siguiente código,la imagen se está degradando, pero el tamaño siempre se limita a 34 KB.
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)
Y también, por favor, háganme saber qué es la configuración.STATICMAP_URL.formato (**datos), estoy usando mi usl en lugar de la configuración.STATICMAP_URL.formato (**datos)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-03 05:40:07
Tan fácil como importar imágenes y solicitudes
from PIL import Image
import requests
img = Image.open(requests.get(url, stream = True).raw)
img.save('img1.jpg')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 08:33:37