Aller au contenu
Retour au blog

JavaScript avec Scrapy : les données d'abord, le rendu uniquement lorsque cela est nécessaire

Mihai MaximDernière mise à jour le 13 min read
JavaScript avec Scrapy : les données d'abord, le rendu uniquement lorsque cela est nécessaire
En bref : l’utilisation de JavaScript avec Scrapy ne nécessite pas toujours un navigateur. Commencez par analyser la réponse brute, les requêtes réseau et l’état de la page intégrée ; n’ajoutez « scrapy-playwright » que lorsque les données cibles dépendent réellement de l’exécution dans le navigateur, puis gérez de manière réfléchie les temps d’attente, les interactions, le nettoyage et la concurrence.

Utiliser JavaScript avec Scrapy revient à ajouter une exécution en navigateur pour les pages dont les données requises n’apparaissent qu’après l’exécution du code côté client. L’objectif pratique n’est pas de rendre chaque page, mais d’identifier le chemin le plus économique et le plus fiable vers les données : du HTML brut, une requête JSON, un objet JavaScript intégré ou, uniquement lorsque cela est nécessaire, un DOM construit par le navigateur.

Cette distinction est importante car le téléchargeur de Scrapy reçoit la réponse du serveur, tandis que Chrome ou Firefox peuvent effectuer des requêtes supplémentaires et modifier le document par la suite. Une page React, Vue ou Angular peut donc sembler complète dans DevTools même si response.text elle ne contienne guère plus qu’une coquille d’application.

Ce guide commence par un diagnostic « navigateur en dernier », puis met en place un workflow Scrapy-Playwright ciblé pour les requêtes qui nécessitent réellement d’être exécutées. Vous découvrirez également comment utiliser des attentes conditionnelles, gérer les clics et l’état de session, comparer les options de rendu et assurer la stabilité des robots dynamiques en production. Il en résulte un workflow qui préserve autant que possible l’efficacité du pipeline HTTP de Scrapy, sans prétendre que tous les sites modernes peuvent être explorés à partir d’un simple balisage statique.

Identifiez la source de données avant le rendu

Avant d’essayer d’exécuter du JavaScript avec Scrapy, examinez ce que le serveur a déjà renvoyé. Les recommandations officielles de Scrapy concernant le contenu dynamique préconisent de localiser d’abord la source sous-jacente. Suivez cet ordre : réponse brute, requête réseau, état intégré, puis navigateur sans interface graphique.

Comparez la réponse de Scrapy avec le DOM rendu

Enregistrez ou recherchez response.text une valeur distinctive visible dans le navigateur, telle qu’un identifiant de produit plutôt qu’un prix formaté. Comparez-la ensuite avec le panneau « Éléments » des DevTools. Si la valeur n’existe que dans le DOM rendu, c’est probablement JavaScript qui l’a insérée, mais cela ne prouve pas pour autant que le rendu soit nécessaire. L’application a peut-être récupéré la même valeur à partir d’un point de terminaison accessible.

Un guide plus complet sur le web scraping avec Scrapy constitue ici une référence interne utile, notamment pour l’inspection des réponses, les sélecteurs et le débogage des requêtes.

Reproduisez la requête XHR ou fetch

Ouvrez DevTools, sélectionnez « Réseau », rechargez la page, puis filtrez par « Fetch/XHR ». Inspectez les réponses candidates jusqu’à ce que vous trouviez les champs dont vous avez besoin. Notez l’URL, la méthode HTTP, la chaîne de requête ou le corps de la requête, les en-têtes pertinents, ainsi que les cookies ou jetons liés à la session.

Reproduisez la plus petite requête valide dans Scrapy au lieu de copier tous les en-têtes du navigateur :

def parse(self, response):
    yield scrapy.Request(
        "https://example.com/api/products?page=1",
        headers={"Accept": "application/json"},
        callback=self.parse_products,
    )

def parse_products(self, response):
    payload = response.json()
    for row in payload["results"]:
        yield {"id": row["id"], "name": row["name"]}

Cette approche évite les délais liés au DOM, la consommation de mémoire du navigateur et les modifications des sélecteurs visuels. Si le point de terminaison utilise la pagination, des valeurs de curseur ou des données POST, suivez directement ces paramètres. En cas d’authentification, conservez les cookies ou le flux de jetons requis plutôt que de coder en dur des identifiants à durée de vie limitée.

Analysez le JSON et les données intégrées dans les scripts

