Web Scraping con Crawlee – Guía Paso a Paso

Descubre cómo usar Crawlee para un scraping web eficiente con Node.js, cubriendo desde la configuración básica hasta la rotación de proxies avanzada y el manejo de contenido dinámico.
12 min de lectura
Web Scraping With Crawlee blog image

Si estás interesado en el scraping web, Crawlee puede ayudarte. Es un motor de scraping rápido e interactivo utilizado por científicos de datos, desarrolladores e investigadores para recopilar datos web. Crawlee es fácil de configurar y ofrece funciones como rotación de proxies y manejo de sesiones. Estas funciones son fundamentales para hacer scraping en sitios web grandes o dinámicos sin que tu dirección IP sea bloqueada, garantizando una recopilación de datos fluida e ininterrumpida.

En este tutorial, aprenderás a usar Crawlee para el scraping web. Comenzarás con un ejemplo básico de scraping web y avanzarás hacia conceptos más complejos, como la gestión de sesiones y el scraping de páginas dinámicas.

Cómo hacer Scraping Web con Crawlee

Antes de comenzar este tutorial, asegúrate de tener los siguientes requisitos previos instalados en tu máquina:

  • Node.js
  • npm
  • Visual Studio Code

Scraping Web Básico con Crawlee

Una vez que tengas todos los requisitos previos, comencemos haciendo scraping en el sitio web Books to Scrape, que es perfecto para aprender ya que proporciona una estructura HTML sencilla.

Abre tu terminal o shell y comienza inicializando un proyecto Node.js con los siguientes comandos:

mkdir crawlee-tutorial
cd crawlee-tutorial
npm init -y

Luego, instala la biblioteca Crawlee con el siguiente comando:

npm install crawlee

Para hacer scraping de datos de cualquier sitio web de manera efectiva, debes inspeccionar la página web que deseas scrapear para obtener los detalles de las etiquetas HTML del sitio. Para ello, abre el sitio web en tu navegador y navega a las Herramientas para desarrolladores haciendo clic derecho en cualquier parte de la página web. Luego, haz clic en Inspeccionar o Inspeccionar elemento:

Inspeccionar elemento HTML

La pestaña Elementos debería estar activa por defecto y representa el diseño HTML de la página web. En este ejemplo, cada libro mostrado está ubicado en una etiqueta HTML article con la clase product_pod. Dentro de cada artículo, el título del libro está contenido en una etiqueta h3. El título real del libro está en el atributo title de la etiqueta a ubicada dentro del elemento h3. El precio del libro está dentro de la etiqueta p con la clase price_color:

Inspeccionar los elementos HTML en el sitio web Books to Scrape

En el directorio raíz de tu proyecto, crea un archivo llamado scrape.js y agrega el siguiente código:

   const { CheerioCrawler } = require('crawlee');

   const crawler = new CheerioCrawler({
       async requestHandler({ request, $ }) {
           const books = [];
           $('article.product_pod').each((index, element) => {
               const title = $(element).find('h3 a').attr('title');
               const price = $(element).find('.price_color').text();
               books.push({ title, price });
           });
           console.log(books);
       },
   });

   crawler.run(['https://books.toscrape.com/']);

En este código, usas CheerioCrawler de crawlee para hacer scraping de títulos y precios de libros desde https://books.toscrape.com/. El crawler obtiene el contenido HTML, extrae datos de los elementos <article class="product_pod"> usando una sintaxis similar a jQuery y registra los resultados en la consola.

Una vez que hayas añadido el código anterior a tu archivo scrape.js, puedes ejecutar el código con el siguiente comando:

node scrape.js

Un array de títulos y precios de libros debería imprimirse en tu terminal:

…output omitted…
  {
    title: 'The Boys in the Boat: Nine Americans and Their Epic Quest for Gold at the 1936 Berlin Olympics',
    price: '£22.60'
  },
  { title: 'The Black Maria', price: '£52.15' },
  {
    title: 'Starving Hearts (Triangular Trade Trilogy, #1)',
    price: '£13.99'
  },
  { title: "Shakespeare's Sonnets", price: '£20.66' },
  { title: 'Set Me Free', price: '£17.46' },
  {
    title: "Scott Pilgrim's Precious Little Life (Scott Pilgrim #1)",
    price: '£52.29'
  },
