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 :

  1. 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
  2. Blocage par les systèmes anti-bot : Cloudflare Turnstile, Akamai et autres protections renvoient directement une erreur 403 aux requêtes normales
  3. 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

BASH
pip install scrapling

Vérification de l'installation

PYTHON
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 :

BASH
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.

PYTHON
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.

PYTHON
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 :

PYTHON
# 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.

PYTHON
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.

PYTHON
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.

PYTHON
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

PYTHON
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

PYTHON
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.

PYTHON
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

PYTHON
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

PYTHON
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.

PYTHON
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

PYTHON
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é

PYTHON
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.

PYTHON
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 :

PYTHON
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 :

PYTHON
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 :

PYTHON
# 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 !