Parfois, le code HTML initial contient déjà l’état de l’application à l’intérieur d’un <script> . Extrayez ce script à l’aide d’un sélecteur CSS ou XPath. Utilisez json.loads() lorsque le contenu est du JSON valide ; utilisez chompjs lorsqu’il s’agit d’une syntaxe d’objet JavaScript comportant des clés non entre guillemets, des virgules de fin ou d’autres différences similaires.

import chompjs

script = response.css("script[data-page-state]::text").get()
state = chompjs.parse_js_object(script) if script else {}
items = state.get("products", [])

Préférez un analyseur structuré à une expression régulière trop générale. Les expressions régulières peuvent isoler une affectation clairement délimitée, mais elles deviennent fragiles face à des objets imbriqués et des chaînes échappées. Associer des requêtes JSON directes à l’analyse des balises script permet souvent de traiter le contenu dynamique de Scrapy sans lancer de navigateur.

Ajoutez le rendu JavaScript avec scrapy-playwright

Lorsque les données dépendent d’un comportement propre au navigateur, tel que du code d’application, des API Web ou un état piloté par les interactions, ajoutez le rendu de manière sélective. Cet exemple de JavaScript avec Scrapy utilise scrapy-playwright comme principal chemin d’intégration, tout en conservant les requêtes ordinaires sur le téléchargeur standard de Scrapy.

Installer et configurer l’intégration

Un modèle de configuration couramment documenté consiste à installer le plugin et un binaire du navigateur Playwright dans le même environnement de projet :

python -m pip install scrapy-playwright
python -m playwright install chromium

Ajoutez le réacteur asyncio et les gestionnaires de téléchargement Playwright à settings.py:

TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"

DOWNLOAD_HANDLERS = {
    "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
    "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
}

PLAYWRIGHT_BROWSER_TYPE = "chromium"

Fixez les versions compatibles des dépendances dans les projets déployables, et testez le même fichier de verrouillage en développement et en production. Les exemples fournis ne valident pas l’ensemble des possibilités de configuration actuelles du plugin ; consultez donc la documentation actuelle du projet avant de considérer ce modèle comme prêt pour la mise en production.

Rendu d’une requête et analyse à l’aide des sélecteurs Scrapy

Marquez uniquement la requête nécessitant un navigateur. Une attente de sélecteur pertinente garantit que la fonction de rappel reçoit le code HTML une fois que le composant cible est affiché :

import scrapy
from scrapy_playwright.page import PageMethod

class ProductsSpider(scrapy.Spider):
    name = "products"

    def start_requests(self):
        yield scrapy.Request(
            "https://example.com/products",
            meta={
                "playwright": True,
                "playwright_page_methods": [
                    PageMethod(
                        "wait_for_selector",
                        "[data-product-card]",
                    )
                ],
            },
        )

    def parse(self, response):
        for card in response.css("[data-product-card]"):
            yield {
                "name": card.css("[data-name]::text").get(),
                "price": card.css("[data-price]::text").get(),
            }

La fonction de rappel reçoit toujours une réponse Scrapy ; les modèles d’extraction CSS et XPath existants restent donc utiles. Conservez les pages de catégories statiques, les appels API et les ressources dans des requêtes normales. Un tutoriel Scrapy-Playwright dédié aux sites à forte intensité JavaScript constitue la référence interne suivante tout indiquée lorsque vous avez besoin de contextes multiples, d’événements de page ou d’une configuration de projet plus poussée.

Attendre et interagir avec le contenu dynamique

Un événement de navigation terminé ne signifie pas que les données de l’application sont prêtes. Le rendu JavaScript de Scrapy ne devient fiable que lorsque l’araignée attend un état lié aux champs qu’elle prévoit d’extraire.

Privilégiez les attentes basées sur l’état plutôt que les délais fixes

Attendez un sélecteur stable, une réponse API connue, une transition d’URL ou un indicateur de l’application. Un sélecteur tel que [data-results-loaded="true"] exprime mieux l’intention qu’une mise en veille de trois secondes. Les délais fixes peuvent s’avérer trop courts lors d’une exécution lente et faire perdre du temps lors d’une exécution rapide.

Utilisez des délais d’attente bornés et consignez la condition qui a échoué. En l’absence de signal stable, un court délai d’attente fixe peut servir de solution de secours, mais fixez une limite supérieure à l’ensemble de la requête du navigateur. Cela permet de rendre observable l’attente Scrapy en cas d’échec JavaScript, au lieu de laisser les pages ouvertes indéfiniment.

Cliquer, faire défiler, paginer et conserver l’état de la session

Les méthodes de page peuvent effectuer une interaction contrôlée avant que la réponse ne revienne :

