Un rastreador web, o araña, es un tipo de bot que recorre un sitio y extrae datos utilizando campos definidos por el usuario a través de selectores CSS. Un rastreador puede extraer todos los enlaces de una página y utilizar algunos específicos (como los enlaces de paginación) para rastrear más datos.
Es hora de sentar las bases del rastreador: crea el archivo ebay_scraper.ex en la carpeta lib/elixir_spider y pega el siguiente código en él:
# 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
Esto es solo el esqueleto del archivo y no se ejecutará ni devolverá ningún resultado. Hablemos primero de cada función y luego las rellenaremos una por una.
La función base_url() se llama una vez y devuelve la URL base del sitio web de destino que el rastreador va a rastrear; también se utiliza para filtrar enlaces externos y evitar que el rastreador los siga. No quieres rastrear todo Internet.
@impl Crawly.Spider
def base_url(), do: "https://www.ebay.com/"
La función init() se invoca una vez y se utiliza para inicializar el estado predeterminado del rastreador; en este caso, la función devuelve la start_url desde donde comenzará el rastreo.
Sustituye tu función en blanco por esta:
@impl Crawly.Spider
def init() do
[start_urls: ["https://www.ebay.com/sch/i.html?_nkw=ps5"]]
end
Toda la magia de la extracción de datos tiene lugar en parse_item(). Esta función se invoca para cada URL rastreada. Dentro de esta función, utilizamos el analizador HTML de Floki para extraer los campos que necesitamos: title, url y price.
La función tendrá este aspecto:
@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 habrás notado, estamos utilizando las clases que encontramos en la sección «Introducción: inspeccionar el objetivo» para extraer los datos que necesitamos de los elementos DOM.