Crawling Web Efficace avec les Index de Plan de Site

Introduction

Le crawling web est essentiel pour extraire des données de sites web, mais peut rapidement devenir inefficace s’il n’est pas correctement structuré. Une approche courante consiste à naviguer à travers des pages de catégories, paginer les listes de produits et récupérer les données. Cependant, cette méthode peut être gourmande en ressources et chronophage. Une alternative plus efficace consiste à exploiter les index de sitemap et les sitemaps pour accéder directement au contenu pertinent, comme les pages produits et leurs horodatages de dernière mise à jour.

Le problème du crawling traditionnel

Les robots d’indexation traditionnels suivent généralement cette séquence :

  1. Extraire les catégories principales de la page d’accueil.
  2. Parcourir chaque catégorie pour obtenir les sous-catégories.
  3. Paginer à travers les listes de produits dans chaque sous-catégorie.
  4. Extraire les détails des produits.

Bien que cette méthode assure une collecte exhaustive de données, elle présente plusieurs inconvénients :

  • Consommation élevée de ressources : Explorer des pages inutiles augmente la charge du serveur et l’utilisation de la bande passante.
  • Traitement plus lent : La récupération et l’analyse de chaque page prennent du temps, surtout pour les grands sites e-commerce.
  • Risque accru de blocage : Les sites web peuvent imposer des limites de débit ou bloquer les IP générant trop de requêtes.

Exploiter les index de sitemap pour un crawling efficace

La plupart des sites web fournissent un index de sitemap XML qui référence plusieurs fichiers sitemap. Ces sitemaps contiennent souvent des liens directs vers des pages importantes, comme les fiches produits, articles de blog ou autre contenu structuré. Les utiliser pour le crawling offre des avantages significatifs :

1. Accès plus rapide aux pages produits

Au lieu de parcourir les pages de catégories et de paginer les résultats, le crawler peut extraire directement les URL des produits depuis le sitemap. Cela élimine les requêtes superflues et accélère la récupération des données.

2. Suivi des mises à jour de contenu

Les sitemaps incluent souvent la balise <lastmod>, indiquant quand une page a été mise à jour. Cela permet au crawler de :

  • Récupérer uniquement les produits nouvellement mis à jour au lieu de reparser l’ensemble du site web.
  • Optimiser les appels API en se concentrant sur les données fraîches.

3. Risque réduit de détection

Puisque le crawler imite les moteurs de recherche en récupérant les sitemaps, il réduit la probabilité d’être identifié comme un bot ou bloqué par le site web.

Stratégie d’implémentation

  1. Récupérer l’index de sitemap : Identifier le sitemap racine (par exemple, https://example.com/sitemap_index.xml).
  2. Extraire les sitemaps individuels : Analyser l’index pour obtenir des liens vers les sitemaps de produits (par exemple, https://example.com/sitemap_products.xml).
  3. Traiter les URL de produits : Parcourir chaque sitemap, extraire les liens des produits et vérifier la date <lastmod>.
  4. Récupérer uniquement les produits mis à jour : Comparer la date de mise à jour avec l’horodatage du dernier crawl et traiter uniquement les éléments nouveaux ou modifiés.

Exemple : Analyser un sitemap en Python

Voici un script Python optimisé utilisant BeautifulSoup et requests pour récupérer et analyser un sitemap efficacement. La fonction scrape_products_links extrait les liens de produits depuis le sitemap XML d’un site web, récupère les détails des produits et les met à jour ou les insère dans une base de données. Elle récupère d’abord une liste de sitemaps à partir d’un index donné et enregistre le nombre trouvé. Pour chaque sitemap, elle récupère et analyse son contenu, extrayant les éléments et filtrant ceux se terminant par .html, supposés être des pages produits.

def scrape_products_links(self) -> list[str]:
    sitemaps = self.get_sitemaps_from_index("https://www.example.com/sitemap.xml")
    logger.info(f"Trouvé {len(sitemaps)} sitemaps.")
    links_crawled = []
    for sitemap in sitemaps:
        logger.info(f"Exploration du sitemap: {sitemap}")
        r = requests.get(sitemap)
        soup = self.b4s_parse(r.text, 'xml')
        links = soup.find_all('url')
        logger.info(f"Trouvé {len(links)} liens.")
        # Trouver toutes les balises <url> où <loc> se termine par .html
        links = [
            url for url in links
            if url.loc and url.loc.text.endswith(".html")
        ]
        logger.info(f"Trouvé {len(links)} liens de produits.")
        new_products = []
        old_products = []
        for link in links:
            product = Product()
            # Extraire les champs requis
            product.url = link.loc.text if link.loc else None
            # Ignorer si l'URL n'est pas trouvée
            if not product.url:
                continue
            hash = self.create_hash(product.url)
            p = Product.get_by_hash(hash=hash)
            product.website_updated_at = link.lastmod.text if link.lastmod else None
            # Ignorer si le produit existe déjà en base ou a été mis à jour
            if p:
                logger.info("Le produit existe déjà")
                logger.info(f"Date du produit sur le site: {product.website_updated_at}")
                logger.info(f"Date du produit en base: {p.website_updated_at}")
                if p.website_updated_at != product.website_updated_at:
                    p.website_updated_at = product.website_updated_at
                    old_products.append(p)
                continue
            else:
                links_crawled.append(product.url)
            product.hash = hash
            product.website = CategoryWebsite.BOTICINAL
            # Extraire le nom du produit depuis PageMap
            data_object = link.find("DataObject", {"type": "thumbnail"})
            if data_object:
                name_attr = data_object.find("Attribute", {"name": "name"})
                if name_attr:
                    product.name = name_attr["value"]
            image_loc = link.find("image:loc")
            if image_loc:
                product.image = self.get_clean_url(image_loc.text)
            product.crawler_updated_at = product.website_updated_at
            new_products.append(product)
            logger.info(f"Produit: {product}")
        
        if len(new_products) > 0:
            Product.bulk_insert(new_products)
            logger.info(f"{len(new_products)} produits insérés.")
        if len(old_products) > 0:
            Product.bulk_insert(old_products)
            logger.info(f"{len(old_products)} produits mis à jour.")
    return links_crawled

Conclusion

L’utilisation des index de sitemap pour le crawling web est une stratégie d’optimisation puissante. Elle permet une extraction de données plus rapide, une meilleure efficacité des ressources et une précision améliorée en se concentrant uniquement sur le contenu mis à jour. En implémentant cette approche, les entreprises peuvent maintenir des informations produits à jour tout en réduisant la charge inutile sur les sites web ciblés et leur propre infrastructure.

L’adoption de cette technique améliorera considérablement les performances de toute solution de crawling web, rendant la collecte de données à la fois plus intelligente et plus durable.