Apprenez à extraire et télécharger des images d’une seule page web en Python en utilisant les requêtes et les bibliothèques BeautifulSoup.
Avez-vous déjà voulu télécharger toutes les images sur une certaine page web ? Dans ce tutoriel, vous apprendrez comment vous pouvez construire un racleur Python qui récupère toutes les images d’une page web étant donné son URL et les télécharge à l’aide de requêtes et de bibliothèques BeautifulSoup.
Pour commencer, nous avons besoin d’un certain nombre de dépendances, installons-les:
pip3 install requests bs4 tqdm
Ouvrir un nouveau fichier Python et importer les modules nécessaires:
import requests
import os
from tqdm import tqdm
from bs4 import BeautifulSoup as bs
from urllib.parse import urljoin, urlparse
Tout d’abord, faisons un validateur d’URL, qui s’assure que l’URL passée est valide, car il y a des sites web qui mettent des données encodées à la place d’une URL, donc nous devons sauter ceux-ci:
def is_valid(url):
"""
Vérifie si « url » est une URL valide.
"""
parsed = urlparse(url)
return bool(parsed.netloc) and bool(parsed.scheme)
urlparse() fonction analyse une URL en six composantes, il suffit de voir si le netloc (nom de domaine) et le schéma (protocole) sont là.
Deuxièmement, je vais écrire la fonction centrale qui saisit toutes les URL d’image d’une page web :
def get_all_images(url):
"""
Renvoie toutes les URL d'images sur une seule `url`
"""
soup = bs(requests.get(url).content, "html.parser")
Le contenu HTML de la page web est en soup
objet, pour extraire toutes les étiquettes img dans HTML, nous devons utiliser soup.find_all("img")
Méthode, voyons-le en action:
urls = []
for img in tqdm(soup.find_all("img"), "Extracting images"):
img_url = img.attrs.get("src")
if not img_url:
## si img ne contient pas d'attribut src, sautez simplement
continue
Cela permettra de récupérer tous les éléments d’image sous la liste Python
Je l’ai enveloppé dans un objet tqdm juste pour imprimer une barre de progression. Pour saisir l’URL d’une balise img, il y a un attribut src. Cependant, il y a certaines étiquettes qui ne contiennent pas l’attribut src, nous les sautons en utilisant la mention continue ci-dessus.
Maintenant, nous devons nous assurer que l’URL est absolue :
#rendre l'URL absolue en joignant le domaine avec l'URL qui vient d'être extraite
img_url = urljoin(url, img_url)
Il y a des URL qui contiennent des paires de valeur de clé HTTP GET que nous n’aimons pas (cela se termine par quelque chose comme « /image.png?c.c.
try:
pos = img_url.index("?")
img_url = img_url[:pos]
except ValueError:
pass
Nous obtenons la position du caractère ‘?’, puis enlever tout après, s’il n’y en a pas, il va augmenter ValueError, c’est pourquoi je l’ai enveloppé dans le but/sauf le bloc (bien sûr, vous pouvez l’implémenter d’une meilleure manière, si oui, s’il vous plaît, partagez-le avec nous dans les commentaires ci-dessous).
Maintenant, assurons-nous que chaque URL est valide et retourne toutes les URL de l’image:
#enfin, si l'url est valide
if is_valid(img_url):
urls.append(img_url)
return urls
Maintenant que nous avons une fonction qui saisit toutes les URL d’image, nous avons besoin d’une fonction pour télécharger des fichiers à partir du web avec Python, j’ai apporté la fonction suivante de ce tutoriel :
def download(url, pathname):
"""
Télécharge un fichier à partir d'une URL et le place dans le dossier `pathname`
"""
#si le chemin n'existe pas, créez ce chemin dir
if not os.path.isdir(pathname):
os.makedirs(pathname)
#télécharger le corps de la réponse par morceaux, pas immédiatement
response = requests.get(url, stream=True)
#obtenir la taille totale du fichier
file_size = int(response.headers.get("Content-Length", 0))
#obtenir le nom du fichier
filename = os.path.join(pathname, url.split("/")[-1])
#barre de progression, changeant l'unité en octets au lieu d'itération (par défaut par tqdm)
progress = tqdm(response.iter_content(1024), f"Downloading {filename}", total=file_size, unit="B", unit_scale=True, unit_divisor=1024)
with open(filename, "wb") as f:
for data in progress.iterable:
#écrire les données lues dans le fichier
f.write(data)
#mettre à jour la barre de progression manuellement
progress.update(len(data))
La fonction ci-dessus amène essentiellement l’url de fichier à télécharger et le nom de chemin du dossier pour enregistrer ce fichier.
Enfin, voici la fonction principale:
def main(url, path):
#obtenir toutes les images
imgs = get_all_images(url)
for img in imgs:
#pour chaque image, téléchargez-la
download(img, path)
Obtenir toutes les URL d’images à partir de cette page et les télécharger chacune une par une. Testons ceci :
main("https://yandex.com/images/", "yandex-images")
Cela permettra de télécharger toutes les images de cette URL et les stockera dans le dossier « yandex-images » qui sera créé automatiquement.
Remarquez cependant, il y a des sites web qui chargent leurs données en utilisant Javascript, dans ce cas, vous devriez utiliser request bibliothèque.