Home » Desarrollo » Web Scraping Dinámico con Puppeteer JS

Web Scraping Dinámico con Puppeteer JS

Puppeteer Js es una biblioteca de Node.js que permite automatizar acciones sobre los navegadores de Google (Chrome y Chromium). Y lo mejor de todo es que está desarrollado por los ingenieros de Google.

Entre sus ventajas está que no se necesita referenciar a un driver externo como en el caso de Selenium WebDriver. Y también ofrece por defecto una ejecución de pruebas en modo headless.

Sin mucho que hablar vamos a ir al grano. El sitio que vamos a realizar el scraping es https://quotes.toscrape.com/search.aspx. Presenta citas de una lista de autores determinados para una lista de temas.

Requisitos previos a la instalación.

Como vamos a construir todo usando Node.js, primero vamos a crear y abrir una nueva carpeta, y crear un nuevo proyecto de node dentro y ejecutamos los siguientes comandos:

mkdir js-webscraper
cd js-webscraper
npm init

Asegurémonos de que ya se ha instalado npm. El instalador nos hará unas cuantas preguntas sobre la meta-información de este proyecto que podemos saltarnos dándole a la tecla «Enter».

Instalación de Puppeteer.

Vamos a instalarlo usando npm:

npm install puppeteer

Construyendo nuestro Scraper.

Ahora, vamos a empezar a construir nuestro scraper creando un nuevo archivo, llamado web_scraper.js. Primero, importamos la biblioteca «Puppeteer» previamente instalada :

const puppeteer = require('puppeteer');

Como siguiente paso, le decimos a Puppeteer que abra una nueva instancia del navegador dentro de una función asíncrona y autoejecutable.

(async function scrape() {
const browser = await puppeteer.launch({ headless: false });
// scraping logic comes here…
})();

Por defecto, el modo headless está desactivado, ya que aumenta el rendimiento. Sin embargo, cuando se construye un nuevo scraper, desactivaremos el modo headless. Esto nos permite seguir el proceso por el que pasa el navegador y ver todo el contenido renderizado.

Dentro de nuestra instancia abierta del navegador, ahora abrimos una nueva página y dirigimos hacia nuestra URL de destino:

const page = await browser.newPage();
await page.goto('https://quotes.toscrape.com/search.aspx');

Como parte de la función asíncrona, utilizaremos la sentencia await para esperar a que se ejecute el siguiente comando antes de proceder con la siguiente línea de código.

Ahora que hemos abierto con éxito una ventana del navegador y hemos navegado a la página, tenemos que crear el estado del sitio web, para que la información deseada sea visible para el scraping.

Los temas disponibles se generan dinámicamente para un autor seleccionado. Por lo tanto, primero seleccionaremos «Albert Einstein» y esperaremos a que se genere la lista de temas. Una vez que la lista se ha generado por completo, seleccionamos «aprendizaje» como tema y lo seleccionamos como segundo parámetro del formulario. A continuación, hacemos clic en enviar y extraemos las citas recuperadas del contenedor que contiene los resultados.

Como ahora vamos a convertir esto en lógica JavaScript, vamos a hacer primero una lista de todos los selectores de elementos de los que hemos hablado en el párrafo anterior:

Campo de selección del autor – #author

Campo de selección de etiqueta – #tag

Botón de envío – input[type=»submit»]

Contenedor de citas – .quote

Antes de empezar a interactuar con la página, nos aseguraremos de que todos los elementos a los que vamos a acceder son visibles, añadiendo las siguientes líneas a nuestro script:

await page.waitForSelector('#author');
await page.waitForSelector('#tag');

A continuación, seleccionaremos valores para nuestros dos campos de selección:

await page.select('select#author', 'Albert Einstein');
await page.select('select#tag', 'learning');

Ya estamos listos para realizar nuestra búsqueda pulsando el botón «Buscar» de la página y esperar a que aparezcan las citas:

await page.click('.btn');
await page.waitForSelector('.quote');

Como ahora vamos a acceder a la estructura HTML DOM de la página, llamamos a la función page.evaluate() proporcionada, seleccionando el contenedor que contiene las comillas (en este caso es sólo uno). A continuación, construimos un objeto y definimos null como valor de retorno para cada parámetro del objeto:

let quotes = await page.evaluate(() => {
        let quotesElement = document.body.querySelectorAll('.quote');
  let quotes = Object.values(quotesElement).map(x => {
              return {
                  author: x.querySelector('.author').textContent ?? null,
    quote: x.querySelector('.content').textContent ?? null,
    tag: x.querySelector('.tag').textContent ?? null,
  };
});
 return quotes;
});

Hacemos que todos los resultados sean visibles en nuestra consola registrándolos:

console.log(quotes);

Finalmente, cerramos nuestro navegador y añadamos una sentencia catch:

await browser.close();

El código completo queda de la siguiente forma:

const puppeteer = require('puppeteer');

(async function scrape() {
    const browser = await puppeteer.launch({ headless: false });

    const page = await browser.newPage();
    await page.goto('https://quotes.toscrape.com/search.aspx');

    await page.waitForSelector('#author');
    await page.select('#author', 'Albert Einstein');

    await page.waitForSelector('#tag');
    await page.select('#tag', 'learning');

    await page.click('.btn');
    await page.waitForSelector('.quote');

    // extracting information from code
    let quotes = await page.evaluate(() => {

        let quotesElement = document.body.querySelectorAll('.quote');
        let quotes = Object.values(quotesElement).map(x => {
            return {
                author: x.querySelector('.author').textContent ?? null,
                quote: x.querySelector('.content').textContent ?? null,
                tag: x.querySelector('.tag').textContent ?? null,

            }
        });

        return quotes;

    });

    // logging results
    console.log(quotes);
    await browser.close();

})();

Ahora ejecutamos nuestro scraper con:

node scraper.js

Y listo. El scraper devuelve nuestra cita tal y como se esperaba:

Si quieres el código completo les dejo el enlace a GitHub:

https://github.com/andy910304/js-webscraper

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *