Web Scraping con Puppeteer Advanced Node.JS

Gabriel Cioci el 28 Jul 2021

En lugar de utilizar herramientas comerciales, muchos desarrolladores prefieren crear sus propios web scrapers. Aunque los productos disponibles tienen funciones más desarrolladas, no podemos negar los resultados que pueden dar estos bots ni lo divertido que resulta crear el tuyo propio.

En el siguiente artículo, descubrirás los pasos que tienes que seguir para construir tu propio web scraper usando Node.js y Puppeteer. Vamos a codificar una aplicación que carga un sitio web, toma una captura de pantalla, inicia sesión en el sitio web utilizando un navegador sin cabeza y raspar algunos datos a través de múltiples páginas. Tu aplicación crecerá en complejidad a medida que progreses.

Visión general del Web Scraping con Puppeteer

Google diseñó Puppeteer para proporcionar una interfaz sencilla pero potente en Node.js para automatizar pruebas y diversas tareas utilizando el motor del navegador Chromium. Se ejecuta headless por defecto, pero se puede configurar para ejecutar Chrome completo o Chromium.

La API construida por el equipo de Puppeteer utiliza el protocolo DevTools para tomar el control de un navegador web, como Chrome, y realizar diferentes tareas, como:

  • Realiza capturas de pantalla y genera archivos PDF de las páginas
  • Automatizar el envío de formularios
  • Pruebas de interfaz de usuario (pulsación de botones, introducción de datos mediante el teclado, etc.)
  • Scrapear un SPA y generar contenido pre-renderizado (Server-Side Rendering)

La mayoría de las acciones que puedes hacer manualmente en el navegador también se pueden hacer usando Puppeteer. Además, se pueden automatizar para que puedas ahorrar más tiempo y centrarte en otros asuntos.

Puppeteer también fue construido para ser amigable con los desarrolladores. Las personas familiarizadas con otros marcos de pruebas populares, como Mocha, se sentirán como en casa con Puppeteer y encontrarán una comunidad activa que ofrece soporte para Puppeteer. Esto ha llevado a un crecimiento masivo de popularidad entre los desarrolladores.

Por supuesto, Puppeteer no es adecuado sólo para pruebas. Después de todo, si puede hacer cualquier cosa que un navegador estándar puede hacer, entonces puede ser extremadamente útil para los web scrapers. A saber, puede ayudar a ejecutar código javascript para que el scraper pueda llegar al HTML de la página e imitar el comportamiento normal del usuario desplazándose por la página o haciendo clic en secciones aleatorias.

Estas funcionalidades tan necesarias convierten a los navegadores sin cabeza en un componente básico para cualquier herramienta comercial de extracción de datos y para todos los raspadores web, salvo los más sencillos de fabricación casera.

Requisitos previos

Lo primero y más importante, asegúrate de que tienes versiones actualizadas de Node.js y Puppeteer instaladas en tu máquina. Si ese no es el caso, puedes seguir los siguientes pasos para instalar todos los prerrequisitos.

Puedes descargar e instalar Node.js desde aquí. El gestor de paquetes por defecto de Node , npm, viene preinstalado con Node.js.

Para instalar la libreria Puppeteer, puede ejecutar el siguiente comando en el directorio raiz de su proyecto:

npm install puppeteer
# o "yarn add puppeteer"

Tenga en cuenta que cuando instala Puppeteer, también descarga la última versión de Chromium que está garantizada para funcionar con la API.

Titiritero en acción

Hay muchas cosas diferentes que puedes hacer con la biblioteca. Dado que nuestro principal objetivo es el web scraping, hablaremos de los casos de uso que más probablemente te interesen si quieres extraer datos web.

Hacer una captura de pantalla

Empecemos con un ejemplo básico. Vamos a escribir un script que hará una captura de pantalla de un sitio web de nuestra elección.

Ten en cuenta que Puppeteer es una librería basada en promesas (realiza llamadas asíncronas a la instancia headless de Chrome). Así que vamos a mantener el código limpio mediante el uso de async/await.

Primero, crea un nuevo archivo llamado index.js en el directorio raíz de tu proyecto.

Dentro de ese archivo, necesitamos definir una función asíncrona y envolverla alrededor de todo el código de Puppeteer.

const puppeteer = require('puppeteer')

async function snapScreenshot() {
try {
const URL = 'https://old.reddit.com/'
const browser = await puppeteer.launch()
const page = await browser.newPage()

await page.goto(URL)
await page.screenshot({ path: 'screenshot.png' })

await browser.close()
} catch (error) {
console.error(error)
}
}

snapScreenshot()

En primer lugar, se inicia una instancia del navegador utilizando el comando puppeteer.launch(). A continuación, creamos una nueva página utilizando la instancia del navegador. Para navegar a la página web deseada, podemos utilizar el método goto( ), pasando la URL como parámetro. Para hacer una captura de pantalla, usaremos el método screenshot(). También necesitamos pasar la ubicación donde se guardará la imagen.

Tenga en cuenta que Puppeteer establece un tamaño de página inicial de 800×600px, que define el tamaño de la captura de pantalla. Puedes personalizar el tamaño de la página usando el método setViewport().

No olvides cerrar la instancia del navegador. Entonces todo lo que tienes que hacer es ejecutar node index.js en el terminal.

Así de sencillo. Ahora debería ver un nuevo archivo llamado screenshot.png en la carpeta del proyecto.

Enviar un formulario

Si, por alguna razón, el sitio web que desea raspar no muestra el contenido a menos que haya iniciado sesión, puede automatizar el proceso de inicio de sesión con Puppeteer.