bplaywright_page_methods": [
    PageMethod("click", "button.load-more"),
    PageMethod("wait_for_selector", "[data-page='2']"),
]

Pour le défilement infini, répétez une action de défilement uniquement tant que le nombre d’éléments augmente, et arrêtez-vous après un nombre défini de passages sans changement. Pour la pagination, privilégiez la requête de données du site si elle existe ; sinon, cliquez sur le contrôle « Suivant » et attendez qu’un marqueur de page ou l’ID de la première ligne change.

Conservez les requêtes authentifiées associées dans le même contexte de navigateur nommé afin que les cookies et le stockage local puissent persister. Avec playwright_include_page=True, fermez la page active dans un finally bloc. Fermez un contexte dédié après sa dernière requête de session, et non tant que d’autres requêtes en dépendent encore :

async def parse_last_session_page(self, response):
    page = response.meta["playwright_page"]
    context = page.context
    try:
        return {"title": await page.title()}
    finally:
        await page.close()
        await context.close()

Les API d’inclusion et de nettoyage pouvant évoluer, vérifiez les métadonnées de la requête en cours et les règles de cycle de vie avant le déploiement. Les pages qui fuient finissent par épuiser la limite de pages du navigateur et donnent l’impression qu’un spider JavaScript avec Scrapy, par ailleurs correct, est bloqué.

Comparez les options JavaScript de Scrapy

Le choix de la meilleure intégration dépend de vos besoins en matière de navigateur réel, du niveau d’interaction requis par le flux et de l’identité de l’opérateur de l’infrastructure de rendu. Ne vous fiez pas uniquement à la rapidité apparente de la première démo.

Playwright, Selenium, Splash et les API de rendu hébergées

Option

Meilleur choix

Principaux compromis

scrapy-playwright

Rendu sélectif dans un navigateur au sein d’un projet Scrapy, y compris les interactions modernes

Coût en CPU et en mémoire du navigateur, gestion asynchrone du cycle de vie et détails d’intégration dépendants de la version

Intégration basée sur Selenium

Équipes disposant déjà d’un code d’automatisation ou de test WebDriver

Gestion des pilotes et des navigateurs, davantage de liens avec Scrapy, et compatibilité à vérifier pour le package choisi

Intégration basée sur Splash

Un service de rendu HTTP ou des workflows existants basés sur Lua

Un service distinct à exploiter, ainsi qu’un comportement JavaScript pouvant différer de celui d’un navigateur complet actuel

API de rendu hébergée

Externalisation de l’infrastructure de navigateur, de proxy et de tentatives de reconnexion

Limites propres au fournisseur, sémantique des délais d’expiration, concurrence, tarification et contrôle local réduit

Une comparaison ciblée entre Scrapy et Selenium peut s’avérer utile si vous gérez déjà du code WebDriver. Un tutoriel Scrapy Splash est plus pertinent lorsque votre architecture privilégie un service de rendu autonome. Pour l’utilisation de JavaScript avec Scrapy, optez pour la solution qui répond au minimum d’interaction requis tout en conservant les requêtes simples sans passer par un navigateur.

Le rendu ne constitue pas une garantie anti-bot. Un navigateur complet peut toujours recevoir une réponse 403, un CAPTCHA, une limitation de débit ou une vérification de compte ; évaluez donc les contrôles d’accès indépendamment de l’exécution du DOM.

Exécutez vos robots de recherche avec rendu de manière fiable en production

Un navigateur sans interface utilisateur avec Scrapy est plus lent et plus gourmand qu’une requête HTTP normale. La fiabilité en production repose sur la limitation du travail du navigateur, le confinement des défaillances et la mesure des ressources.

Maîtrisez les coûts, la concurrence et les ressources du navigateur

N’effectuez le rendu que pour les URL dont vous avez vérifié qu’elles en ont besoin. Mettez en cache des pages représentatives pendant le développement de l’analyseur, bloquez les médias inutiles avec prudence et fixez des limites prudentes pour les contextes de navigateur et les pages. Augmentez progressivement la concurrence tout en surveillant la mémoire, le CPU, les délais d’expiration et les pages ouvertes.

Utilisez des budgets de délai d’expiration distincts pour la navigation et les attentes post-chargement. Réessayez en cas de défaillances transitoires du réseau ou du processus du navigateur, mais plafonnez le nombre de tentatives et évitez de réessayer indéfiniment en cas d’échecs déterministes, tels qu’un sélecteur supprimé. Fermez les pages en cas de succès ou d’exception, et recyclez les workers de navigateur défaillants. Ces contrôles empêchent JavaScript avec Scrapy de transformer une cible lente en contre-pression à l’échelle de l’ensemble du robot d’indexation.

