In questo articolo vedremo come effettuare il download ed il ridimensionamento di un'immagine usando le API di Unsplash con Python.

Per il nostro scopo sono necessari tre moduli aggiuntivi:

  1. requests per effettuare le richieste HTTP.
  2. python-dotenv per leggere la chiave API di Unsplash che memorizzeremo in un file .env.
  3. Pillow per la manipolazione delle immagini.

Dopo aver impostato l'ambiente virtuale e installato i moduli richiesti, salviamo la chiave API di Unsplash in un file .env.

ACCESS_KEY=chiave_API

Quindi invochiamo la funzione load_dotenv() all'inizio del nostro codice in modo da caricare in memoria il file appena creato che andrà a popolare le nostre variabili d'ambiente.

import sys
import os
import requests
from dotenv import load_dotenv
from PIL import Image

load_dotenv()

Ora possiamo creare una funzione per il download dell'immagine remota.

def download_image(url=None, name='image.jpg'):
    if url is None:
        return None
    try:
        res = requests.get(url, allow_redirects=True)
        data = res.content
        with open(name, 'wb') as img:
            img.write(data)
        return True
    except requests.exceptions.RequestException:
        return False

Il contenuto della risposta, la proprietà content, contiene i dati binari dell'immagine che andremo a salvare in locale con il nome specificato.

Ora con il modulo Pillow dobbiamo creare una funzione che effettui il ridimensionamento dell'immagine.

def resize_image(img=None, dimensions=(2000, 850)):
    if img is None:
        return False
    with Image.open(img) as im:
        im.resize(dimensions)
        im.save(f'./resized/{img}')
    os.unlink(img)
    return True

L'immagine da ridimensionare è l'immagine salvata in precedenza. La tuple dimensions specifica l'altezza e la larghezza che verranno usate dal metodo resize(). Quindi l'immagine viene salvata in una nuova destinazione e l'immagine scaricata viene eliminata.

A questo punto non ci resta che definire una funzione che, dato come argomento un termine di ricerca, effettui una richiesta alle API di Unsplash e restituisca l'URL dell'immagine contenuta nel primo risultato della ricerca.

def unsplash_api_search(query=None):
    if query is None:
        return None
    api_url = 'https://api.unsplash.com/search/photos'
    params = {'query': query, 'client_id': os.getenv('ACCESS_KEY')}

    try:
        res = requests.get(api_url, params=params, allow_redirects=True)
        data = res.json()
        if not data.get('total'):
            return None
        return data['results'][0]['urls']['raw']

    except requests.exceptions.RequestException:
        return None

Possiamo usare le funzioni che abbiamo definito direttamente dalla shell con un minimo di interazione da parte dell'utente nella scelta del termine di ricerca.

def main():
    search_query = input('Query: ')
    if not search_query:
        print('Invalid query.')
        sys.exit(1)
    results_url = unsplash_api_search(search_query)
    if results_url is None:
        print('Request error.')
        sys.exit(1)
    print('Got a result from the API.')
    img_name = f'{search_query.strip()}.jpg'
    print('Downloading image...')
    is_image_downloaded = download_image(results_url, img_name)
    if not is_image_downloaded:
        print('Download error.')
        sys.exit(1)
    print(f'Downloaded {img_name}')
    resized_img = resize_image(img_name)
    if not resized_img:
        print('Resize error')
        os.unlink(img_name)
        sys.exit(1)
    print(f'Resized image in ./resized/{img_name}')


if __name__ == '__main__':
    main()