…output omitted…

Rotación de Proxy con Crawlee

Un proxy es el intermediario entre tu computadora e internet. Cuando usas un proxy, este envía tus solicitudes web al servidor proxy, que las reenvía al sitio web de destino. El servidor proxy devuelve la respuesta del sitio web, y el proxy oculta tu dirección IP evitando que te limiten la tasa o te bloqueen la IP.

Crawlee facilita la implementación de proxies porque incluye manejo integrado de proxies, que gestiona eficientemente los reintentos y errores. Crawlee también admite una variedad de configuraciones de proxy para implementar proxies rotativos.

En la siguiente sección, configurarás un proxy obteniendo primero un proxy válido. Luego, verificarás que tus solicitudes estén pasando a través de los proxies.

Configurar un Proxy

Los proxies gratuitos generalmente no son recomendables porque pueden ser lentos e inseguros, y puede que no tengan el soporte necesario para tareas web sensibles. En su lugar, considera usar Bright Data, un servicio de proxy seguro, estable y confiable. También ofrece pruebas gratuitas, para que puedas probarlo antes de comprometerte.

Para usar Bright Data, haz clic en el botón Prueba gratuita en su página de inicio y completa la información requerida para crear una cuenta.

Una vez creada tu cuenta, inicia sesión en el panel de Bright Data, navega a Proxies e Infraestructura de Scraping y añade un nuevo proxy seleccionando Proxies Residenciales:

Añadir un proxy residencial

Mantén la configuración predeterminada y finaliza la creación de tu proxy residencial haciendo clic en Añadir.

Si se te pide instalar un certificado, puedes seleccionar Continuar sin certificado. Sin embargo, para producción y casos de uso reales, debes configurar el certificado para evitar el uso indebido si tu información de proxy queda expuesta.

Una vez creado, anota las credenciales del proxy, incluyendo el host, puerto, nombre de usuario y contraseña. Los necesitarás en el siguiente paso:

Credenciales del proxy de Bright Data

En el directorio raíz de tu proyecto, ejecuta el siguiente comando para instalar la biblioteca axios:

npm install axios

Usas la biblioteca axios para hacer una solicitud GET a http://lumtest.com/myip.json, que devuelve los detalles del proxy que estás usando cada vez que ejecutas el script.

A continuación, en el directorio raíz de tu proyecto, crea un archivo llamado scrapeWithProxy.js y agrega el siguiente código:

const { CheerioCrawler } = require("crawlee");
const { ProxyConfiguration } = require("crawlee");
const axios = require("axios");

const proxyConfiguration = new ProxyConfiguration({
  proxyUrls: ["http://USERNAME:PASSWORD@HOST:PORT"],
});

const crawler = new CheerioCrawler({
  proxyConfiguration,
  async requestHandler({ request, $, response, proxies }) {
    // Make a GET request to the proxy information URL
    try {
      const proxyInfo = await axios.get("http://lumtest.com/myip.json", {
        proxy: {
          host: "HOST",
          port: PORT,
          auth: {
            username: "USERNAME",
            password: "PASSWORD",
          },
        },
      });
      console.log("Proxy Information:", proxyInfo.data);
    } catch (error) {
      console.error("Error fetching proxy information:", error.message);
    }

    const books = [];
    $("article.product_pod").each((index, element) => {
      const title = $(element).find("h3 a").attr("title");
      const price = $(element).find(".price_color").text();
      books.push({ title, price });
    });
    console.log(books);
  },
});

crawler.run(["https://books.toscrape.com/"]);

Nota: Asegúrate de reemplazar HOSTPORTUSERNAME y PASSWORD con tus credenciales.

