Prérequis
Avant de suivre cet article, vous devez avoir des connaissances de base en Python et avoir installé ce langage sur votre ordinateur. De plus, vous devrez installer les modules Requests et BeautifulSoup. Pour ce faire, exécutez la commande suivante dans votre invite de commande ou votre terminal :
$ pip install requests bs4
Pour la deuxième partie de cet article, où nous allons créer un exemple de robot d'indexation à l'aide de Scrapy, vous devrez installer le framework Scrapy. Les créateurs de ce framework recommandent vivement d'installer Scrapy dans un environnement virtuel dédié, afin d'éviter tout conflit avec les paquets de votre système.
Je vous suggère d'installer virtualenv et virtualenvwrapper pour créer un environnement Python isolé. Veuillez noter qu'il existe une version de virtualenvwrapper pour Windows appelée virtualenvwrapper-win.
Vous devrez également installer pipx via pip pour installer virtualenv.
$ python -m pip install --user pipx
$ python -m pipx ensurepath
Une fois que vous avez créé un environnement Python isolé, vous pouvez installer Scrapy à l'aide de la commande suivante.
$ pip install Scrapy
Vous trouverez le guide d'installation de Scrapy ici.
Qu'est-ce qu'un robot d'indexation ?
Le crawling et le scraping sont des concepts liés mais distincts. Le scraping désigne le processus global d'extraction de données d'un site web. Le crawling est la tâche spécifique consistant à parcourir automatiquement les pages web pour trouver les URL à scraper.
Un robot d'indexation commence avec une liste d'URL à parcourir, appelée « seed ». À mesure qu'il parcourt chaque URL, il recherche des liens dans le code HTML et les filtre selon des critères spécifiques. Tout nouveau lien trouvé est ajouté à une file d'attente pour un traitement ultérieur. Le code HTML extrait ou les informations spécifiées sont ensuite transmis à un autre pipeline pour un traitement plus approfondi.
Lors de la création d'un robot d'indexation, il est important de garder à l'esprit que toutes les pages d'un site web ne seront pas visitées. Le nombre de pages visitées dépend du budget alloué au robot, de la profondeur d'exploration ou du temps alloué à l'exécution.
De nombreux sites web disposent d'un fichier robots.txt qui indique les parties du site pouvant être explorées et celles à éviter. De plus, certains sites web possèdent un fichier sitemap.xml qui est plus explicite que le robots.txt : il indique précisément aux robots quelles pages doivent être explorées et fournit des métadonnées supplémentaires pour chaque URL.
Les robots d'indexation sont couramment utilisés à des fins diverses :
- Les outils d'analyse SEO collectent des métadonnées telles que le temps de réponse et le statut de réponse, en plus du code HTML, afin de détecter les pages cassées et les liens entre différents domaines pour collecter des backlinks.
- Les outils de surveillance des prix explorent les sites de commerce électronique pour trouver les pages de produits et extraire des métadonnées, en particulier les prix. Les pages de produits sont ensuite revisitées périodiquement.
- Les moteurs de recherche, tels que Googlebot, Bingbot et Yandex Bot, collectent tout le code HTML d'une partie importante du Web et utilisent ces données pour le rendre consultable.
Plus loin dans cet article, nous comparerons deux approches différentes pour créer un robot d'indexation en Python. La première approche consiste à utiliser la bibliothèque Requests pour effectuer des requêtes HTTP et BeautifulSoup pour analyser le contenu HTML. La deuxième approche consiste à utiliser un framework de robot d'indexation. Nous utiliserons Scrapy.
Utilisation des bibliothèques Requests et BeautifulSoup
Le module Requests en Python est un outil puissant pour effectuer des requêtes HTTP. Pour l'utiliser dans le cadre du crawling Web, vous pouvez commencer par importer le module et envoyer une requête vers une URL spécifique. Par exemple :
url = 'https://amazon.com/s?k=baby+products'
response = requests.get(url)
Une fois que vous avez la réponse, vous pouvez extraire tous les liens du contenu HTML à l'aide de BeautifulSoup. Par exemple :
import json
from urllib.parse import urljoin
from bs4 import BeautifulSoup
html = response.text
links = []
soup = BeautifulSoup(html, 'html.parser')
for link in soup.find_all('a'):
path = link.get('href')
if path and path.startswith('/'):
path = urljoin(url, path)
links.append(path)
print(json.dumps(links, sort_keys = True, indent = 2))
Vous pouvez ensuite parcourir les liens et effectuer des requêtes vers ceux-ci, en répétant le processus jusqu'à ce que vous ayez visité toutes les pages que vous souhaitez explorer. Voici une fonction récursive qui fonctionne exactement de cette manière :
import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup
import logging
logging.basicConfig(
format='%(asctime)s %(levelname)s:%(message)s',
level=logging.INFO)
url = 'https://amazon.com/s?k=baby+products'
visited = []
def crawl(url):
logging.info(f'Crawling: {url}')
visited.append(url)
html = ''
try:
html = requests.get(url).text
except Exception:
logging.exception(f'Failed to crawl: {url}')
return
soup = BeautifulSoup(html, 'html.parser')
# here you can extract and store useful data from the page
for link in soup.find_all('a'):
path = link.get('href')
if path and path.startswith('/'):
path = urljoin(url, path)
if path not in visited:
crawl(path)
crawl(url)
La fonction enregistre une ligne pour chaque URL visitée.
2023-01-16 09:20:51,681 INFO:Crawling: https://amazon.com/s?k=baby+products
2023-01-16 09:20:53,053 INFO:Crawling: https://amazon.com/ref=cs_503_logo
2023-01-16 09:20:54,195 INFO:Crawling: https://amazon.com/ref=cs_503_link
2023-01-16 09:20:55,131 INFO:Crawling: https://amazon.com/dogsofamazon/ref=cs_503_d
2023-01-16 09:20:56,549 INFO:Crawling: https://www.amazon.com/ref=nodl_?nodl_android
2023-01-16 09:20:57,071 INFO:Crawling: https://www.amazon.com/ref=cs_503_logo
2023-01-16 09:20:57,690 INFO:Crawling: https://www.amazon.com/ref=cs_503_link
2023-01-16 09:20:57,943 INFO:Crawling: https://www.amazon.com/dogsofamazon/ref=cs_503_d
2023-01-16 09:20:58,413 INFO:Crawling: https://www.amazon.com.au/ref=nodl_&nodl_android
2023-01-16 09:20:59,555 INFO:Crawling: None
2023-01-16 09:20:59,557 ERROR:Failed to crawl: None
Bien que le code d'un robot d'indexation web basique puisse sembler simple, de nombreux défis doivent être surmontés pour réussir à explorer l'intégralité d'un site web. Parmi ceux-ci, on peut citer :
- La logique de l'URL de téléchargement ne dispose pas d'un mécanisme de réessai et la file d'attente d'URL n'est pas très efficace lorsque le nombre d'URL est élevé.
- Le robot d'indexation ne s'identifie pas et ignore le fichier robots.txt.
- Le robot d'indexation est lent et ne prend pas en charge le parallélisme. L'indexation de chaque URL prend environ une seconde, et le robot attend une réponse avant de passer à l'URL suivante.
- La logique d'extraction des liens ne prend pas en charge la normalisation des URL en supprimant les paramètres de chaîne de requête, ne gère pas les URL d'ancrage/de fragment relatives (telles que href="#anchor") et ne permet pas de filtrer les URL par domaine ni d'exclure les requêtes vers des fichiers statiques.
Dans la section suivante, nous verrons comment Scrapy résout ces problèmes et facilite l'extension des fonctionnalités du robot d'indexation pour des cas d'utilisation personnalisés.
Comment créer un robot d'indexation en Python à l'aide du framework Scrapy
Scrapy est un framework puissant permettant de créer des robots d'indexation en Python. Il offre un moyen intégré de suivre les liens et d'extraire des informations des pages web. Vous devrez créer un nouveau projet Scrapy et un spider pour définir le comportement de votre robot d'indexation.
Avant de commencer à explorer un site web comme Amazon, il est important de vérifier le fichier robots.txt du site pour voir quels chemins d'URL sont autorisés. Scrapy lit automatiquement ce fichier et le suit lorsque le paramètre ROBOTSTXT_OBEY est défini sur true, ce qui est la valeur par défaut pour les projets créés à l'aide de la commande Scrapy `startproject`.
Pour créer un nouveau projet Scrapy, vous devez exécuter la commande suivante :
$ scrapy startproject amazon_crawler
Cette commande générera un projet présentant la structure suivante :
amazon_crawler/
├── scrapy.cfg
└── amazon_crawler
├── __init__.py
├── items.py
├── middlewares.py
├── pipelines.py
├── settings.py
└── spiders
├── __init__.py
Pour créer un spider, utilisez la commande `genspider` de l'interface CLI de Scrapy. La commande a la définition suivante :
$ scrapy genspider [options] <name> <domain>
Pour générer un spider pour ce crawler, nous pouvons exécuter :
$ cd amazon_crawler
$ scrapy genspider baby_products amazon.com
Cela devrait créer un fichier nommé `baby_products.py` dans le dossier nommé `spiders` et générer le code suivant :
import scrapy
class BabyProductsSpider(scrapy.Spider):
name = 'wikipedia'
allowed_domains = ['en.wikipedia.com']
start_urls = ['http://en.wikipedia.com/']
def parse(self, response):
pass
Scrapy propose également une variété de classes de spider prédéfinies, telles que CrawlSpider, XMLFeedSpider, CSVFeedSpider et SitemapSpider. La classe CrawlSpider, qui s’appuie sur la classe de base Spider, inclut un attribut « rules » supplémentaire permettant de définir comment naviguer sur un site web. Chaque règle utilise un LinkExtractor pour déterminer quels liens doivent être extraits de chaque page.
Pour notre cas d'utilisation, nous devons faire hériter notre classe Spider de CrawlSpider. Nous devrons également créer une règle LinkExtractor qui indique au crawler d'extraire uniquement les liens de la pagination d'Amazon. N'oubliez pas que notre objectif était de collecter des données sur tous les produits pour bébés d'Amazon ; nous ne souhaitons donc pas suivre tous les liens que nous trouvons sur la page.
Ensuite, nous devons créer deux autres méthodes dans notre classe, `parse_item` et `parse_product`. `parse_item` sera fournie en tant que fonction de rappel à notre règle LinkExtractor et sera appelée pour chaque lien extrait. `parse_product` analysera chaque produit… ¯\_(ツ)_/¯
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from bs4 import BeautifulSoup
class BabyProductsSpider(CrawlSpider):
name = 'baby_products'
allowed_domains = ['amazon.com']
start_urls = ['https://amazon.com/s?k=baby+products']
rules = (
Rule(
LinkExtractor(
restrict_css='.s-pagination-strip'
),
callback='parse_item',
follow=True),
)
def parse_item(self, response):
soup = BeautifulSoup(response.text, 'html.parser')
products = soup.select('div[data-component-type="s-search-result"]')
data = []
for product in products:
parsed_product = self.parse_product(product)
if (parsed_product != 'error'):
data.append(parsed_product)
return {
'url': response.url,
'data': data
}
def parse_product(self, product):
try:
link = product.select_one('a.a-text-normal')
price = product.select_one('span.a-price > span.a-offscreen').text
return {
'product_url': link['href'],
'name': link.text,
'price': price
}
except:
return 'error'
Pour lancer le crawler, vous pouvez exécuter :
$ scrapy crawl baby_products
Vous verrez de nombreux logs s'afficher dans la console (vous pouvez spécifier un fichier de log avec `--logfile [log_file_name]`).
J'ai utilisé Amazon Search comme exemple pour illustrer les bases de la création d'un robot d'indexation en Python. Cependant, le robot ne trouve pas beaucoup de liens à suivre et n'est pas adapté à un cas d'utilisation spécifique des données. Si vous cherchez à extraire des données spécifiques d'Amazon Search, vous pouvez envisager d'utiliser notre API Amazon Product Data. Nous avons créé des analyseurs personnalisés pour les pages de recherche, de produit et de catégorie d'Amazon, et celle-ci renvoie des données au format JSON prêtes à être utilisées dans votre application.
Pourquoi est-il préférable d'utiliser un service de scraping professionnel plutôt qu'un robot d'indexation ?
Si le crawling Web peut être un outil utile pour extraire des données d'Internet, sa mise en place peut également s'avérer longue et complexe. De plus, le scraping Web peut enfreindre les conditions d'utilisation de certains sites Web et entraîner le blocage de votre adresse IP, voire des poursuites judiciaires à votre encontre.
En revanche, les services de scraping professionnels utilisent des techniques et des technologies avancées pour contourner les mesures anti-scraping et extraire des données sans être détectés. Ils gèrent également la maintenance et la mise à l'échelle de l'infrastructure de scraping, ce qui vous permet de vous concentrer sur l'analyse et l'utilisation des données. De plus, ils offrent un niveau supérieur de précision et d'exhaustivité des données, car ils sont capables de traiter des cas d'utilisation d'extraction de données plus avancés et de gérer des tâches de scraping à grande échelle.
Résumé
En conclusion, si le crawling peut être un outil utile pour extraire des données d'Internet, sa mise en place peut s'avérer longue et complexe. De plus, le crawling peut enfreindre les conditions d'utilisation de certains sites web et entraîner le blocage de votre adresse IP, voire des poursuites judiciaires à votre encontre. Par conséquent, pour les tâches de scraping plus avancées et à grande échelle, il est préférable de faire appel à un service de scraping professionnel.
Si vous recherchez une alternative au crawling que vous effectuez vous-même, pensez à utiliser WebScrapingAPI. WebScrapingAPI est un service de scraping web professionnel qui vous permet d'extraire facilement des données de sites web sans avoir à créer et à maintenir votre propre outil de scraping.
Il s'agit d'une solution rapide, fiable et économique qui convient aux entreprises de toutes tailles.
Pourquoi ne pas l'essayer dès aujourd'hui ? C'est gratuit et nous proposons un essai de 14 jours sans carte bancaire.




