Volver al blog
Guías
Mihnea-Octavian Manolache28 de febrero de 20237 min de lectura

Cómo crear un scraper y enviar un formulario con Puppeteer

Cómo crear un scraper y enviar un formulario con Puppeteer

¿Qué es Puppeteer y por qué es importante para el web scraping?

En general, el web scraping se refiere al proceso de automatizar la extracción de datos de varios servidores. Antiguamente, un simple cliente HTTP habría bastado para realizar esta tarea. Hoy en día, sin embargo, los sitios web dependen cada vez más de JavaScript. Y los clientes HTTP tradicionales son incapaces de procesar archivos JavaScript. Aquí es donde Puppeteer entra en juego.

Puppeteer es una librería Node.js que te permite controlar un navegador Chrome o Chromium headless a través del protocolo DevTools. En resumen, proporciona una API de alto nivel para automatizar Chrome.

En términos de raspado web, Puppeteer es útil para raspar sitios web que requieren JavaScript para ser renderizados. Además, también se puede utilizar para interactuar con las páginas web de una manera similar a un ser humano. Por ejemplo, haciendo clic en botones o, lo que nos interesa hoy, rellenando formularios. Esto lo hace ideal para el scraping de sitios web que utilizan técnicas anti-scraping.

Creación de un proyecto Puppeteer sencillo

Creo en tomar las cosas con calma para una mejor comprensión del proceso en general. Antes de entrar en cómo enviar el formulario con Puppeteer, vamos a hablar de Puppeteer simple. En esta sección, voy a mostrarte como configurar un proyecto Node, instalar Puppeteer, y usarlo para scrapear datos. Asi que, lo primero, vamos a crear una nueva carpeta y abrirla dentro de nuestro IDE deseado. Yo prefiero Visual Studio Code pero siéntete libre de usar lo que quieras.

¿Lo sabías?

  • Puedes crear una nueva carpeta "programáticamente" desde tu terminal escribiendo el comando `mkdir`.
  • Puedes utilizar el comando `npm init -y` para configurar un proyecto node y aceptar los valores por defecto
  • Puede crear un nuevo archivo con el comando `touch`.
  • También puede abrir VSCode con el comando `code .`.

Si quieres, puedes combinar los cuatro e hilar un proyecto en cuestión de segundos como éste:

~ " mkdir scraper && cd scraper && npm init -y && code . 

Dentro de tu IDE, abre un nuevo terminal (Terminal > Nuevo terminal) y vamos a instalar Puppeteer. Escribe `npm i puppeteer --save` en el terminal. Por cierto, prefiero usar módulos JS en lugar de CommonJS. Echa un vistazo a las diferencias entreambos aquí. Si tú también quieres usar módulos, abre el archivo `package.json` y añade `"type": "module"` al objeto JSON.

VS Code mostrando un archivo package.json y un comando de terminal para instalar Puppeteer con npm

Ahora que ya tenemos todo listo, podemos empezar a añadir algo de código. Crea un nuevo archivo `index.js` y ábrelo en el IDE. No es necesario hacerlo desde la terminal esta vez, pero como pista, puedes usar el comando `touch`. Ahora vamos a añadir el código:

import puppeteer, { executablePath } from 'puppeteer'

const scraper = async (url) => {

   const browser = await puppeteer.launch({

       headless: false,

       executablePath: executablePath(),

   })

   const page = await browser.newPage()

   await page.goto(url)

   const html = await page.content()

   await browser.close()

   return html

}

Y veamos lo que estamos haciendo:

  • Estamos importando Puppeteer y `executablePath` en nuestro proyecto
  • Estamos definiendo una nueva función, que toma un parámetro `url`.
  • Vamos a iniciar un nuevo navegador utilizando `puppeteer.launch` a. Especificamos que queremos que se ejecute en modo «headful» b. Utilizamos `executablePath` para obtener la ruta de Chrome
  • Abrimos una nueva página y navegamos a la `url`.
  • Estamos guardando el `page.content()` en una constante
  • Cerramos la instancia del navegador
  • Y por último, devolvemos la salida `html` de la página que acabamos de raspar

Hasta aquí las cosas no son complicadas. Esto es lo minimo para implementar un web scraper con Node JS y Puppeteer. Si quieres ejecutar el codigo, simplemente dale a la funcion `scraper` un objetivo y registra su valor de retorno:

console.log(await scraper('https://webscrapingapi.com/'))

Pero recuerde que nuestro objetivo es extraer datos al enviar un formulario. Esto significa que tenemos que pensar en una manera de enviar el formulario con Puppeteer. Por suerte, lo he hecho antes y sé que no es difícil. Asi que veamos como puedes hacerlo tu tambien.

Cómo enviar formularios con Puppeteer

Piense en Puppeteer como el medio para imitar el comportamiento humano en un sitio web determinado. ¿Cómo nosotros, los humanos, enviamos formularios? Bueno, identificamos el formulario, lo rellenamos y normalmente pulsamos un botón. Esa es la misma lógica utilizada para enviar formularios con Puppeteer. La única diferencia es cómo realizamos estas acciones. Porque los humanos nos basamos en los sentidos. Como Puppeteer es software, lo haremos programáticamente, usando los métodos incorporados de Puppeteer, así:

