Qu'est-ce que Scrapling ?
Scrapling est un framework de web scraping Python adaptatif, créé par le développeur D4Vinci. Il a rapidement gagné en popularité sur GitHub Trending en 2026, dépassant 57 000 étoiles, devenant ainsi le représentant de la nouvelle génération d'outils de scraping.
Pourquoi avoir besoin de Scrapling ?
Les frameworks de scraping traditionnels (comme Scrapy, BeautifulSoup) font face à trois problèmes majeurs :
- Les changements de structure du site rendent le code obsolète : Les sélecteurs CSS ou XPath se brisent complètement dès que la page est modifiée
- Blocage par les systèmes anti-bot : Cloudflare Turnstile, Akamai et autres protections renvoient directement une erreur 403 aux requêtes normales
- Faible extensibilité : Passer d'un petit scraping à un crawling massif nécessite de réécrire beaucoup de code
La philosophie de conception centrale de Scrapling est "One library, zero compromises" (une bibliothèque, zéro compromis) :
- Parseur adaptatif : Apprend automatiquement la structure du site, relocalise les éléments automatiquement après une mise à jour de la page
- Anti-blocage intégré : Prêt à l'emploi, contourne Cloudflare Turnstile et autres protections principales
- API similaire à Scrapy : Les développeurs familiers avec Scrapy peuvent migrer sans effort
- De la requête unique au crawling complet : La même API supporte à la fois le scraping simple et le crawling massif concurrentiel
Scrapling vs outils de scraping traditionnels
| Fonctionnalité | BeautifulSoup | Scrapy | Scrapling |
|---|---|---|---|
| Courbe d'apprentissage | Faible | Moyenne | Moyenne |
| Parsing adaptatif | ❌ | ❌ | ✅ |
| Contournement Cloudflare | ❌ | Nécessite plugin | ✅ Intégré |
| Crawling concurrentiel | ❌ | ✅ | ✅ |
| Support pages dynamiques | ❌ | Nécessite middleware | ✅ Playwright intégré |
| Pause/Reprise | ❌ | Nécessite extension | ✅ Intégré |
| Sortie en flux | ❌ | ❌ | ✅ |
Installation de Scrapling
Prérequis
- Python 3.8+
- Gestionnaire de paquets pip
Installation rapide
pip install scrapling
Vérification de l'installation
from scrapling.fetchers import Fetcher
# Tester les fonctionnalités de base
p = Fetcher.fetch('https://example.com')
print(p.title) # Affiche le titre de la page
Dépendances optionnelles
Si vous avez besoin du rendu de pages dynamiques (sites JavaScript), installez Playwright :
pip install playwright
playwright install chromium
Premiers pas : Votre premier scraper
Exemple 1 : Scraping de page simple
Commençons par un exemple simple — récupérer les titres principaux de Hacker News.
from scrapling.fetchers import Fetcher
# Envoyer une requête HTTP
page = Fetcher.fetch('https://news.ycombinator.com/')
# Utiliser les sélecteurs CSS pour extraire les données
stories = page.css('.titleline > a')
for story in stories[:5]: # Prendre seulement les 5 premiers
title = story.text
link = story.attrs.get('href', '')
print(f"Titre : {title}")
print(f"Lien : {link}")
print("-" * 40)
Exemple de sortie :
Titre : Show HN : J'ai construit un outil de collaboration de code en temps réel
Lien : https://github.com/example/collab-tool
----------------------------------------
Titre : Ask HN : Quelle est votre bibliothèque Python préférée en 2026 ?
Lien : https://news.ycombinator.com/item?id=123456
----------------------------------------
Exemple 2 : Parsing adaptatif (Auto-save)
La fonctionnalité principale de Scrapling est le parsing adaptatif. Lors de votre première extraction de données, vous pouvez activer auto_save=True, Scrapling apprendra la structure de la page et sauvegardera les caractéristiques. Lorsque le site est modifié, il suffit de passer adaptive=True, et il pourra retrouver automatiquement les éléments cibles.
from scrapling.fetchers import Fetcher
page = Fetcher.fetch('https://quotes.toscrape.com/')
# Premier scraping : activer auto_save
quotes = page.css('.quote', auto_save=True)
for quote in quotes[:3]:
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
print(f"{text} — {author}")
Si la structure du site change :
# Scrapings suivants : passer adaptive=True
page = Fetcher.fetch('https://quotes.toscrape.com/')
quotes = page.css('.quote', adaptive=True) # S'adapte automatiquement à la nouvelle structure !
for quote in quotes[:3]:
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
print(f"{text} — {author}")
💡 Comment ça marche : Scrapling enregistre plusieurs caractéristiques de l'élément (type de balise, texte voisin, motifs d'attributs, etc.). Même si les noms de classe CSS changent, il peut relocaliser l'élément grâce à d'autres caractéristiques.
Fonctionnalités avancées
1. Contourner Cloudflare Turnstile
De nombreux sites utilisent Cloudflare Turnstile ou d'autres systèmes anti-bot. Le StealthyFetcher de Scrapling peut gérer automatiquement ces protections.
from scrapling.fetchers import StealthyFetcher
# Activer le mode adaptatif
StealthyFetcher.adaptive = True
# Contourner automatiquement Cloudflare
page = StealthyFetcher.fetch(
'https://example-protected-site.com',
headless=True, # Mode navigateur sans tête
network_idle=True # Attendre que le réseau soit inactif
)
# Extraire les données normalement
products = page.css('.product-item')
for product in products:
name = product.css('.name::text').get()
price = product.css('.price::text').get()
print(f"{name} : {price}")
Explication des paramètres clés :
- headless=True : Utilise un navigateur sans tête, simule le comportement d'un utilisateur réel
- network_idle=True : Attend que tout le réseau soit terminé avant l'extraction (adapté aux applications SPA)
- adaptive=True : Active le parsing adaptatif
2. Rendu de pages dynamiques (Playwright)
Pour les sites nécessitant un rendu JavaScript, utilisez DynamicFetcher.
from scrapling.fetchers import DynamicFetcher
page = DynamicFetcher.fetch(
'https://spa-example.com',
wait_for='.content-loaded', # Attendre qu'un élément spécifique apparaisse
timeout=30000 # Délai d'attente (millisecondes)
)
# Extraire le contenu chargé dynamiquement
articles = page.css('article')
for article in articles:
title = article.css('h2::text').get()
summary = article.css('.summary::text').get()
print(f"{title}\n{summary}\n")
3. Scraping asynchrone concurrentiel
Utilisez AsyncFetcher pour réaliser un scraping hautement concurrentiel.
import asyncio
from scrapling.fetchers import AsyncFetcher
async def fetch_multiple_pages():
urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3',
'https://example.com/page/4',
'https://example.com/page/5',
]
# Envoyer des requêtes concurrentes
pages = await AsyncFetcher.fetch_many(urls, concurrency=3)
for url, page in zip(urls, pages):
if page:
title = page.title
print(f"{url} : {title}")
else:
print(f"{url} : Échec de la requête")
asyncio.run(fetch_multiple_pages())
Framework Spider : Crawling massif
Scrapling fournit un framework Spider similaire à Scrapy, supportant le crawling massif concurrentiel.
Spider de base
from scrapling.spiders import Spider, Response
class QuoteSpider(Spider):
name = "quotes"
start_urls = ["https://quotes.toscrape.com/"]
async def parse(self, response: Response):
# Extraire les citations de la page actuelle
for quote in response.css('.quote'):
yield {
"text": quote.css('.text::text').get(),
"author": quote.css('.author::text').get(),
"tags": quote.css('.tag::text').getall()
}
# Pagination
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
# Démarrer le spider
QuoteSpider().start()
Configuration de la concurrence
class MultiPageSpider(Spider):
name = "multi-page"
start_urls = [f"https://example.com/page/{i}" for i in range(1, 101)]
# Configurer la concurrence
custom_settings = {
"concurrency": 5, # Nombre maximum de connexions simultanées
"download_delay": 1, # Délai de téléchargement (secondes)
"robots_txt_obey": True, # Respecter robots.txt
}
async def parse(self, response: Response):
title = response.css('h1::text').get()
yield {"url": response.url, "title": title}
MultiPageSpider().start()
Pause et reprise
Scrapling supporte la persistance basée sur des points de contrôle. Après une sortie élégante avec Ctrl+C, le prochain démarrage reprendra automatiquement.
class LongRunningSpider(Spider):
name = "long-crawl"
start_urls = ["https://large-site.com/"]
custom_settings = {
"checkpoint_dir": "./checkpoints", # Répertoire des points de contrôle
}
async def parse(self, response: Response):
# Extraire les données...
yield {"data": "..."}
# Continuer le crawling
for link in response.css('a::attr(href)').getall():
yield self.follow(link, callback=self.parse)
LongRunningSpider().start()
Cas pratiques
Cas 1 : Scraper les projets GitHub Trending
from scrapling.fetchers import Fetcher
def scrape_github_trending():
page = Fetcher.fetch('https://github.com/trending')
repos = page.css('.Box-row')
trending = []
for repo in repos[:10]:
name = repo.css('h2 a::text').get('').strip()
description = repo.css('p.col-9::text').get('').strip()
stars = repo.css('[href$=stargazers] span::text').get('').strip()
language = repo.css('[itemprop=programmingLanguage]::text').get('').strip()
trending.append({
"name": name,
"description": description,
"stars": stars,
"language": language
})
return trending
if __name__ == "__main__":
results = scrape_github_trending()
for repo in results:
print(f"📦 {repo['name']}")
print(f" {repo['description'][:80]}...")
print(f" ⭐ {repo['stars']} | 📝 {repo['language']}")
print()
Cas 2 : Surveillance des prix de produits e-commerce
from scrapling.fetchers import StealthyFetcher
import json
from datetime import datetime
def monitor_prices():
urls = [
"https://amazon.com/dp/B08N5WRWNW",
"https://amazon.com/dp/B0BSHF7WHW",
"https://amazon.com/dp/B09G9FPHY6",
]
results = []
for url in urls:
page = StealthyFetcher.fetch(url, headless=True)
title = page.css('#productTitle::text').get('').strip()
price = page.css('.a-price .a-offscreen::text').get('').strip()
results.append({
"url": url,
"title": title,
"price": price,
"timestamp": datetime.now().isoformat()
})
print(f"✅ {title[:50]}... - {price}")
# Sauvegarder en JSON
with open('price_monitor.json', 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"\n📊 {len(results)} données de prix sauvegardées dans price_monitor.json")
if __name__ == "__main__":
monitor_prices()
Cas 3 : Sortie en flux (traitement en temps réel)
Pour les crawlers fonctionnant longtemps, vous pouvez utiliser le mode flux pour traiter les données en temps réel.
from scrapling.spiders import Spider, Response
class StreamingSpider(Spider):
name = "streaming-demo"
start_urls = ["https://quotes.toscrape.com/"]
async def parse(self, response: Response):
for quote in response.css('.quote'):
item = {
"text": quote.css('.text::text').get(),
"author": quote.css('.author::text').get()
}
yield item # Produit immédiatement, pas besoin d'attendre la fin
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
# Consommation en flux
async def main():
spider = StreamingSpider()
async for item in spider.stream():
# Traiter chaque item en temps réel
print(f"Reçu : {item['text'][:50]}... par {item['author']}")
# Peut être immédiatement stocké en base de données, envoyé à une file de messages, etc.
import asyncio
asyncio.run(main())
Astuces avancées
1. Rotation de proxy
from scrapling.spiders import Spider, Response
class ProxySpider(Spider):
name = "proxy-spider"
start_urls = ["https://httpbin.org/ip"]
custom_settings = {
"proxy_list": [
"http://proxy1.example.com:8080",
"http://proxy2.example.com:8080",
"http://proxy3.example.com:8080",
],
"proxy_rotation": "per_request", # Rotation de proxy par requête
}
async def parse(self, response: Response):
ip = response.json().get('origin')
print(f"IP actuelle : {ip}")
2. Pipeline d'export personnalisé
from scrapling.spiders import Spider, Response
import csv
class CSVSpider(Spider):
name = "csv-export"
start_urls = ["https://quotes.toscrape.com/"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.csv_file = open('quotes.csv', 'w', newline='', encoding='utf-8')
self.writer = csv.writer(self.csv_file)
self.writer.writerow(['Text', 'Author', 'Tags'])
async def parse(self, response: Response):
for quote in response.css('.quote'):
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
tags = ', '.join(quote.css('.tag::text').getall())
self.writer.writerow([text, author, tags])
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
def close(self, reason):
self.csv_file.close()
print(f"✅ Données sauvegardées dans quotes.csv")
3. Mode développement (cache des réponses)
Lors du débogage de la logique de parsing, évitez les requêtes répétées au serveur.
from scrapling.spiders import Spider, Response
class DevSpider(Spider):
name = "dev-mode"
start_urls = ["https://example.com"]
custom_settings = {
"dev_mode": True, # Activer le mode développement
"cache_dir": "./http_cache", # Répertoire de cache
}
async def parse(self, response: Response):
# Première exécution : cache la réponse sur disque
# Exécutions suivantes : lecture directe depuis le disque, pas de requête réseau
title = response.css('h1::text').get()
yield {"title": title}
Questions fréquentes
Q1 : Quelle est la différence entre Scrapling et Scrapy ?
R : Scrapling peut être considéré comme une version modernisée et améliorée de Scrapy : - Parsing adaptatif : Les sélecteurs de Scrapy deviennent obsolètes après une modification de page, Scrapling s'adapte automatiquement - Anti-blocage intégré : Scrapy nécessite des middlewares supplémentaires pour contourner Cloudflare, Scrapling est prêt à l'emploi - API plus concise : L'API Fetcher de Scrapling est plus adaptée au scraping rapide à petite échelle
Si vous êtes déjà familier avec Scrapy, la migration vers Scrapling n'a pratiquement aucun coût d'apprentissage.
Q2 : Comment gérer les pages après connexion ?
R : Utilisez StealthyFetcher ou DynamicFetcher pour simuler la connexion :
from scrapling.fetchers import DynamicFetcher
page = DynamicFetcher.fetch(
'https://example.com/login',
headless=True,
wait_for='#dashboard' # Attendre la redirection après connexion
)
# Exécuter l'opération de connexion (via Playwright)
page.page.fill('#username', 'votre_nom_utilisateur')
page.page.fill('#password', 'votre_mot_de_passe')
page.page.click('#login-button')
page.page.wait_for_selector('#dashboard')
# Maintenant vous pouvez scraper le contenu après connexion
data = page.css('.private-data::text').getall()
Q3 : Comment limiter la vitesse de crawling pour éviter le blocage ?
R : Configurez le délai de téléchargement et les limites de concurrence dans le Spider :
class PoliteSpider(Spider):
custom_settings = {
"concurrency": 2, # Réduire le nombre de connexions simultanées
"download_delay": 2, # Intervalle de 2 secondes entre chaque requête
"robots_txt_obey": True, # Respecter robots.txt
}
Q4 : Quels sélecteurs Scrapling supporte-t-il ?
R : Supporte les sélecteurs CSS et XPath :
# Sélecteurs CSS
page.css('.class-name::text').get()
page.css('#id-name').getall()
# XPath
page.xpath('//div[@class="example"]/text()').get()
Résumé
Scrapling est le framework de web scraping Python le plus prometteur en 2026. Il combine parfaitement parsing adaptatif, capacités anti-blocage et API similaire à Scrapy, permettant aux développeurs de réaliser les crawlers les plus stables avec le minimum de code.
Récapitulatif des avantages principaux : - ✅ Parseur adaptatif : Relocalisation automatique des éléments après modification de page - ✅ Anti-blocage intégré : Contournement prêt à l'emploi de Cloudflare Turnstile - ✅ De la requête unique au crawling complet : La même API couvre tous les scénarios - ✅ Concurrence, pause/reprise, sortie en flux : Toutes les fonctionnalités de niveau production sont disponibles
Liens utiles : - Dépôt GitHub - Documentation officielle - Communauté Discord
Si cet article vous a été utile, n'hésitez pas à le partager avec plus de développeurs !