AccueilBlogTest technique web scraping Python : BeautifulSoup, Selenium, Scrapy, éthique
Guide recrutement data

Test technique web scraping Python : BeautifulSoup, Selenium, Scrapy, éthique

Le web scraping est une compétence Data Engineer courante pour collecter des données non disponibles via API. En entretien, on évalue la maîtrise technique mais aussi la capacité à respecter les contraintes légales et techniques.

Data Builder·Juin 2025·8 min de lecture·Data Engineer

Le scraping n'est pas que technique — c'est aussi une question de responsabilité. En entretien, un candidat qui ne mentionne ni le robots.txt ni les aspects légaux n'est pas prêt pour la production.

1HTTP et HTML : les fondamentaux

Question discriminante

Quelle est la différence entre une page HTML statique et une page rendue côté client (SPA) ? Quel impact sur votre approche de scraping ?

  • Page statique — le contenu HTML est directement dans la réponse HTTP. BeautifulSoup + requests suffisent
  • Page dynamique (SPA) — le HTML initial est vide, le contenu est chargé via JavaScript/AJAX. Nécessite Selenium ou Playwright pour exécuter le JS
  • Inspection réseau — chercher les appels XHR/Fetch dans les DevTools Chrome. Si l'API sous-jacente est accessible, l'appeler directement est plus efficace que le scraping DOM
  • Status codes HTTP : 200 OK, 301/302 redirect, 403 Forbidden, 429 Too Many Requests, 503 Service Unavailable

2BeautifulSoup : scraping de pages statiques

Question discriminante

Comment scrapez-vous toutes les pages d'un site paginé ? Comment gérez-vous les erreurs et les timeouts ?

import requests from bs4 import BeautifulSoup import time import random def scrape_page(url: str, max_retries: int = 3) -> BeautifulSoup: headers = { "User-Agent": "Mozilla/5.0 (compatible; DataBot/1.0)", "Accept-Language": "fr-FR,fr;q=0.9" } for attempt in range(max_retries): try: response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() return BeautifulSoup(response.text, "lxml") except requests.RequestException as e: if attempt < max_retries - 1: time.sleep(2 ** attempt) # exponential backoff else: raise def scrape_all_pages(base_url: str) -> list: results = [] page = 1 while True: soup = scrape_page(f"{base_url}?page={page}") items = soup.select(".product-card") if not items: break for item in items: results.append({ "name": item.select_one(".title").get_text(strip=True), "price": item.select_one(".price").get_text(strip=True), "url": item.select_one("a")["href"] }) page += 1 time.sleep(random.uniform(1, 3)) # politeness delay return results
  • Sélecteurs CSS — .select() et .select_one() pour sélectionner par classe, ID, attributs
  • Exponential backoff — attendre de plus en plus longtemps après chaque échec pour ne pas surcharger le serveur
  • Politeness delay — pause aléatoire entre les requêtes pour imiter le comportement humain

3Selenium et Playwright : sites dynamiques

Question discriminante

Quand utilisez-vous Selenium plutôt que BeautifulSoup ? Et Playwright plutôt que Selenium ?

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC options = webdriver.ChromeOptions() options.add_argument("--headless") # sans interface graphique options.add_argument("--no-sandbox") driver = webdriver.Chrome(options=options) driver.get("https://exemple.com/products") # Attendre que les données soient chargées wait = WebDriverWait(driver, 10) products = wait.until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".product-card")) ) data = [] for product in products: data.append({ "name": product.find_element(By.CSS_SELECTOR, ".title").text, "price": product.find_element(By.CSS_SELECTOR, ".price").text }) driver.quit()
  • Selenium — contrôle un vrai navigateur Chrome/Firefox, idéal pour les SPA JavaScript
  • Playwright — plus rapide, plus moderne, meilleure gestion des async. Recommandé pour les nouveaux projets
  • WebDriverWait — attendre que les éléments soient présents avant de les lire (évite les erreurs sur les pages lentes à charger)

4Scrapy : scraping industriel

Question discriminante

Dans quel cas utilisez-vous Scrapy plutôt que requests+BeautifulSoup ?

  • Scrapy — framework complet pour le scraping industriel : gestion automatique des requêtes concurrentes, middlewares, pipelines de traitement, respecte robots.txt nativement
  • Avantages : scraping concurrent (async), pipelines d'export (JSON, CSV, base de données), gestion des cookies et sessions, logging intégré
  • Cas d'usage : scraper des milliers de pages, scraping récurrent planifié (Scrapy + Scrapyd ou Airflow)
  • Scrapy vs requests — requests pour 1-100 pages, Scrapy pour 1000+ pages ou scraping récurrent

5Gestion des protections anti-bots

Question discriminante

Vous recevez un 403 ou un CAPTCHA après quelques requêtes. Que faites-vous ?

  • 429 Too Many Requests — respecter le Retry-After header, augmenter le délai entre les requêtes
  • Rotation de User-Agent — varier les User-Agent pour ne pas être identifié comme bot
  • Proxies rotatifs — utiliser un pool de proxies pour distribuer les requêtes (Bright Data, Oxylabs)
  • CAPTCHA — services de résolution (2captcha, Anti-Captcha) ou reconsidérer l'approche (API officielle ?)
  • Session management — maintenir les cookies de session pour paraître comme un utilisateur régulier

Avant tout : vérifier s'il existe une API officielle ou un export de données. Le scraping est toujours un dernier recours.

6Légalité et éthique du scraping

Question discriminante

Comment vérifiez-vous que votre scraper respecte les règles du site ? Quels aspects légaux prenez-vous en compte ?

  • robots.txt — toujours vérifier avant de scraper. Le respect n'est pas légalement obligatoire mais est une pratique éthique standard
  • CGU/ToS — certains sites interdisent explicitement le scraping dans leurs conditions. Violation possible si données commercialisées
  • RGPD — scraper des données personnelles (emails, noms) de citoyens européens sans base légale valide est illégal
  • Propriété intellectuelle — le contenu scraper peut être protégé par copyright (textes, images)
  • Charge serveur — un scraper trop agressif peut être assimilé à une attaque DoS. Limiter la fréquence des requêtes

7Grille par niveau

NiveauMaîtrise attendueSignal GONO-GO
Juniorrequests + BeautifulSoup, sélecteurs CSS, gestion des erreurs basiqueA scraper plusieurs pages avec pagination, gère les timeoutsNe vérifie pas robots.txt, ne gère pas les erreurs HTTP
ConfirméSelenium/Playwright pour les SPA, exponential backoff, ScrapySait quand utiliser Selenium vs BeautifulSoup, a utilisé Scrapy sur un projetNe sait pas gérer les pages JavaScript, n'a jamais utilisé Scrapy
SeniorProxies rotatifs, scraping industrialisé, aspects légaux maîtrisésA industrialisé un scraper en production avec Airflow, cite spontanément robots.txt et RGPDNe mentionne pas les aspects légaux, n'a pas de stratégie pour les anti-bots

Vous recrutez un Data Engineer ?

Premier entretien gratuit. Rapport GO/NO-GO sous 48h.

Tester gratuitementRéserver un appel