Um rastreador web, ou spider, é um tipo de bot que percorre um site e extrai dados utilizando campos definidos pelo utilizador através de seletores CSS. Um rastreador pode extrair todos os links de uma página e utilizar alguns específicos (como links de paginação) para rastrear mais dados.
É hora de definir a base para o rastreador: crie o ficheiro ebay_scraper.ex na pasta lib/elixir_spider e cole o seguinte código nele:
# 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
Este é apenas o esqueleto do ficheiro e não irá executar-se nem devolver quaisquer resultados. Vamos falar primeiro sobre cada função e, em seguida, preenchê-las uma a uma.
A função base_url() é chamada uma vez e devolve o URL base do site de destino que o rastreador irá rastrear; também é utilizada para filtrar links externos e impedir que o rastreador os siga. Não se pretende rastrear toda a Internet.
@impl Crawly.Spider
def base_url(), do: "https://www.ebay.com/"
A função init() é chamada uma vez e é utilizada para inicializar o estado padrão do rastreador; neste caso, a função devolve o start_url a partir do qual a recolha de dados terá início.
Substitua a sua função em branco por esta:
@impl Crawly.Spider
def init() do
[start_urls: ["https://www.ebay.com/sch/i.html?_nkw=ps5"]]
end
Toda a magia da extração de dados acontece na função parse_item(). Esta função é chamada para cada URL rastreada. Dentro desta função, usamos o analisador HTML Floki para extrair os campos de que precisamos: título, URL e preço.
A função ficará assim:
@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
Como deve ter notado, estamos a utilizar as classes que encontrámos na secção Introdução - Inspecionar o alvo para extrair os dados de que precisamos dos elementos DOM.