En este código, usas CheerioCrawler de crawlee para hacer scraping de información desde https://books.toscrape.com/ usando un proxy especificado. Configuras el proxy con ProxyConfiguration; luego, obtienes y registras los detalles del proxy usando una solicitud GET a http://lumtest.com/myip.json. Finalmente, extraes los títulos y precios de libros usando la sintaxis similar a jQuery de Cheerio y registras los datos scrapeados en la consola.

Ahora puedes ejecutar y probar el código para asegurarte de que los proxies funcionen:

node scrapeWithProxy.js

Verás resultados similares a los anteriores, pero esta vez tus solicitudes se enrutan a través de los proxies de Bright Data. También deberías ver los detalles del proxy registrados en la consola:

Proxy Information: {
  country: 'US',
  asn: { asnum: 21928, org_name: 'T-MOBILE-AS21928' },
  geo: {
    city: 'El Paso',
    region: 'TX',
    region_name: 'Texas',
    postal_code: '79925',
    latitude: 31.7899,
    longitude: -106.3658,
    tz: 'America/Denver',
    lum_city: 'elpaso',
    lum_region: 'tx'
  }
}
[
  { title: 'A Light in the Attic', price: '£51.77' },
  { title: 'Tipping the Velvet', price: '£53.74' },
  { title: 'Soumission', price: '£50.10' },
  { title: 'Sharp Objects', price: '£47.82' },
  { title: 'Sapiens: A Brief History of Humankind', price: '£54.23' },
  { title: 'The Requiem Red', price: '£22.65' },
…output omitted..

Si ejecutas el script nuevamente con node scrapingWithBrightData.js, deberías ver una ubicación de dirección IP diferente usada por el servidor proxy de Bright Data. Esto valida que Bright Data rota ubicaciones e IPs cada vez que ejecutas tu script de scraping. Esta rotación es importante para evitar bloqueos o baneos de IP de los sitios web de destino.

Nota: En la proxyConfiguration, podrías haber pasado diferentes IPs de proxy, pero como Bright Data lo hace por ti, no necesitas especificar las IPs.

Gestión de Sesiones con Crawlee

Las sesiones ayudan a mantener el estado entre múltiples solicitudes, lo que es útil para sitios web que usan cookies o sesiones de inicio de sesión.

Para gestionar una sesión, crea un archivo llamado scrapeWithSessions.js en el directorio raíz de tu proyecto y agrega el siguiente código:

const { CheerioCrawler, SessionPool } = require("crawlee");

(async () => {
  // Open a session pool
  const sessionPool = await SessionPool.open();

  // Ensure there is a session in the pool
  let session = await sessionPool.getSession();
  if (!session) {
    session = await sessionPool.createSession();
  }

  const crawler = new CheerioCrawler({
    useSessionPool: true, // Enable session pool
    async requestHandler({ request, $, response, session }) {
      // Log the session information
      console.log(`Using session: ${session.id}`);

      // Extract book data and log it (for demonstration)
      const books = [];
      $("article.product_pod").each((index, element) => {
        const title = $(element).find("h3 a").attr("title");
        const price = $(element).find(".price_color").text();
        books.push({ title, price });
      });
      console.log(books);
    },
  });

  // First run
  await crawler.run(["https://books.toscrape.com/"]);
  console.log("First run completed.");

  // Second run
  await crawler.run(["https://books.toscrape.com/"]);
  console.log("Second run completed.");
})();

Aquí, usas CheerioCrawler y SessionPool de crawlee para hacer scraping de datos desde https://books.toscrape.com/. Inicializas un grupo de sesiones y luego configuras el crawler para utilizarla. La función requestHandler registra la información de la sesión y extrae títulos y precios de libros usando los selectores similares a jQuery de Cheerio. El código realiza dos ejecuciones de scraping consecutivas y registra el ID de sesión en cada ejecución.

Ejecuta y prueba el código para validar que se estén usando diferentes sesiones:

node scrapeWithSessions.js

Deberías ver resultados similares a los anteriores, pero esta vez también deberías ver el ID de sesión para cada ejecución:

Using session: session_GmKuZ2TnVX
[
  { title: 'A Light in the Attic', price: '£51.77' },
  { title: 'Tipping the Velvet', price: '£53.74' },
…output omitted…
Using session: session_lNRxE89hXu
[
  { title: 'A Light in the Attic', price: '£51.77' },
  { title: 'Tipping the Velvet', price: '£53.74' },
…output omitted…

Si ejecutas el código nuevamente, deberías ver que se está usando un ID de sesión diferente.

Manejo de Contenido Dinámico con Crawlee

Si estás trabajando con sitios web dinámicos (es decir sitios web con contenido generado por JavaScript), el scraping web puede ser extremadamente desafiante porque necesitas renderizar JavaScript para acceder a los datos. Para manejar estas situaciones, Crawlee se integra con Puppeteer, un navegador sin interfaz que puede renderizar JavaScript e interactuar con el sitio web de destino como lo haría un humano.

Para demostrar esta funcionalidad, vamos a hacer scraping de contenido de esta página de YouTube. Como siempre, antes de scrapear cualquier cosa, asegúrate de revisar las reglas y términos de servicio de esa página.

Después de revisar los términos de servicio, crea un archivo llamado scrapeDynamicContent.js en el directorio raíz de tu proyecto y agrega el siguiente código:

const { PuppeteerCrawler } = require("crawlee");

async function scrapeYouTube() {
  const crawler = new PuppeteerCrawler({
    async requestHandler({ page, request, enqueueLinks, log }) {
      const { url } = request;
      await page.goto(url, { waitUntil: "networkidle2" });

      // Scraping first 10 comments
      const comments = await page.evaluate(() => {
        return Array.from(document.querySelectorAll("#comments #content-text"))
          .slice(0, 10)
          .map((el) => el.innerText);
      });

      log.info(`Comments: ${comments.join("n")}`);
    },

    launchContext: {
      launchOptions: {
        headless: true,
      },
    },
  });

  // Add the URL of the YouTube video you want to scrape
  await crawler.run(["https://www.youtube.com/watch?v=wZ6cST5pexo"]);
}

scrapeYouTube();

Luego, ejecuta el código con el siguiente comando:

node scrapeDynamicContent.js

En este código, usas PuppeteerCrawler de la biblioteca Crawlee para hacer scraping de comentarios de videos de YouTube. Comienzas inicializando un crawler que navega a una URL específica de YouTube y espera a que la página cargue completamente. Una vez cargada, el código evalúa el contenido de la página para extraer los primeros diez comentarios seleccionando elementos con el selector CSS especificado #comments #content-text. Los comentarios se registran en la consola.

Tu salida debería incluir los primeros diez comentarios relacionados con el video seleccionado:

INFO  PuppeteerCrawler: Starting the crawler.
INFO  PuppeteerCrawler: Comments: Who are you rooting for?? US Marines or Ex Cons 
Bro Mateo is a beast, no lifting straps, close stance.
ex convict doing the pushups is a monster.
I love how quick this video was, without nonsense talk and long intros or outros
"They Both have combat experience" is wicked 
That military guy doing that deadlift is really no joke.. ...
One lives to fight and the other fights to live.
Finally something that would test the real outcome on which narrative is true on movies
I like the comradery between all of them. Especially on the Bench Press ... Both team members quickly helped out on the spotting to protect from injury. Well done.
I like this style, no youtube funny business. Just straight to the lifts
…output omitted…

Puedes encontrar todo el código utilizado en este tutorial en GitHub.

Conclusión

En este artículo, aprendiste a usar Crawlee para el scraping web, y viste cómo puede ayudar a mejorar la eficiencia y confiabilidad de tus proyectos de scraping web.

Recuerda siempre respetar el archivo robots.txt y los términos de servicio del sitio web de destino al hacer scraping de datos.

¿Listo para llevar tus proyectos de scraping web al siguiente nivel con datos, herramientas y proxies de nivel profesional? Explora la completa infraestructura de scraping web de Bright Data, que ofrece conjuntos de datos listos para usar y servicios de proxy avanzados para optimizar tus esfuerzos de recopilación de datos.

¡Regístrate ahora y comienza tu prueba gratuita!