Python: come scaricare le immagini per i prototipi delle web app

Python: come scaricare le immagini per i prototipi delle web app

Python può rivelarsi come un ottimo aiutante nell'implementazione di web app nel compito di reperire le immagini di esempio usate durante lo sviluppo.

Supponiamo di voler offrire ai nostri clienti un prototipo il più simile possibile al risultato finale e che per far ciò dobbiamo reperire numerose immagini di esempio.

Effettuare il download delle immagini è un compito che può essere automatizzato con Python seguendo una procedura precisa:

  1. Individuiamo una pagina di un sito che offra immagini prive di copyright. Eviteremo in questo tutorial di utilizzare le API di un servizio come Unsplash a scopo puramente didattico.
  2. Esaminiamo il sorgente HTML della pagina e verifichiamo come sono inserite le immagini. Molti siti infatti offrono un'anteprima delle immagini nella pagina di riepilogo e l'immagine effettiva nella pagina di dettaglio.
  3. Reperiamo la pagina iniziale con il modulo requests e estraiamo gli URL delle pagine di dettaglio con il modulo BeautifulSoup.
  4. Dopo aver studiato il codice sorgente di una pagina di dettaglio, effettuiamo una richiesta GET su ciascun URL e estraiamo dalla pagina il valore dell'attributo src dell'immagine principale, ossia l'URL dell'immagine che vogliamo scaricare.
  5. Scarichiamo quindi l'immagine principale preservandone il nome originale.

La prima funzione che andremo a definire è quella che estrare il nome del file contenuto in un URL.

import os
from urllib.parse import urlsplit

def get_filename_from_url(url=None):
    if url is None:
        return None
    urlpath = urlsplit(url).path
    return os.path.basename(urlpath)

La funzione core urlsplit() estrae il percorso da un URL assoluto. La proprietà path viene quindi usata dal metodo basename() per ottenere il solo nome del file compreso di estensione.

Ora possiamo creare la funzione che effettua il download di una pagina web e restituisce il suo codice HTML come stringa.

import requests

def get_page(url):
    try:
        r = requests.get(url, allow_redirects=True)
        return r.text
    except requests.exceptions.RequestException as e:
        return ''

Se la richiesta HTTP fallisce, viene restituita una stringa vuota. Ora possiamo definire la funzione che effettua il download dell'immagine e la salva nel filesystem.

import requests

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

La proprietà content della risposta viene qui salvata nel filesystem usando la modalità binaria in scrittura poichè si tratta di immagini. Questa funzione restituisce un valore booleano che indica l'esito dell'operazione.

A questo punto dobbiamo estrarre gli elementi della pagina usando i loro attributi HTML.

from bs4 import BeautifulSoup

def get_page_elements(html, attrs):
    soup = BeautifulSoup(html, 'html.parser')
    elements = soup.find_all(attrs=attrs)
    return elements

Poichè stiamo cercando più elementi nel documento, usiamo il metodo find_all() passandogli come parametro il dizionario attrs che ci permette di specificare il nome dell'attributo e il suo valore.

Possiamo quindi definire la funzione principale:

def download_images(start_url, link_class, img_class):
    start_page = get_page(start_url)
    if not start_page:
        return []
    detail_links = get_page_elements(start_page, {'class': link_class})
    downloaded_images = []
    for dlink in detail_links:
        dpage_url = dlink.get('href')
        lnk_page = get_page(dpage_url)
        if not lnk_page:
            continue
        imgs = get_page_elements(lnk_page, {'class': img_class})
        for img in imgs:
            src = img.get('src')
            name = get_filename_from_url(src)
            download = download_image(src, f'./static/{name}')
            if download:
                downloaded_images.append(name)
    return downloaded_images

Questa funzione restituisce una lista contenente i nomi delle immagini scaricate o una lista vuota in caso di errore. Possiamo usare questa funzione come segue:

def main():
    images = download_images('https://site.tld/images/', 'detail', 'pic')
    print(images)


if __name__ == '__main__':
    main()

In conclusione, Python si rivela essere un ottimo strumento per velocizzare l'acquisizione delle assets per creare i prototipi delle web app da presentare.

Torna su