Le guide ultime sur la façon de commencer le Web Scraping avec Elixir

Suciu Dan le 18 octobre 2022

Introduction

Le web scraping est le processus d'extraction de données à partir de sites accessibles au public tels que les forums, les sites de médias sociaux, les sites d'information, les plateformes de commerce électronique, etc. Pour vous donner un aperçu de ce que vous allez construire aujourd'hui, cet article décrit la création d'un scraper web en Elixir.

Si la définition du web scraping n'est pas encore claire pour vous, considérons l'enregistrement d'une image à partir d'un site comme du web scraping manuel. Si vous souhaitez enregistrer toutes les images d'un site à la main, en fonction de la complexité du site, cela peut prendre des heures, voire des jours. 

Vous pouvez automatiser ce processus en créant un scraper web.

Vous vous demandez peut-être quels sont les cas d'utilisation d'un scraper web. Voici les cas les plus courants :

Suivi de l'actualité

Vous pouvez extraire les dernières nouvelles de votre site d'information financière préféré, exécuter un algorithme d'analyse des sentiments et savoir dans quoi investir quelques minutes avant que le marché ne démarre et ne bouge.

Perspectives des médias sociaux

Vous pouvez récupérer les commentaires de vos pages de médias sociaux et analyser ce dont vos abonnés parlent et ce qu'ils pensent de votre produit ou service.

Surveillance des prix

Si votre passion est de collectionner des consoles et des jeux vidéo mais que vous ne voulez pas dépenser une fortune pour la dernière PS5, vous pouvez créer un scraper web qui récupère les listes eBay et vous envoie une notification lorsqu'une console bon marché est sur le marché.

Formation à l'apprentissage automatique

Si vous souhaitez créer une application mobile capable d'identifier la race d'un chat sur n'importe quelle photo, vous aurez besoin d'un grand nombre de données d'entraînement. Au lieu d'enregistrer manuellement des centaines de milliers de photos de chats pour entraîner le modèle, vous pouvez utiliser un scraper web pour le faire automatiquement.

Nous construirons notre scraper web en Elixir, un langage de programmation construit au-dessus d'Erlang, créé par José Valim, membre de l'équipe principale de Ruby on Rails. Le langage de programmation emprunte la simplicité syntaxique de Ruby et la combine avec la capacité d'Erlang à construire des systèmes à faible latence, distribués et tolérants aux pannes.

Exigences

Avant d'écrire la première ligne de code, assurez-vous qu'Elixir est installé sur votre ordinateur. Téléchargez le programme d'installation correspondant à votre système d'exploitation et suivez les instructions de la page d'installation

Pendant l'installation, vous remarquerez que le langage de programmation Erlang est également requis. Gardez à l'esprit qu'Elixir s'exécute dans la VM Erlang et que vous avez donc besoin des deux.

Pour commencer

Dans cet article, vous apprendrez à créer un scraper web en Elixir, à récupérer les produits d'eBay pour les listes PS5 et à stocker localement les données extraites (nom, url, prix).

Inspection de la cible

Il est temps d'inspecter les résultats de la recherche sur la page eBay et de collecter quelques sélecteurs.

Allez sur ebay.com, entrez le terme PS5 dans la zone de recherche et cliquez sur le bouton de recherche. Une fois la page des résultats de la recherche chargée, ouvrez l'outil Inspecter dans votre navigateur (cliquez avec le bouton droit de la souris n'importe où sur la page et sélectionnez Inspecter).

Vous devez rassembler les sélecteurs suivants :

  • Liste des produits Article
  • URL du produit
  • Nom du produit
  • Prix du produit

Utilisez l'outil de sélection d'éléments et recherchez la liste des articles (ul) et l'article (li) :

blog-image

En utilisant ces deux éléments, vous pouvez extraire les classes nécessaires au crawler pour l'extraction des données :

  • .srp-results .s-item les éléments enfants de l'élément liste de produits (ul)
  • .s-item__title span le titre du produit
  • .s-item__link le lien du produit
  • .s-item__price le prix du produit

Création du projet

Créons un projet Elixir à l'aide de la commande mix :

mix new elixir_spider --sup

