Scrapy est un framework Python puissant et rapide pour extraire des données de sites web. Ce guide couvre les étapes essentielles pour l'utiliser, de l'installation à l'extraction avancée.
Installation de Scrapy
Scrapy dépend de Twisted, qui est généralement distribué sous forme de package wheel. L'installation se fait donc en plusieurs étapes. Tout d'abord, intsallez l'outil wheel, puis installez Twisted à l'aide du lien correspondant à votre système. Enfin, installez Scrapy lui-même.
pip install wheel
pip install https://download.lfd.uci.edu/pythonlibs/q5gtlas7/Twisted-19.2.0-cp37-cp37m-win_amd64.whl
pip install scrapy
Note : Le fichier .whl pour Twisted doit correspondre à la version de votre Python et à l'architecture de votre système d'exploitation.
Initialisation d'un projet
Pour démarrer un nouveau projet, utilisez la commande startproject. Cela génère la structure de répertoire par défaut.
scrapy startproject mon_projet
Développement d'un spider
Un spider est la classe qui définit comment parcourir un site et extraire les données. Créons un exemple pour extraire des informations de livres depuis une bibliothèque en ligne.
import scrapy
from bs4 import BeautifulSoup
from ..items import BookItem
class BookSpider(scrapy.Spider):
name = 'livres'
allowed_domains = ['bibliotheque-en-ligne.fr']
def start_requests(self):
for page in range(3):
url = f'https://bibliotheque-en-ligne.fr/populaires?offset={page * 20}'
yield scrapy.Request(url=url, callback=self.parse_list)
def parse_list(self, response):
soup = BeautifulSoup(response.text, 'html.parser')
entries = soup.select('div.book-card')
for entry in entries:
title = entry.select_one('h3.title').text.strip()
details = entry.select_one('p.meta').text.strip()
rating = entry.select_one('span.note').text.strip()
item = BookItem()
item['titre'] = title
item['details'] = details
item['note'] = rating
yield item
Définition des items
La classe Item définit la structure des données que nous voulons collecter.
import scrapy
class BookItem(scrapy.Item):
titre = scrapy.Field()
details = scrapy.Field()
note = scrapy.Field()
Configuration du spider
Le fichier settings.py contient les configurations critiques, comme le User-Agent pour simuler un navigateur et le respect du robots.txt.
BOT_NAME = 'mon_projet'
SPIDER_MODULES = ['mon_projet.spiders']
NEWSPIDER_MODULE = 'mon_projet.spiders'
# Désactiver le respect du robots.txt pour l'extraction
ROBOTSTXT_OBEY = False
# Définir un User-Agent réaliste
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
Exécution du spider
Le spider peut être lancé directement depuis la ligne de commande ou via un script Python.
# En ligne de commande
scrapy crawl livres
# Via un script main.py
from scrapy import cmdline
cmdline.execute(['scrapy', 'crawl', 'livres'])
Exportation des résultats
Scrapy offre plusieurs façons d'exporter les données extraites.
Vers un fichier CSV : Ajoutez ces paramètres dans settings.py.
FEED_URI = './resultats/%(name)s.csv'
FEED_FORMAT = 'CSV'
FEED_EXPORT_ENCODING = 'utf-8-sig'
Vers un fichier Excel : Cela nécessite la mise en place d'un Item Pipeline. Activez le pipeline dans settings.py.
ITEM_PIPELINES = {
'mon_projet.pipelines.ExcelPipeline': 300,
}
Ensuite, implémentez le pipeline dans pipelines.py.
import openpyxl
class ExcelPipeline:
def open_spider(self, spider):
self.classeur = openpyxl.Workbook()
self.feille = self.classeur.active
self.feille.append(['Titre', 'Détails', 'Note'])
def process_item(self, item, spider):
ligne = [item['titre'], item['details'], item['note']]
self.feille.append(ligne)
return item
def close_spider(self, spider):
self.classeur.save('./livres_exportes.xlsx')
Paramètres supplémentaires
Le délai entre les reequêtes peut être contrôlé pour être plus poli envers le serveur.
# Délai aléatoire entre 2 et 5 secondes
DOWNLOAD_DELAY = 3
RANDOMIZE_DOWNLOAD_DELAY = True
Concepts avancés et callback
Pour extraire des données qui nécessitent de naviguer sur plusieurs pages (par exemple, une page de liste puis une page de détail par élément), on utilise le système de callback.
class JobSpider(scrapy.Spider):
name = 'emplois'
allowed_domains = ['site-emploi.com']
def parse(self, response):
# Traitement de la page de liste des entreprises
soup = BeautifulSoup(response.text, 'html.parser')
for link in soup.select('a.company-link'):
company_url = response.urljoin(link['href'])
yield scrapy.Request(company_url, callback=self.parse_company)
def parse_company(self, response):
# Traitement de la page de détails d'une entreprise
soup = BeautifulSoup(response.text, 'html.parser')
company_name = soup.select_one('h1#main-title').text.strip()
# ... extraction des offres d'emploi ...
for job in soup.select('div.job-posting'):
item = JobItem()
item['entreprise'] = company_name
item['poste'] = job.select_one('h3').text.strip()
item['lieu'] = job.select_one('.location').text.strip()
yield item
Ce modèle ouvre la porte à des requêtes plus complexes, comme la gestion des cookies, l'intégration avec Selenium pour le rendu JavaScript, ou la construction d'architectures distribuées.