Exploration des Capacités de Scrapy pour la Collecte de Données Web et le Stockage Persistant

Le framework Scrapy est un outil puissant pour l'extraction de données à partir de sites web, offrant une flexibilité pour collecter diverses informations, des images aux données financières complexes. Cet article explore des applications pratiques de Scrapy, démontrant son utilisation pour l'extraction d'images, de données boursières et de taux de change, avec un accent sur la gestion de la concurrence et la persistance des données dans une base de données MySQL.

Collecte d'Images à Grande Échelle

L'extraction d'images depuis un site web est une tâche courante en web scraping. L'implémentation ci-dessous utilise Scrapy pour naviguer à travers les pages d'un site et télécharger un nombre défini d'images, tout en contrôlant la profondeur de la navigation.

Pour éviter de surcharger le serveur cible et pour une gestion efficace des ressources, des limites sont mises en place pour le nombre total de pages à visiter et le volume d'images à télécharger. Le framework Scrapy permet également de configurer des paramètres de concurrence pour optimiser la vitesse de récupération.


import scrapy

class ImageScraperSpider(scrapy.Spider):
   name = 'extracteur_images'
   
   # Paramètres de contrôle pour limiter la collecte
   pages_max = 5          # Nombre maximal de pages à parcourir
   images_max = 142       # Nombre maximal d'images à télécharger
   compteur_images = 0    # Compteur d'images actuellement téléchargées
   page_actuelle = 1      # Suivi de la page en cours
   
   start_urls = ['https://p.weather.com.cn/tqxc/index.shtml'] # URL de départ à adapter

   def parse(self, response):
       # Localisation des URLs d'images via sélecteurs CSS
       urls_images = response.css('img::attr(src)').getall()

       for url_img in urls_images:
           if self.compteur_images >= self.images_max:
               break # Arrêt si le quota d'images est atteint

           self.compteur_images += 1
           yield {
               'url_image': url_img # L'Item 'url_image' sera traité par un Pipeline d'images
           }

       # Logique pour naviguer vers la page suivante
       if self.page_actuelle < self.pages_max and self.compteur_images < self.images_max:
           self.page_actuelle += 1
           url_prochaine_page = f'https://p.weather.com.cn/tqxc/index_{self.page_actuelle}.shtml'
           yield response.follow(url_prochaine_page, self.parse)

   def closed(self, reason):
       self.logger.info(f'Total images extraites : {self.compteur_images}')

# Pour la configuration multi-threading (dans settings.py de Scrapy) :
# CONCURRENT_REQUESTS = 16  # Nombre de requêtes concurrentes maximales
# DOWNLOAD_DELAY = 0.5      # Délai entre les requêtes pour éviter la surcharge
   

La gestion de la concurrence est cruciale pour une collecte efficace. En ajustant les paramètres CONCURRENT_REQUESTS et DOWNLOAD_DELAY dans les réglages de Scrapy (settings.py), il est possible d'optimiser la vitesse d'extraction tout en respectant la politique d'utilisation des serveurs cibles.

Collecte et Persistance de Données Boursières

L'extraction de données financières, telles que les cours boursiers, nécessite souvent de traiter des structures de données complexes comme le JSON. Scrapy, combiné à l'utilisation d'Item pour structurer les données et de Pipeline pour la persistance, offre une solution robuste.

Les données sont d'abord extraites d'une réponse de type JSONP (JSON avec padding), puis converties en objets Python. Chaque ensemble de données de stock est ensuite mappé à un StockItem, qui est transmis aux Pipelines pour le stockage.


import scrapy
import json
from scrapy import Item, Field

class StockItem(Item):
   identifiant = Field()         # Code du titre boursier
   nom_titre = Field()           # Nom de l'entreprise
   cours_actuel = Field()        # Prix actuel de l'action
   variation_prix = Field()      # Changement de prix (positif/négatif)
   volume_echanges = Field()     # Volume des transactions
   montant_total_echanges = Field() # Montant total des transactions
   pourcentage_variation = Field() # Pourcentage de variation du prix

