Un crawler web, ou spider, est un type de bot qui parcourt un site et extrait des données à l'aide de champs définis par l'utilisateur via des sélecteurs CSS. Un crawler peut extraire tous les liens d'une page et utiliser certains d'entre eux (comme les liens de pagination) pour explorer davantage de données.
Il est temps de poser les bases 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 ; il ne s'exécutera pas et ne renverra aucun résultat. Commençons par passer en revue chaque fonction, puis nous les compléterons une par une.
La fonction base_url() est appelée une seule fois et renvoie l'URL de base du site web cible que le crawler va scraper ; elle sert également à filtrer les liens externes et à empêcher le crawler de les suivre. Vous ne voulez pas scraper l'intégralité d'Internet.
@impl Crawly.Spider
def base_url(), do: "https://www.ebay.com/"
La fonction init() est appelée une seule fois et sert à initialiser l'état par défaut du crawler ; dans ce cas, la fonction renvoie l'URL de départ (start_url) à partir de laquelle l'exploration 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 passe dans la fonction parse_item(). Cette fonction est appelée pour chaque URL explorée. Au sein de cette fonction, nous utilisons l'analyseur HTML Floki pour extraire les champs dont nous avons besoin : title, url et price.
La fonction ressemblera à ceci :
@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 « Pour commencer - Inspection de la cible » pour extraire les données dont nous avons besoin à partir des éléments DOM.