L'option --sup génère un squelette d'application OTP comprenant un arbre de supervision, une fonctionnalité nécessaire pour une application qui gère plusieurs processus simultanés comme un crawler.

Création du dossier temporaire

Changer le répertoire courant pour la racine du projet :

cd elixir_spider

Créer le répertoire temporaire :

mkdir temp

Nous utilisons ce répertoire pour stocker les éléments récupérés.

Ajouter les dépendances

Une fois le projet créé, vous devez ajouter les deux dépendances :

  • Crawly est un cadre d'application pour l'exploration de sites et l'extraction de données structurées.
  • Floki est un analyseur HTML qui permet de rechercher des nœuds à l'aide de sélecteurs CSS.

Ouvrez le fichier mix.exs et ajoutez les dépendances dans le bloc deps :

defp deps do
[
{:crawly, "~> 0.14.0"},
{:floki, "~> 0.33.1"}
]
end

Récupérez les dépendances en exécutant cette commande :

mix deps.get

Créer la configuration

Créez le fichier config/config.exs et collez-y cette configuration :

import Config

config :crawly,
closespider_timeout: 10,
concurrent_requests_per_domain: 8,
closespider_itemcount: 100,

middlewares: [
Crawly.Middlewares.DomainFilter,
Crawly.Middlewares.UniqueRequest,
{Crawly.Middlewares.UserAgent, user_agents: ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0"]}
],
pipelines: [
{Crawly.Pipelines.Validate, fields: [:url, :title, :price]},
{Crawly.Pipelines.DuplicatesFilter, item_id: :title},
Crawly.Pipelines.JSONEncoder,
{Crawly.Pipelines.WriteToFile, extension: "jl", folder: "./temp"}
]

Options générales

Passons en revue chaque bien et donnons-lui un sens :

  • closespider_timeout : entier, nombre maximum de secondes pendant lesquelles l'araignée restera ouverte
  • concurrent_requests_per_domain : le nombre maximum de requêtes qui seront effectuées pour chaque domaine scrappé.
  • closespider_itemcount : le nombre maximum d'éléments transmis par le pipeline d'éléments

Agent utilisateur

En définissant l'agent utilisateur, vous améliorez les résultats du scraping en imitant un véritable navigateur. Les sites n'apprécient guère les "scrapers" et tentent de bloquer tout agent utilisateur qui ne semble pas réel. Vous pouvez utiliser un outil comme celui-ci pour obtenir l'agent utilisateur de votre navigateur.

WebScrapingAPI fait tourner l'agent utilisateur et l'adresse IP à chaque demande et met en œuvre d'innombrables astuces pour éviter ce genre de situation. Vos requêtes ne seront pas bloquées et la mise en œuvre d'un mécanisme de relance vous donnera des résultats dignes d'une amazone.

Pipelines

Les pipelines sont des commandes traitées de haut en bas et permettent de manipuler les éléments traités. Nous utilisons les pipelines suivants :

  • Valider les champs (titre, prix, url) : vérifie si l'article contient les champs scrappés.
  • Filtre des doublons : recherche les doublons par titre
  • Encodeur JSON : encode les structures en objets JSON
  • Écrire dans le fichier : écrit les éléments dans le dossier ./temp

Création de l'araignée

Un web crawler, ou spider, est un type de robot qui parcourt un site et extrait des données en utilisant des champs définis par l'utilisateur au moyen de sélecteurs CSS. Un crawler peut extraire tous les liens d'une page et en utiliser certains (comme les liens de pagination) pour extraire davantage de données. 

Il est temps de définir la base du crawler : créez le fichier ebay_scraper.ex dans le dossier lib/elixir_spider et collez-y le code suivant :

# lib/elixir_spider/ebay.ex
defmodule EbayScraper do
use Crawly.Spider

@impl Crawly.Spider
def base_url(), do : ""

@impl Crawly.Spider
def init() do

end

@impl Crawly.Spider
def parse_item(response) do

end
end

Il s'agit simplement du squelette du fichier, qui ne s'exécutera pas et ne renverra aucun résultat. Parlons d'abord de chaque fonction, puis remplissons-les une par une.

La fonction base_url() est appelée une fois et renvoie l'URL de base du site web cible que le crawler va explorer ; elle est également utilisée pour filtrer les liens externes et empêcher le crawler de les suivre. Il n'est pas souhaitable d'explorer l'ensemble de l'internet.

@impl Crawly.Spider
def base_url(), do : "https://www.ebay.com/"

La fonction init() est appelée une fois et sert à initialiser l'état par défaut du crawler ; dans ce cas, la fonction renvoie l'url de départ à partir de laquelle le scraping commencera.

Remplacez votre fonction vide par celle-ci :

@impl Crawly.Spider
def init() do
[start_urls : ["https://www.ebay.com/sch/i.html?_nkw=ps5"]]
end

Toute la magie de l'extraction des données se produit dans la fonction parse_item(). Cette fonction est appelée pour chaque URL scrappée. Dans cette fonction, nous utilisons l'analyseur HTML de Floki pour extraire les champs dont nous avons besoin : titre, url et prix.

La fonction se présente comme suit :

@impl Crawly.Spider
def parse_item(response) do
# Parse response body to document
{:ok, document} = Floki.parse_document(response.body)

# Create item (for pages where items exists)
items =
document
|> Floki.find(".srp-results .s-item")
|> Enum.map(fn x ->
%{
title: Floki.find(x, ".s-item__title span") |> Floki.text(),
price: Floki.find(x, ".s-item__price") |> Floki.text(),
url: Floki.find(x, ".s-item__link") |> Floki.attribute("href") |> Floki.text(),
}
end)

%{items: items}
end

Comme vous l'avez peut-être remarqué, nous utilisons les classes que nous avons trouvées dans la section "Getting Started - Inspecting the target" pour extraire les données dont nous avons besoin à partir des éléments du DOM.

L'araignée en marche

Il est temps de tester le code et de s'assurer qu'il fonctionne. À partir du répertoire racine du projet, exécutez la commande suivante :

iex -S mix run -e "Crawly.Engine.start_spider(EbayScraper)"

Si vous utilisez PowerShell, assurez-vous de remplacer iex par iex.bat, sinon vous obtiendrez une erreur en raison de l'inexistence du paramètre -S. Utilisez cette commande pour PowerShell :

iex.bat -S mix run -e "Crawly.Engine.start_spider(EbayScraper)"

Vérification des résultats

Ouvrez le dossier ./temp et vérifiez le fichier .jl. Vous devriez voir un fichier texte contenant une liste d'objets JSON, un par ligne. Chaque objet contient les informations dont nous avions besoin à partir de la liste des produits eBay : titre, prix et URL.

Voici à quoi devrait ressembler l'objet produit :

{"url":"https://www.ebay.com/itm/204096893295?epid=19040936896&hash=item2f851f716f:g:3G8AAOSwNslhoSZW&amdata=enc%3AAQAHAAAA0Nq2ODU0vEdnTBtnKgiVKIcOMvqJDPem%2BrNHrG4nsY9c3Ny1bzsybI0zClPHX1w4URLWSfXWX%2FeKXpdgpOe%2BF8IO%2FCh77%2FycTnMxDQNr5JfvTQZTF4%2Fu450uJ3RC7c%2B9ze0JHQ%2BWrbWP4yvDJnsTTWmjSONi2Cw71QMP6BnpfHBkn2mNzJ7j3Y1%2FSTIqcZ%2F8akkVNhUT0SQN7%2FBD38ue9kiUNDw9YDTUI1PhY14VbXB6ZMWZkN4hCt6gCDCl5mM7ZRpfYiDaVjaWVCbxUIm3rIg%3D%7Ctkp%3ABFBMwpvFwvRg","title":"PS5 Sony PlayStation 5 Console Disc Version!  US VERSION!","price":"$669.99"}

Améliorer l'araignée

Nous avons récupéré tous les produits de la première page de la liste des produits, mais ce n'est pas suffisant. Il est temps d'implémenter la pagination et de laisser le crawler extraire tous les produits disponibles.

Modifions la fonction parse_item() et ajoutons un nouveau bloc qui crée une structure requests avec le prochain lien de pagination. Ajoutez ce code après le code des éléments :

# Extrait le lien de la page suivante et le convertit en requête
requests =
document
|> Floki.find(".s-pagination a.pagination__next")
|> Floki.attribute("href")
|> Crawly.Utils.build_absolute_urls(response.request_url)
|> Crawly.Utils.requests_from_urls()

Mettez à jour la déclaration de retour de la fonction parse_item() pour inclure les demandes suivantes. La structure ressemblera à ceci :

%{
:requests => requests,
:items => items
}

Lancez à nouveau le crawler, mais cette fois-ci, préparez un café. La recherche des listes PS5 sur toutes les pages prendra quelques minutes.

Une fois que le crawler a terminé son travail, vérifiez le dossier ./temp pour les résultats obtenus. Vous avez réussi à rechercher des consoles PS5 sur eBay et vous disposez d'une liste avec leurs prix. Vous pouvez étendre ce crawler pour rechercher d'autres produits.

Conclusion

Dans cet article, vous avez appris ce qu'est un scraper web, quels sont les cas d'utilisation de ces crawlers, comment utiliser des bibliothèques déjà faites pour mettre en place un scraper en utilisant Elixir en quelques minutes, et comment exécuter et extraire les données réelles.

Si vous avez eu l'impression que cela représentait beaucoup de travail, je voudrais vous annoncer une mauvaise nouvelle : nous n'avons fait qu'effleurer la surface. L'utilisation de ce scraper pendant une longue période entraînera plus de problèmes que vous ne pouvez en imaginer.

eBay détectera votre activité et la marquera comme suspecte ; le crawler commencera à recevoir des patchs Captcha ; vous devrez étendre la fonctionnalité du crawler pour résoudre les captchas.

Les systèmes de détection d'eBay peuvent signaler votre adresse IP et vous empêcher d'accéder au site web ; vous devrez obtenir un pool de proxy et faire tourner les adresses IP à chaque demande. 

Vous avez déjà la tête qui tourne ? Parlons d'un autre problème : l'agent utilisateur. Vous devez construire une grande base de données avec les agents utilisateurs et faire tourner cette valeur à chaque demande. Les systèmes de détection bloquent les "scrapers" sur la base de l'adresse IP et de l'agent utilisateur.

Si vous souhaitez vous concentrer davantage sur l'aspect commercial et investir votre temps dans l'extraction de données plutôt que de résoudre les problèmes de détection, l'utilisation d'un scraper en tant que service est un meilleur choix. Une solution comme WebScrapingAPI résout tous les problèmes présentés ci-dessus et bien d'autres encore. 

Nouvelles et mises à jour

Restez au courant des derniers guides et nouvelles sur le web scraping en vous inscrivant à notre lettre d'information.

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Articles connexes

vignette
La science du Web ScrapingScrapy vs. Selenium : Un guide complet pour choisir le meilleur outil de Web Scraping

Explorez la comparaison approfondie entre Scrapy et Selenium pour le web scraping. De l'acquisition de données à grande échelle à la gestion de contenus dynamiques, découvrez les avantages, les inconvénients et les caractéristiques uniques de chacun. Apprenez à choisir le meilleur framework en fonction des besoins et de l'échelle de votre projet.

WebscrapingAPI
avatar de l'auteur
WebscrapingAPI
14 minutes de lecture
vignette
GuidesTutoriel Scrapy Splash : Maîtriser l'art du scraping de sites web rendus en JavaScript avec Scrapy et Splash

Apprenez à récupérer des sites web dynamiques en JavaScript à l'aide de Scrapy et de Splash. De l'installation à l'écriture d'un spider, en passant par la gestion de la pagination et des réponses Splash, ce guide complet propose des instructions pas à pas pour les débutants comme pour les experts.

Ștefan Răcila
avatar de l'auteur
Ștefan Răcila
6 minutes de lecture
vignette
GuidesLe guide ultime de la recherche d'emploi en ligne, ses avantages et ses inconvénients

La définition et l'utilisation du "job scraping" en ligne. Les avantages et les inconvénients du "job scraping", ainsi que les stratégies et les risques potentiels.

Suciu Dan
avatar de l'auteur
Suciu Dan
8 minutes de lecture