Un guide sur le web scraping sans se faire bloquer constitue un complément interne utile pour les en-têtes, les taux de requêtes, les proxys et les diagnostics d’accès, qui sont distincts de la justesse du rendu.

Dépannage du contenu manquant, lent ou bloqué

Symptôme

Vérifiez ensuite

Le champ existe dans le navigateur mais pas response.text

Recherchez la requête Fetch/XHR ou le script intégré avant d’ajouter le rendu

La réponse rendue présente toujours des données manquantes

Attendez un sélecteur spécifique au champ ou une condition réseau, puis vérifiez le sélecteur par rapport au DOM final

La première page fonctionne, mais les pages suivantes sont vides

Conservez les cookies, les jetons, l’état du contexte et les paramètres de pagination

Le robot de navigation ralentit au fil du temps

Comptez les pages et les contextes ouverts, vérifiez leur suppression et réduisez la concurrence de rendu

Timeouts répétés

Séparer la navigation des temps d’attente de l’application, capturer les diagnostics et limiter le nombre de tentatives

403 ou CAPTCHA

Considérez cela comme un problème de contrôle d’accès, et non comme la preuve d’un échec de JavaScript

Lorsqu’un sélecteur ne fonctionne plus, enregistrez le code HTML rendu et comparez-le à la session de navigateur utilisée pour les tests manuels. Si les réponses sont bloquées, examinez les codes d’état et les pages de vérification avant de modifier la logique d’attente. Ce cycle « symptôme-action » permet de fonder le débogage sur des preuves plutôt que d’ajouter des délais d’attente plus longs à chaque requête.

Points clés à retenir

  • Recherchez le code HTML brut, les points de terminaison JSON et l’état intégré de l’application avant d’ajouter un navigateur.
  • Activez « scrapy-playwright » uniquement pour les requêtes nécessitant une exécution, puis continuez à utiliser les sélecteurs Scrapy sur la réponse rendue.
  • Attendez que l’état de la page soit observable, limitez les délais d’expiration et fermez chaque page incluse ou chaque contexte dédié.
  • Considérez le rendu, la mise à l’échelle et l’accès anti-bot comme des problèmes techniques distincts nécessitant des diagnostics différents.

FAQ

Un spider Scrapy peut-il mélanger des requêtes standard et des requêtes rendues en JavaScript ?

Oui. Conservez les objets scrapy.Request sur le téléchargeur par défaut et n'ajoutez les métadonnées de rendu qu'aux URL nécessitant un navigateur. Les deux types de requêtes peuvent alimenter le même pipeline d'éléments. Ce modèle sélectif préserve le débit de Scrapy pour les pages statiques tout en permettant à un sous-ensemble plus restreint d'utiliser l'exécution via le navigateur.

Comment puis-je exécuter du code JavaScript personnalisé ou cliquer sur un élément avec scrapy-playwright ?

Utilisez une entrée de méthode de page pour les opérations pouvant s’exécuter avant le rappel, telles qu’un clic ou un evaluate appel. Pour la logique conditionnelle ou les valeurs renvoyées par du JavaScript personnalisé, incluez l’objet de page actif dans les métadonnées de réponse et utilisez un callback asynchrone. Fermez toujours cette page dans finally, y compris lorsque l’extraction génère une exception.

Comment capturer une capture d’écran ou inspecter le code HTML rendu lors du débogage ?

Incluez l’objet Page Playwright dans la réponse, puis appelez page.screenshot(path="debug.png", full_page=True) à l’intérieur d’un rappel asynchrone. Enregistrez await page.content() avec la capture d’écran lorsque le comportement du sélecteur n’est pas clair. Utilisez des noms de fichiers uniques contenant un identifiant de requête, et évitez de laisser ces diagnostics activés à grande échelle, car les captures d’écran génèrent une surcharge en termes d’E/S et de stockage.

Un navigateur sans interface utilisateur empêche-t-il les réponses 403, les CAPTCHA ou les interdictions d’accès ?

Non. Un navigateur sans interface utilisateur exécute du JavaScript, mais les sites peuvent toujours évaluer la réputation de l’adresse IP, le débit de requêtes, les cookies, le comportement du compte, les empreintes du navigateur et les habitudes de navigation. Analysez séparément le statut renvoyé et le contenu du défi. Le rendu peut rendre la page fonctionnelle sans pour autant rendre le trafic fiable ou autorisé.

