Guardar imágenes con (solo) solicitudes: HTTP para humanos

tenga en cuenta que la versión de ‘solo código’ de la función a continuación se puede obtener en https://gist.github.com/4221658

He estado trabajando en un scraper para descargar URL de imágenes que recopilé para otro proyecto, usando Requests: HTTP for Humans , y el método sugerido para guardar imágenes de las solicitudes me estaba dando algunos problemas:

import requests
from PIL import Image
from StringIO import StringIO

r
= requests.get('http://server.com/1.jpg')
r
.content
i
= Image.open(StringIO(r.content))

Resultó ser mi culpa, pero aún así, PIL puede ser un PITA si aún no lo tiene instalado, por lo que parece potencialmente útil distribuir una solución alternativa que solo requiere una biblioteca estándar (es decir, tal vez 2.6 o 2.7 aunque …) fuera de las solicitudes.

Porque, en realidad, las imágenes no son especiales, son solo archivos. Y si los está descargando, no necesita usar software que comprenda imágenes, solo tiene que manejar los bits de IO y manejo de archivos. Entonces, además de las solicitudes, solo necesitamos dos importaciones de bibliotecas estándar:

import requests
from io import open as iopen
from urlparse import urlsplit

Observe que introduje io.open como iopen y no abierto; no parecía estrictamente necesario, pero quería asegurarme de que era obvio que no estaba usando el File.open más común.

def requests_image(file_url):

suffix_list es una lista blanca: solo se guardarán los archivos que tengan los siguientes sufijos:

suffix_list = ['jpg', 'gif', 'png', 'tif', 'svg',]

Para la validación usamos el mismo truco dos veces, después de obtener la ruta [2] de urlsplit (file_url), por ejemplo:

urlsplit(file_url)[2] = 'image_cache/1354660469986314.jpg'

.split () la ruta con ‘/’ primero y obtenga el resultado más correcto (‘1354660469986314.jpg’) y luego .split () ese resultado con ‘.’
para obtener el sufijo del nombre del archivo (‘jpg’)

file_name =  urlsplit(file_url)[2].split('/')[-1]
file_suffix
= file_name.split('.')[1]

… si desea agregar la comprobación de errores, también puede hacer algo como

fileType = i.headers['content-type'].split('/')[-1]  
# 'image/jpeg' => 'jpeg'

Pero como tendrá que agregar ‘jpeg’ a la lista de sufijos, también puede crear una segunda tupla como ctypes = [‘image / jpeg’, ‘image / png’,] y validar i.headers [‘content -type ‘] contra eso – en mi caso estoy pasando enlaces de img src de todos modos, por lo que no me atasco en demasiada validación.

Continuando, la parte de las solicitudes es muy simple, como lo diseñó kennethreitz

i = requests.get(file_url)

El resto es más o menos el ejemplo de la página io en la biblioteca estándar; lo único que hay que mencionar es que el modo es ‘wb’ para ‘escribir binario.

También para ‘warner brothers’ porque soy fan de bugs bunny desde hace mucho tiempo

    if file_suffix in suffix_list and i.status_code == requests.codes.ok:
with iopen(file_name, 'wb') as file:
file
.write(i.content)
else:
return False

```

Esto se puede probar fácilmente en el intérprete:

requests_image(raw_input())  

y luego copie / pegue las URL de imagen (o URL que no sean de imagen si desea que el intérprete de Python imprima “Falso”)

La función no comentada está aquí:

https://gist.github.com/4221658


* Seamos realistas, importe declaraciones y más: devolver falso es, en el mejor de los casos, una guarnición, no la carne