Salvando imagens com (apenas) Solicitações: HTTP para humanos

observe que a versão ‘apenas código’ da função abaixo pode ser obtida em https://gist.github.com/4221658

Estou trabalhando em um raspador para baixar URLs de imagem que coletei para outro projeto, usando Requests: HTTP for Humans , e o método sugerido para salvar imagens de solicitações estava me causando alguns 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))

Acabou sendo minha própria culpa, mas ainda assim – PIL pode ser um PITA se você ainda não o tiver instalado, então parece potencialmente útil distribuir uma solução alternativa que requer apenas biblioteca padrão (er, talvez 2.6 ou 2.7 embora …) fora das solicitações.

Porque, na realidade, as imagens não são especiais – são apenas arquivos. E se você estiver baixando-os, você não precisa usar um software que entenda imagens, você só precisa lidar com o IO e os bits de manuseio de arquivo. Portanto, além das solicitações, precisamos apenas de duas importações de biblioteca padrão:

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

Observe que incluí io.open como iopen e não como open – não parecia estritamente necessário, mas queria ter certeza de que era óbvio que não estava usando o File.open mais comum.

def requests_image(file_url):

suffix_list é uma lista de permissões – apenas os arquivos que têm os seguintes sufixos serão salvos:

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

Para validação, usamos o mesmo hack duas vezes – depois de obter o caminho [2] de urlsplit (file_url), ex:

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

.split () o caminho com ‘/’ primeiro e obter o resultado mais correto (‘1354660469986314.jpg’) e depois .split () esse resultado com ‘.’
para obter o sufixo do nome do arquivo (‘jpg’)

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

… se você quiser adicionar verificação de erro, você também pode fazer algo como

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

Mas já que você vai ter que adicionar ‘jpeg’ à lista de sufixos, você também pode fazer uma segunda tupla como ctypes = [‘imagem / jpeg’, ‘imagem / png’,] e validar i.headers [‘conteúdo -tipo ‘] contra isso – no meu caso, estou passando links de img src de qualquer maneira, então não estou me atrapalhando com muita validação.

Continuando, a parte dos pedidos é muito simples, conforme projetado por kennethreitz

i = requests.get(file_url)

O resto é basicamente o exemplo da página io no lib padrão – a única coisa a mencionar é que o modo é ‘wb’ para ‘binário de escrita.

Também para ‘irmãos warner’ porque sou um fã de bugs bunny há muito tempo

    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

```

Isso pode ser testado no intérprete facilmente:

requests_image(raw_input())  

e, em seguida, copie / cole urls de imagem (ou urls de não imagem, se quiser ver o interpretador python imprimir “Falso”)

A função não comentada está aqui:

https://gist.github.com/4221658


* sejamos realistas, importe declarações e mais: return false é enfeite na melhor das hipóteses – não a carne