En primer lugar tenemos que inspeccionar el sitio web que estamos raspando y encontrar los campos de inicio de sesión. Podemos hacerlo haciendo clic con el botón derecho en el elemento y eligiendo la opción Inspeccionar.

blog-image

En mi caso, las entradas están dentro de un formulario con la clase login-form. Podemos introducir las credenciales de inicio de sesión utilizando el método type().

Además, si quieres asegurarte de que realiza las acciones correctas, puedes añadir el parámetro headless y ponerlo a false cuando lances la instancia de Puppeteer. Entonces verás como Puppeteer hace todo el proceso por ti.

const puppeteer = require('puppeteer')

async function login() {
try {
const URL = 'https://old.reddit.com/'
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()

await page.goto(URL)

await page.type('.login-form input[name="user"]', 'EMAIL@gmail.com')
await page.type('.login-form input[name="passwd"]', 'PASSWORD')

await Promise.all([
page.click('.login-form .submit button'),
page.waitForNavigation(),
]);

await browser.close()

} catch (error) {
console.error(error)
}
}

login()

Para simular un clic de ratón podemos utilizar el método click(). Después de hacer clic en el botón de inicio de sesión, debemos esperar a que se cargue la página. Podemos hacerlo con el método waitForNavigation().

Si hemos introducido las credenciales correctas, ya deberíamos estar conectados.

Raspar varias páginas

Usaré el subreddit /r/learnprogramming para este artículo. Así que queremos navegar a la página web, agarrar el título y la URL de cada post. Usaremos el método evaluate() para eso.

El código debería tener este aspecto:

const puppeteer = require('puppeteer')

async function tutorial() {
try {
const URL = 'https://old.reddit.com/r/learnprogramming/'
const browser = await puppeteer.launch()
const page = await browser.newPage()

await page.goto(URL)
let data = await page.evaluate(() => {
let results = []
let items = document.querySelectorAll('.thing')
items.forEach((item) => {
results.push({
url: item.getAttribute('data-url'),
title: item.querySelector('.title').innerText,
})
})
return results
})

console.log(data)
await browser.close()

} catch (error) {
console.error(error)
}
}

tutorial()

Usando el método Inspect presentado anteriormente, podemos coger todos los posts apuntando al selector .thing. Iteramos a través de ellos, y para cada uno, obtenemos la URL y el título y los empujamos en una matriz.

Una vez completado todo el proceso, podrá ver el resultado en su consola.

blog-image

Genial, hemos raspado la primera página. Pero, ¿cómo raspamos varias páginas de este subreddit?

Es más sencillo de lo que crees. Aquí está el código:

const puppeteer = require('puppeteer')

async function tutorial() {
try {
const URL = 'https://old.reddit.com/r/learnprogramming/'
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()

await page.goto(URL)
let pagesToScrape = 5;
let currentPage = 1;
let data = []
while (currentPage <= pagesToScrape) {
let newResults = await page.evaluate(() => {
let results = []
let items = document.querySelectorAll('.thing')
items.forEach((item) => {
results.push({
url: item.getAttribute('data-url'),
text: item.querySelector('.title').innerText,
})
})
return results
})
data = data.concat(newResults)
if (currentPage < pagesToScrape) {
await page.click('.next-button a')
await page.waitForSelector('.thing')
await page.waitForSelector('.next-button a')
}
currentPage++;
}
console.log(data)
await browser.close()
} catch (error) {
console.error(error)
}
}

tutorial()

Necesitamos una variable para saber cuántas páginas queremos raspar y otra variable para la página actual. Mientras que la página actual es menor o igual que el número de páginas que queremos raspar, obtenemos la URL y el título de cada entrada de la página. Una vez obtenida cada página, concatenamos los nuevos resultados con los ya obtenidos.

A continuación, hacemos clic en el botón de página siguiente y repetimos el proceso de raspado hasta alcanzar el número deseado de páginas extraídas. También necesitamos incrementar la página actual después de cada página.

Una opción aún más sencilla

¡Enhorabuena! Has construido con éxito tu propio raspador web con Puppeteer. Espero que hayas disfrutado del tutorial.

Aún así, el script que creamos en esta guía no puede hacer mucho trabajo duro. Le faltan algunos aspectos clave que hacen que el web scraping sea impecable. Usar proxies móviles o residenciales y resolver CAPTCHAs son sólo algunas de las funcionalidades que faltan.

Si buscas una forma más profesional de extraer datos, echa un vistazo a lo que WebScrapingAPI puede conseguir y comprueba si te conviene. Hay un paquete gratuito, así que solo tienes que invertir 30 minutos de tu tiempo.

¡Feliz web scraping!

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
GuíasAprenda a eludir la detección de Cloudflare con el mejor navegador Selenium

Conozca cuál es el mejor navegador para eludir los sistemas de detección de Cloudflare mientras hace web scraping con Selenium.

Mihnea-Octavian Manolache
avatar de autor
Mihnea-Octavian Manolache
9 min leer
miniatura
GuíasCómo construir un rascador y descargar un archivo con Puppeteer

Descubra 3 maneras de descargar archivos con Puppeteer y construya un raspador web que haga exactamente eso.

Mihnea-Octavian Manolache
avatar de autor
Mihnea-Octavian Manolache
8 min leer
miniatura
GuíasLa guía definitiva de scraping web y automatización de Playwright para 2023

Aprenda a utilizar Playwright para el scraping web y la automatización con nuestra completa guía. Desde la configuración básica hasta las técnicas avanzadas, esta guía lo abarca todo.

Suciu Dan
avatar de autor
Suciu Dan
16 min leer