Volver al blog
Guías
Mihnea-Octavian ManolacheLast updated on Mar 31, 20266 min read

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

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

¿Alguna vez has tenido que trabajar con solicitudes POST al extraer datos de la web? ¡Seguro que sí! Y la mayoría de las veces se trata de formularios. Por eso, hoy voy a hablar de cómo enviar un formulario con Puppeteer. Si aún no sabes qué es Puppeteer, no te preocupes. Lo descubrirás en un momento. Hasta entonces, déjame establecer algunas expectativas para el artículo de hoy. Si me sigues en nuestro recorrido de aprendizaje, hoy deberías poder aprender:

  • Qué es Puppeteer en el web scraping
  • Cómo configurar un proyecto sencillo con Puppeteer
  • Cómo se gestiona el envío de formularios en Puppeteer

Así que, sin más preámbulos, ¡vamos a ello!

¿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 diversos servidores. Antiguamente, un simple cliente HTTP habría sido suficiente 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 renderizar archivos JavaScript. Ahí es donde entra en juego Puppeteer.

Puppeteer es una biblioteca de Node.js que te permite controlar un navegador Chrome o Chromium sin interfaz gráfica a través del protocolo DevTools. En resumen, proporciona una API de alto nivel para automatizar Chrome.

En lo que respecta al web scraping, Puppeteer resulta útil para extraer datos de sitios web que requieren la ejecución de JavaScript. Además, también se puede utilizar para interactuar con páginas web de una forma similar a como lo haría un ser humano. Por ejemplo, haciendo clic en botones o, como es el caso que nos ocupa hoy, rellenando formularios. Esto lo hace ideal para extraer datos de sitios web que utilizan técnicas anti-scraping.

Configuración de un proyecto sencillo con Puppeteer

Creo que es mejor ir poco a poco para comprender mejor el proceso en su conjunto. Antes de entrar en cómo enviar el formulario con Puppeteer, hablemos de Puppeteer en general. En esta sección, te voy a mostrar cómo configurar un proyecto Node, instalar Puppeteer y utilizarlo para extraer datos. Así que, lo primero es lo primero: creemos una nueva carpeta y abrámosla en nuestro IDE preferido. Yo prefiero Visual Studio Code, pero puedes usar el que quieras.

¿Sabías que...?

  • Puedes crear una nueva carpeta «programáticamente» desde tu terminal escribiendo el comando `mkdir`.
  • Puedes usar el comando `npm init -y` para configurar un proyecto Node y aceptar los valores predeterminados
  • Puedes crear un nuevo archivo con el comando `touch`.
  • Y también puedes abrir VSCode con el comando `code .`.

Si quieres, puedes combinar los cuatro y poner en marcha un proyecto en segundos de esta manera:

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

Dentro de tu IDE, abre un nuevo terminal (Terminal > Nuevo terminal) e instalemos Puppeteer. Escribe `npm i puppeteer --save` en tu terminal. Además, me gusta usar módulos JS en lugar de CommonJS. Echa un vistazo a las diferencias entre ambos aquí. Si tú también quieres usar módulos, abre `package.json` y añade `"type": "module"` al objeto JSON.

Ahora que ya lo tenemos todo listo, podemos empezar a añadir código. Crea un nuevo archivo `index.js` y ábrelo en el IDE. Esta vez no hace falta hacerlo desde la terminal, pero como sugerencia, podrías usar el comando `touch`. Ahora añadamos 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 qué estamos haciendo:

  • Estamos importando Puppeteer y `executablePath` a nuestro proyecto
  • Estamos definiendo una nueva función que toma un parámetro `url`
  • Estamos iniciando un nuevo navegador usando `puppeteer.launch` a. Estamos especificando que queremos que se ejecute en modo head-first b. Estamos usando `executablePath` para obtener la ruta de Chrome
  • Abrimos una nueva página y navegamos a la `url`
  • Guardamos `page.content()` en una constante
  • Cerramos la instancia del navegador
  • Y, por último, devolvemos el resultado `html` de la página que acabamos de rastrear

Hasta ahora, las cosas no son complicadas. Esto es lo mínimo indispensable para implementar un rastreador web con Node.js y Puppeteer. Si quieres ejecutar el código, simplemente pasa un objetivo a la función `scraper` y registra su valor de retorno:

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

Pero recuerda que nuestro objetivo es extraer datos al enviar un formulario. Esto significa que tenemos que pensar en una forma de enviar el formulario con Puppeteer. Por suerte, ya lo he hecho antes y sé que no es difícil. Así que veamos cómo puedes hacerlo tú también.

Cómo enviar formularios con Puppeteer

Piensa en Puppeteer como el medio para imitar el comportamiento humano en un sitio web determinado. ¿Cómo enviamos los formularios los humanos? Bueno, identificamos el formulario, lo rellenamos y, normalmente, hacemos clic en un botón. Esa es la misma lógica que se utiliza 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 un software, lo haremos mediante programación, utilizando los métodos integrados de Puppeteer, de la siguiente manera:

N.º 1: Enviar formularios sencillos con Puppeteer

Lo primero es lo primero: necesitamos «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 tales selectores. En tales casos, puedes utilizar xPaths, por ejemplo. Pero ese es un tema para otra charla. Centrémonos en identificar elementos en Puppeteer utilizando CSS.

Para tener algo de contexto, supongamos 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, ve a la página de inicio de sesión y abre las Herramientas de desarrollador. Puedes hacer clic con el botón derecho en la página y seleccionar «Inspeccionar». Deberías ver algo como esto:

En el lado izquierdo hay una interfaz gráfica. En el lado derecho, está la estructura HTML. Si miras con atención el lado derecho, verás nuestro formulario. Consiste principalmente en dos campos de entrada 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 que sea funcional y reutilizable, he optado por sustituir el parámetro de mi función por un objeto. Este objeto consta de la URL de destino, los selectores y valores de los campos de entrada, y el selector del botón de envío. Así pues, para ejecutar el código, solo tienes que 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: Subir archivos con Puppeteer

A veces, la automatización web nos obliga a subir 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, te interesará utilizar el método `uploadFile` de Puppeteer. Para simplificar las cosas, te sugiero que crees 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()

}

Fíjate en que esta vez estoy usando `page.$` para identificar primero el elemento. Y solo después de eso, llamo al método `uploadFile`, que solo funciona con tipos `ElementHandle`. En cuanto a los parámetros, al igual que antes, estoy usando un objeto para pasar todos los datos de una vez a mi función. Si quieres probar el script, solo tienes que añadir el siguiente código y ejecutar `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

En resumen, diría que es bastante fácil enviar el formulario con Puppeteer. Además, considero que, en comparación con sus alternativas, Puppeteer gestiona completamente esta acción. Básicamente, lo único que tiene que hacer el usuario es identificar correctamente los elementos.

Ahora bien, debo señalar que un scraper 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, probablemente te bloquearán. Por eso, si quieres automatizar el proceso de envío de formularios, te recomiendo utilizar un servicio de scraping profesional. En Web Scraping API, ofrecemos la opción de enviar solicitudes POST y PUT. Puedes leer más al respecto en nuestra documentación.

Acerca del autor
Mihnea-Octavian Manolache, Desarrollador Full Stack @ 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.