class StockScraperSpider(scrapy.Spider):
   name = 'extracteur_actions'
   start_urls = ['http://push2.eastmoney.com/api/qt/clt/count'] # Exemple d'URL, à adapter
   
   def parse(self, response):
       # Le contenu est souvent au format JSONP, nécessitant un pré-traitement
       try:
           json_str_start = response.text.index('(') + 1
           json_str_end = response.text.rindex(')')
           json_data_raw = response.text[json_str_start:json_str_end]
           data = json.loads(json_data_raw)
       except (ValueError, IndexError, json.JSONDecodeError) as e:
           self.logger.error(f"Erreur de traitement JSON: {e} dans {response.url}")
           return

       if 'data' in data and 'diff' in data['data']:
           for detail_action in data['data']['diff']:
               item = StockItem()
               item['identifiant'] = detail_action.get('f12')
               item['nom_titre'] = detail_action.get('f14')
               item['cours_actuel'] = detail_action.get('f2')
               item['variation_prix'] = detail_action.get('f4')
               item['volume_echanges'] = detail_action.get('f5')
               item['montant_total_echanges'] = detail_action.get('f6')
               item['pourcentage_variation'] = detail_action.get('f10')
               yield item
       else:
           self.logger.warning("Structure de données boursières inattendue ou champ 'diff' manquant.")

   

L'intégration de ces données dans une base de données relationnelle comme MySQL via un Pipeline Scrapy permet de stocker, interroger et analyser efficacement les informations financières collectées. Cela transforme les données brutes extraitse en une ressource structurée et utilisable.

Extraction de Taux de Change avec XPath et Stockage MySQL

Pour les sites web où les données sont présentées dans des tableaux HTML classsiques, l'utilisation de sélecteurs XPath est particulièrement efficace. Cette méthode est illustrée par l'extraction des taux de change à partir du site de la Banque de Chine.

Chaque ligne du tableau est itérée, et des expressions XPath précises sont utilisées pour cibler les cellules (<td>) correspondant à des informations spécifiques telles que la devise, les prix d'achat/vente, et la date de publication. Ces données sont ensuite encapsulées dans un ForeignExchangeItem.


import scrapy
from scrapy import Item, Field

class ForeignExchangeItem(Item):
   devise = Field()            # Nom de la devise
   prix_achat = Field()        # Prix d'achat (moyen)
   prix_achat_comptant = Field() # Prix d'achat au comptant
   prix_vente = Field()        # Prix de vente (moyen)
   prix_vente_comptant = Field() # Prix de vente au comptant
   prix_conversion = Field()   # Prix de conversion
   date_publication = Field()  # Date de publication du taux
   heure_publication = Field() # Heure de publication du taux

class ExchangeRateSpider(scrapy.Spider):
   name = "extracteur_taux_change"
   allowed_domains = ["boc.cn"]
   start_urls = ["https://www.boc.cn/sourcedb/whpj/"] # URL de la Banque de Chine

   def parse(self, response):
       # Cibler les lignes du tableau des taux de change, en ignorant l'en-tête
       lignes_tableau = response.xpath('//table//tr[position()>1]')
       
       for ligne in lignes_tableau:
           item = ForeignExchangeItem()
           item['devise'] = ligne.xpath('./td[1]/text()').get()
           item['prix_achat'] = ligne.xpath('./td[2]/text()').get()
           item['prix_achat_comptant'] = ligne.xpath('./td[3]/text()').get()
           item['prix_vente'] = ligne.xpath('./td[4]/text()').get()
           item['prix_vente_comptant'] = ligne.xpath('./td[5]/text()').get()
           item['prix_conversion'] = ligne.xpath('./td[6]/text()').get()
           item['date_publication'] = ligne.xpath('./td[7]/text()').get()
           item['heure_publication'] = ligne.xpath('./td[8]/text()').get()
           yield item

   

Cette approche met en évidence la puissance de XPath pour la navigation et l'extraction de données précises à partir de structures HTML tabulaires, un scénario très courant dans le web scraping d'informations financières ou catalogues.

L'ensemble de ces exemples illustre la polyvalence de Scrapy pour adresser divers besoins de collecte de données. L'utilisation systématique des Items pour la structuration et des Pipelines pour la persistance dans des bases de données comme MySQL est une pratique fondamentale pour construire des solutions de scraping robustes et maintenables.

Étiquettes: Scrapy web scraping Data extraction xpath CSS selectors

Publié le 26 juillet à 15h15