La Guía Definitiva Sobre Cómo Empezar Web Scraping Con Elixir

Suciu Dan el 18 oct 2022

Introducción

Web scraping es el proceso de extracción de datos de sitios de acceso público como foros, redes sociales, sitios de noticias, plataformas de comercio electrónico, etc. Para darte una idea de lo que construirás hoy, este artículo describe la creación de un raspador web en Elixir.

Si la definición de web scraping aún no le queda clara, consideremos que guardar una imagen de un sitio es un web scraping manual. Si desea guardar todas las imágenes de un sitio a mano, en función de la complejidad del sitio, podría tardar horas o incluso días. 

Puedes automatizar este proceso creando un raspador web.

Quizás te estés preguntando cuáles son algunos casos de uso de un raspador web. Aquí están los más comunes:

Seguimiento de noticias

Puede obtener las últimas noticias de su sitio de noticias financieras favorito, ejecutar un algoritmo de análisis de sentimiento y saber en qué invertir minutos antes de que el mercado comience a moverse.

Información sobre las redes sociales

Puede extraer los comentarios de sus páginas en las redes sociales y analizar de qué hablan sus abonados y qué opinan de su producto o servicio.

Control de precios

Si tu pasión es coleccionar consolas y videojuegos pero no quieres gastarte una fortuna en la última PS5, puedes crear un rascador web que recupere los listados de eBay y te envíe una notificación cuando salga al mercado una consola barata.

Formación en aprendizaje automático

Si quieres crear una aplicación móvil que pueda identificar la raza de un gato en cualquier foto, necesitarás muchos datos de entrenamiento; en lugar de guardar cientos de miles de fotos con gatos manualmente para entrenar el modelo, puedes utilizar un raspador web para hacerlo automáticamente.

Construiremos nuestro raspador web en Elixir, un lenguaje de programación construido sobre Erlang, creado por José Valim, miembro del equipo central de Ruby on Rails. El lenguaje de programación toma prestada la sencillez de la sintaxis de Ruby y la combina con la capacidad de Erlang para construir sistemas de baja latencia, distribuidos y tolerantes a fallos.

Requisitos

Antes de escribir la primera línea de código, asegúrese de tener Elixir instalado en su ordenador. Descargue el instalador para su sistema operativo y siga las instrucciones de la página Instalar

Durante la instalación, observará que también se requiere el lenguaje de programación Erlang. Ten en cuenta que Elixir se ejecuta en la máquina virtual Erlang, por lo que necesitas ambos.

Cómo empezar

En este artículo, aprenderá a crear un raspador web en Elixir, raspar los productos de eBay para los listados PS5 y almacenar localmente los datos extraídos (nombre, url, precio).

Inspección del objetivo

Es hora de inspeccionar los resultados de la búsqueda en la página de eBay y recopilar algunos selectores.

Vaya a ebay.com, introduzca el término PS5 en el campo Buscar y haga clic en el botón Buscar. Una vez cargada la página de resultados de la búsqueda, abra la herramienta Inspeccionar desde su navegador (haga clic con el botón derecho del ratón en cualquier lugar de la página y seleccione Inspeccionar).

Debe reunir los siguientes selectores:

  • Lista de productos Artículo
  • URL del producto
  • Nombre del producto
  • Precio del producto

Utilice la herramienta de selección de elementos y busque la lista de elementos del producto (ul) y el elemento del producto (li):

blog-image

Utilizando estos dos elementos, puede extraer las clases necesarias para que el rastreador pueda extraer datos:

  • .srp-results .s-item los elementos hijos del elemento de lista de productos (ul)
  • .s-item__title span el título del producto
  • .s-item__link el enlace del producto
  • .s-item__price el precio del producto

Creación del proyecto

Vamos a crear un proyecto Elixir utilizando el comando mix:

mix nuevo elixir_spider --sup