#1: Envíe formularios sencillos con Puppeteer

Lo primero es lo primero, tenemos que "visualizar" nuestro formulario. En un sitio web, todos los elementos se agrupan en un bloque HTML y cada elemento tiene un identificador. Los identificadores suelen consistir en atributos CSS del elemento. Sin embargo, es posible que te encuentres con sitios web que no tienen este tipo de selectores. En estos casos, puedes utilizar xPaths, por ejemplo. Pero ese es un tema para otra charla. Centrémonos en identificar elementos en Puppeteer usando CSS.

Para tener un poco de antecedentes, digamos que queremos automatizar la acción de inicio de sesión en Stack Overflow. Así que el objetivo es https://stackoverflow.com/users/login. Abre tu navegador, navega a la página de inicio de sesión, y abre Herramientas de Desarrollador. Puedes hacer clic derecho en la página y seleccionar 'Inspeccionar'. Deberías ver algo como esto:

Formulario de inicio de sesión de Stack Overflow junto a Chrome DevTools, que resalta los elementos HTML correspondientes a los campos del formulario

A la izquierda hay una interfaz gráfica. A la derecha, la estructura HTML. Si se fija bien en la parte derecha, verá nuestro formulario. Consta principalmente de dos entradas y un botón. Estos son los tres elementos a los que nos dirigimos. Y como puedes ver, los tres elementos tienen un `id` como identificador CSS. Traduzcamos lo que hemos aprendido hasta ahora en código:

import puppeteer, { executablePath } from 'puppeteer'

const scraper = async (target) => {

   const browser = await puppeteer.launch({

       headless: false,

       executablePath: executablePath(),

   })

   const page = await browser.newPage()

   await page.goto(target.url,{waitUntil: 'networkidle0'})

   await page.type(target.username.selector, target.username.value)

   await page.type(target.password.selector, target.password.value)

   await page.click(target.buttonSelector)

   const html = await page.content()

   await browser.close()

   return html

}

Para mantenerlo funcional y reutilizable, elegí reemplazar el parámetro de mi función por un objeto. Este objeto consiste en la URL de destino, los selectores de entrada y los valores, y el selector para el botón de envío. Por lo tanto, para ejecutar el código, basta con crear un nuevo objeto `TARGET` que contenga tus datos, y pasarlo a tu función `scraper`:

const TARGET = {

   url: 'https://stackoverflow.com/users/login',

   username: {

       selector: 'input[id=email]',

       value: '<YOUR_USERNAME>'

   },

   password: {

       selector: 'input[id=password]',

       value: '<YOUR_PASSWORD>'

   },

   buttonSelector: 'button[id=submit-button]'

}

console.log(await scraper(TARGET))

#2: Cargar archivos con Puppeteer

A veces, la automatización web requiere que subamos archivos, en lugar de enviar simples formularios. Si te encuentras con una tarea de este tipo y necesitas adjuntar archivos antes de enviar el formulario con Puppeteer, querrás hacer uso del método `uploadFile` de Puppeteer. Para mantener las cosas simples, le sugiero que cree una nueva función para esta acción:

const upload = async (target) => {

   const browser = await puppeteer.launch({

       headless: false,

       executablePath: executablePath(),

   })

   const page = await browser.newPage()

   await page.goto(target.url,{waitUntil: 'networkidle0'})

   const upload = await page.$(target.form.file)

   await upload.uploadFile(target.file);

   await page.click(target.form.submit)

  

   await browser.close()

}

Mira como esta vez estoy usando `page.$` para identificar primero el elemento. Y sólo después de eso, estoy llamando a la `uploadFile` método que sólo funciona en `ElementHandle` tipos. En cuanto a los parámetros, igual que antes, estoy usando un objeto para pasar todos los datos a la vez a mi función. Si quieres probar el script, simplemente añade el siguiente código y ejecuta `node index.js` en tu terminal:

const TARGET = {

   url: 'https://ps.uci.edu/~franklin/doc/file_upload.html',

   form: {

       file: 'input[type=file]',

       submit: 'input[type=submit]'

   } ,

   file: './package.json'

}

upload(TARGET)

Conclusiones

Resumiendo, diría que es bastante fácil enviar el formulario con Puppeteer. Además, encuentro que comparado con sus alternativas, Puppeteer maneja completamente esta acción. Básicamente, todo lo que el usuario tiene que hacer es identificar correctamente los elementos.

Ahora bien, debo señalar que un rastreador en el mundo real requiere mucho más para ser eficiente. La mayoría de las veces, si «abuses» de un servidor enviando demasiados formularios en un breve periodo de tiempo, es probable que te bloqueen. Por eso, si quieres automatizar el proceso de envío de formularios, te recomiendo utilizar un servicio profesional de rastreo. En Web Scraping API, ofrecemos la opción de enviar solicitudes POST y PUT. Puedes obtener más información al respecto en nuestra documentación.

Acerca del autor
Mihnea-Octavian Manolache, desarrollador full stack en WebScrapingAPI
Mihnea-Octavian ManolacheDesarrollador Full Stack

Mihnea-Octavian Manolache es ingeniero Full Stack y DevOps en WebScrapingAPI, donde se encarga de desarrollar funciones para los productos y de mantener la infraestructura que garantiza el buen funcionamiento de la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.