Scrapy-Playwright peut-il fonctionner dans Docker ou dans un environnement CI ?

Oui. Le conteneur doit inclure le binaire du navigateur sélectionné et ses dépendances du système d’exploitation, et sa version de Playwright doit correspondre au paquet Python que vous installez. Fixez les dépendances, testez l’image sans serveur d’affichage, prévoyez suffisamment de mémoire partagée et effectuez un petit test de fonctionnement (smoke test) avec rendu avant de lancer l’araignée complète.

Conclusion : JavaScript avec Scrapy en pratique

La méthode fiable pour gérer les pages dynamiques consiste à passer du plus simple au plus complexe. Comparez la réponse brute de Scrapy avec le DOM rendu, identifiez la requête ou l’état intégré qui fournit les champs manquants, et analysez les données structurées directement dès que possible. Ce n’est qu’ensuite que vous devriez recourir à l’exécution dans un navigateur.

Lorsque le rendu est nécessaire, utilisez-le de manière sélective. Attendez un état lié aux données, et non un délai arbitraire ; ne conservez le contexte de session que lorsque le flux de travail l’exige ; et fermez les pages et les contextes de manière prévisible. En production, la concurrence des navigateurs, les limites de délai d’expiration, les tentatives de réessai et les métriques de ressources importent autant que les sélecteurs. Un navigateur qui s’affiche correctement sur un ordinateur portable peut tout de même devenir le goulot d’étranglement du robot d’indexation ou se heurter à des contrôles d’accès à grande échelle.

Si le blocage au niveau de la couche de requêtes devient la contrainte, plutôt que la logique d’interaction, WebScrapingAPI propose une API de scraping qui renvoie du HTML brut tout en gérant en arrière-plan la rotation des proxys et les CAPTCHA. Cela vous permet de conserver le pipeline d’analyse et de traitement des éléments de Scrapy tout en déchargeant la couche de récupération instable. Commencez par le chemin le plus simple que vous puissiez vérifier, instrumenter-le, puis n’ajoutez de la complexité liée au navigateur que lorsque les résultats indiquent que c’est nécessaire.

À propos de l'auteur

Mihai Maxim, Développeur Full Stack @ WebScrapingAPI

Mihai Maxim

Développeur Full Stack

Mihai Maxim est développeur Full Stack chez WebScrapingAPI ; il participe à l'ensemble du produit et contribue à la création d'outils et de fonctionnalités fiables pour la plateforme.

Web scraping avec AWS Lambda : guide pour Python et Java 2026
Guides

Web scraping avec AWS Lambda : guide pour Python et Java 2026

En bref : le web scraping avec AWS Lambda fonctionne mieux lorsque chaque invocation est courte, bien délimitée et peut faire l'objet d'une nouvelle tentative de manière indépendante. Commencez par utiliser les requêtes HTTP directes, AWS SAM et S3, puis ajoutez SQS, des conteneurs, le rendu dans un navigateur, des proxys ou une couche de récupération gérée uniquement lorsque la charge de travail démontre qu'elle en a besoin.

Suciu Dan33 min read
Lire l'article
Comment utiliser GoSpider : exploration, nettoyage des URL et extraction de données
Guides

Comment utiliser GoSpider : exploration, nettoyage des URL et extraction de données

En bref : GoSpider est un robot d'exploration en ligne de commande destiné à découvrir des URL, et non un outil complet de collecte de données structurées. Ce guide d'utilisation de GoSpider présente comment effectuer une exploration limitée, gérer correctement les résultats, transférer les données de Colly vers un fichier CSV, ainsi qu'une procédure de diagnostic pour les réponses 403 ou les pages nécessitant un rendu JavaScript.

Suciu Dan24 min read
Lire l'article
Comment récupérer les données de Redfin : Guide Python des données immobilières
Guides

Comment récupérer les données de Redfin : Guide Python des données immobilières

TL;DR : Redfin expose des points d'extrémité d'API cachés qui renvoient du JSON structuré pour les listes de propriétés, ce qui permet d'ignorer complètement l'analyse HTML fragile. Ce guide vous accompagne dans la construction d'un scraper Python qui extrait les données de location et de vente, effectue des recherches par emplacement, surveille les nouvelles inscriptions via des sitemaps XML et exporte des résultats propres au format CSV ou JSON.

Suciu Dan15 min read
Lire l'article

Commencez à créer

Prêt à faire évoluer votre système de collecte de données ?

Rejoignez plus de 2 000 entreprises qui utilisent WebScrapingAPI pour extraire des données Web à l'échelle de l'entreprise, sans aucun coût d'infrastructure.