La bandera --sup genera un esqueleto de aplicación OTP que incluye un árbol de supervisión, una característica necesaria para una aplicación que gestiona múltiples procesos concurrentes como un crawler.

Creación de la carpeta temporal

Cambia el directorio actual a la raíz del proyecto:

cd elixir_spider

Crea el directorio temporal:

mkdir temp

Utilizamos este directorio para almacenar los elementos raspados.

Añadir las dependencias

Una vez creado el proyecto, hay que añadir las dos dependencias:

  • Crawly es una aplicación para rastrear sitios web y extraer datos estructurados.
  • Floki es un analizador HTML que permite buscar nodos utilizando selectores CSS

Abra el archivo mix.exs y añada las dependencias en el bloque deps:

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

Obtenga las dependencias ejecutando este comando:

mix deps.get

Crear la configuración

Crea el archivo config/config.exs y pega en él esta configuración:

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"}
]

Opciones generales

Repasemos cada propiedad y démosle algún sentido:

  • closespider_timeout: entero, el número máximo de segundos que la araña permanecerá abierta
  • concurrent_requests_per_domain: el número máximo de peticiones que se realizarán para cada dominio raspado.
  • closespider_itemcount: el número máximo de ítems son pasados por el item pipeline

Agente de usuario

Al configurar el agente de usuario, se mejoran los resultados del scraping al imitar un navegador real. Los sitios no están contentos con los scrapers e intentan bloquear cualquier agente de usuario que no parezca real. Puedes utilizar una herramienta como ésta para obtener el agente de usuario de tu navegador.

WebScrapingAPI rota el agente de usuario y la dirección IP con cada petición y también implementa innumerables evasivas para prevenir este tipo de situaciones. Tus peticiones no se bloquearán e implementando un mecanismo de reintento obtendrás resultados asombrosos.

Tuberías

Los pipelines son comandos procesados de arriba a abajo y permiten manipular los elementos procesados. Utilizamos los siguientes pipelines:

  • Validar campos (título, precio, url): comprueba si el artículo tiene configurados los campos raspados.
  • Filtro de duplicados: busca elementos duplicados por título
  • Codificador JSON: codifica las estructuras en objetos JSON
  • Escribir en archivo: escribe los elementos en la carpeta ./temp

Creación de la araña

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 establecer la base para el crawler: 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 sólo el esqueleto para el archivo y no se ejecutará ni devolverá ningún resultado. Hablemos primero de cada función y luego las llenamos una por una.

La función base_url( ) se ejecuta una vez y devuelve la URL base del sitio web de destino que el rastreador rastreará; también se utiliza para filtrar enlaces externos y evitar que el rastreador los siga. No se quiere rastrear todo Internet.

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

La función init( ) se llama una vez y se utiliza para inicializar el estado por defecto del rastreador; en este caso, la función devuelve la start_url desde donde comenzará el raspado.

Sustituye tu función en blanco por ésta:

@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 ocurre en la función parse_item(). Esta función se llama para cada URL raspada. Dentro de esta función, utilizamos el analizador HTML de Floki para extraer los campos que necesitamos: título, url y precio.

La función tendrá el siguiente 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 - Inspección del objetivo para extraer los datos que necesitamos de los elementos DOM.

Ejecutar la araña

Es hora de probar el código y asegurarse de que funciona. Desde el directorio raíz del proyecto, ejecuta este comando:

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

Si utiliza PowerShell, asegúrese de sustituir iex por iex.bat, de lo contrario obtendrá un error por la inexistencia del parámetro -S. Utilice este comando para PowerShell:

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

Comprobación de los resultados

Abra la carpeta ./temp y compruebe el archivo .jl. Debería ver un archivo de texto que contiene una lista de objetos JSON, uno por línea. Cada objeto contiene la información que necesitábamos de la lista de productos de eBay: título, precio y URL.

Este es el aspecto que debería tener el objeto producto:

{"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"}

Mejorar la araña

Hemos recuperado todos los productos de la primera página de la lista de productos, pero esto no es suficiente. Es hora de implementar la paginación y dejar que el rastreador extraiga todos los productos disponibles.

Cambiemos la función parse_item() y añadamos un nuevo bloque que cree un struct de peticiones con el siguiente enlace de paginación. Añade este código después del código de items:

# Extraer el enlace a la página siguiente y convertirlo en una petición
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()

Actualice la sentencia return de la función parse_item() para incluir también las siguientes peticiones. La estructura tendrá este aspecto:

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

Ejecuta de nuevo el rastreador, pero esta vez prepara un café. El rastreo de todas las páginas de los listados de PS5 llevará unos minutos.

Después de que el rastreador termine su tarea, compruebe la carpeta ./temp para ver los resultados del rastreo. Has rastreado eBay con éxito en busca de consolas PS5 y tienes una lista con sus precios. Puede ampliar este rastreador para rastrear cualquier otro producto.

Conclusión

En este artículo aprendiste qué es un raspador web, qué casos de uso tienen estos rastreadores, cómo usar librerías ya hechas para configurar un raspador usando Elixir en minutos, y cómo ejecutar y extraer los datos reales.

Si esto te ha parecido mucho trabajo, quiero darte una noticia no tan buena: sólo hemos arañado la superficie. Ejecutar este rascador durante mucho tiempo comenzará y te causará más problemas de los que puedas imaginar.

eBay detectará tu actividad y la marcará como sospechosa; el rastreador empezará a recibir parches captcha; tendrás que ampliar la funcionalidad del rastreador para resolver captchas

Los sistemas de detección de eBay podrían marcar tu dirección IP y bloquearte el acceso al sitio web; tendrás que conseguir un grupo de proxy y rotar las direcciones IP con cada solicitud. 

¿Ya te da vueltas la cabeza? Hablemos de otra cuestión: el agente de usuario. Necesitas construir una gran base de datos con agentes de usuario y rotar ese valor con cada petición. El sistema de detección bloquea los scrapers basándose en la dirección IP y el agente de usuario.

Si desea centrarse más en la parte comercial e invertir su tiempo en la extracción de datos en lugar de resolver los problemas de detección, el uso de un raspador como servicio es una mejor opción. Una solución como WebScrapingAPI soluciona todos los problemas presentados anteriormente y un montón más. 

Noticias y actualidad

Manténgase al día de las últimas guías y noticias sobre raspado web suscribiéndose a nuestro boletín.

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

Artículos relacionados

miniatura
Ciencia del Web ScrapingScrapy vs. Selenium: Guía completa para elegir la mejor herramienta de Web Scraping

Explore la comparación en profundidad entre Scrapy y Selenium para el scraping web. Desde la adquisición de datos a gran escala hasta la gestión de contenido dinámico, descubra los pros, los contras y las características únicas de cada uno. Aprenda a elegir el mejor marco de trabajo en función de las necesidades y la escala de su proyecto.

WebscrapingAPI
avatar de autor
WebscrapingAPI
14 min leer
miniatura
GuíasTutorial de Scrapy Splash: Dominar el arte del scraping de sitios web renderizados en JavaScript con Scrapy y Splash

Aprenda a scrapear sitios web dinámicos con JavaScript utilizando Scrapy y Splash. Desde la instalación hasta la escritura de una araña, el manejo de la paginación y la gestión de las respuestas de Splash, esta completa guía ofrece instrucciones paso a paso tanto para principiantes como para expertos.

Ștefan Răcila
avatar de autor
Ștefan Răcila
6 min leer
miniatura
GuíasLa guía definitiva para el Job Scraping en línea, es Pros y Contras

Definición y usos del job scraping en línea. Ventajas y desventajas del job scraping, junto con estrategias y riesgos potenciales.

Suciu Dan
avatar de autor
Suciu Dan
8 min leer