Estoy tratando de descargar y guardar una imagen de la web usando el requests
módulo de Python .
Aquí está el código (de trabajo) que utilicé:
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)
¿Me pueden ayudar en qué atributo de la respuesta usar requests
?
python
urllib2
python-requests
shkschneider
fuente
fuente
Respuestas:
Puede usar el
response.raw
objeto de archivo o iterar sobre la respuesta.El uso del
response.raw
objeto tipo archivo no descodificará, de forma predeterminada, las respuestas comprimidas (con GZIP o desinflado). De todos modos, puede forzarlo a descomprimirse configurando eldecode_content
atributo enTrue
(lorequests
configuraFalse
para controlar la decodificación). Luego puede usarshutil.copyfileobj()
para que Python transmita los datos a un objeto de archivo:Para iterar sobre la respuesta, use un bucle; iterar así asegura que los datos se descompriman en esta etapa:
Esto leerá los datos en fragmentos de 128 bytes; Si cree que otro tamaño de fragmento funciona mejor, utilice el
Response.iter_content()
método con un tamaño de fragmento personalizado: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 lo configuramos
stream=True
para querequests
no descargue la imagen completa en la memoria primero.fuente
r2 = requests.post(r.url, data); print r2.content
. Pero ahora también quiero saberfilename
. ¿hay alguna forma limpia? - actualmente encontré el nombre del archivo en el encabezado -r2.headers['content-disposition']
eso me da salida como:'attachment; filename=DELS36532G290115.csi'
Estoy analizando esta cadena para el nombre del archivo ... ¿es su forma más limpia?content-disposition
encabezado es el camino a seguir aquí; usecgi.parse_header()
para analizarlo y obtener los parámetros;params = cgi.parse_header(r2.headers['content-disposition'])[1]
entoncesparams['filename']
.requests.Response
misma :for chunk in r: ...
. Llamandoiter_content()
sinchunk_size
tendrá una iteración en trozos de 1 byte .response.ok
nunca se documentó, y produce verdadero para cualquier estado 1xx, 2xx o 3xx, pero solo una respuesta 200 tiene un cuerpo de respuesta.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 de una vez.
fuente
r.raw.decode_content = True
antesshutil.copyfileobj(response.raw, out_file)
porqueby default, decode compressed responses (with GZIP or deflate)
, por lo que obtendrá una imagen de archivo cero.Qué tal esto, una solución rápida.
fuente
f = open("/Users/apple/Desktop/sample.jpg", 'wb')
¿Qué quieres decir con este camino? Quiero descargar la imagenif response.ok:
Tengo la misma necesidad de descargar imágenes usando solicitudes. Primero probé la respuesta de Martijn Pieters, y funciona bien. Pero cuando hice un perfil en esta función simple, descubrí que usa 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:
Esto redujo mucho más el número de llamadas a funciones, acelerando así mi aplicación. Aquí está el código de mi perfilador y el resultado.
El resultado para testRequest:
Y el resultado para testRequest2:
fuente
chunk_size
parámetro que por defecto es 1, por lo queiter_content
está iterando sobre el flujo de resultados 1 byte a la vez. Consulte la documentación de python-requests.org/en/latest/api/… .PIL
aquí tampoco, solowith open(image_name, 'wb') as outfile: outfile.write(r.content)
es suficiente.PIL
tampoco está en la biblioteca estándar, lo que lo hace un poco menos portátil.iter_content
es lento porque tuchunk_size
es demasiado pequeño, si lo aumentas a 100k será mucho más rápido.Esto podría ser más fácil que usar
requests
. Esta es la única vez que sugeriré no usarrequests
para hacer cosas HTTP.Dos revestimientos usando
urllib
:También hay un bonito módulo Python llamado
wget
que es bastante fácil de usar. Encontrado aquí .Esto demuestra la simplicidad del diseño:
Disfrutar.
Editar: también puede agregar un
out
parámetro para especificar una ruta.fuente
wget
sin problemas. Gracias por indicar los beneficios de usarurllib3
urllib.request.urlretrieve("http://example.com", "file.ext")
.El siguiente fragmento de código descarga un archivo.
El archivo se guarda con su nombre de archivo como en la URL especificada.
fuente
Hay 2 formas principales:
Usando
.content
(más simple / oficial) (ver la respuesta de Zhenyi Zhang ):Utilizando
.raw
(ver la respuesta de Martijn Pieters ):La sincronización de ambos no muestra una diferencia notable.
fuente
1.
respuesta (usandoio.BytesIO
yImage
) fue la primera que funcionó para mí en Python 3.6. No te olvidesfrom PIL import Image
(ypip install Pillow
).Tan fácil como importar imágenes y solicitudes
fuente
Aquí hay una respuesta más fácil de usar que todavía usa la transmisión.
Simplemente defina estas funciones y llame
getImage()
. Utilizará el mismo nombre de archivo que la url y escribirá en el directorio actual de forma predeterminada, pero ambos se pueden cambiar.Las
request
agallas degetImage()
se basan en la respuesta aquí y las agallas degetImageFast()
se basan en la respuesta anterior .fuente
Voy a publicar una respuesta ya que no tengo suficiente representante para hacer un comentario, pero con wget publicado por Blairg23, también puede proporcionar un parámetro de salida para la ruta.
fuente
Esta es la primera respuesta que surge para las búsquedas de Google sobre cómo descargar un archivo binario con solicitudes. En caso de que necesite descargar un archivo arbitrario con solicitudes, puede usar:
fuente
.close()
. Esta es la mejor respuesta a partir de 2019, supongo.Así es como lo hice
fuente
Puedes hacer algo como esto:
fuente