Esta pagina se ve mejor con JavaScript habilitado

NodeJS/Puppeteer

 ·  🎃 kr0m

La automatización de acciones en interfaces web es un campo muy interesante, en un artículo anterior ya explicamos como hacerlo mediante Python/Selenium, en esta ocasión utilizaremos NodeJS/Puppeteer. El ejemplo hará login en un formulario web y acto seguido clickará sobre un botón determinado.

Podemos encontrar el proyecto en Github: https://github.com/puppeteer/puppeteer

Instalamos nodejs:

pkg install npm-node12
emerge -av net-libs/nodejs

Instalamos puppeteer como usuario regular, este intentará descargar una copia de Chrome pero en FreeBSD se queja de que no es una plataforma soportada:

Error: Unsupported platform: freebsd

Para solventarlo tan solo debemos instalarlo indicando que no queremos descargar ninguna copia de Chrome, ya que nosotros ya disponemos de una en local instalada por sl sistema operativo:

PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true npm install puppeteer
npm install puppeteer

En mi caso utilizo esta extensión de Chrome para crear el script base y a partir de este ir adaptándolo a mis necesidades:
https://chrome.google.com/webstore/detail/puppeteer-recorder/djeegiggegleadkkbgopoonhjimgehda

El script final quedaría del siguiente modo:

vi login.js

const puppeteer = require('puppeteer');
function delay(time) {
   return new Promise(function(resolve) {
       setTimeout(resolve, time)
   });
}

(async () => {
  //const browser = await puppeteer.launch({headless: false, slowMo: 50})
  //const browser = await puppeteer.launch({headless: true, slowMo: 50})
  const browser = await puppeteer.launch({headless: true, slowMo: 50, executablePath: '/usr/local/bin/chrome'})

  const page = await browser.newPage()
  
  const navigationPromise = page.waitForNavigation()
  await page.goto('URL')
  
  await page.setViewport({ width: 1919, height: 993 })
  
  await navigationPromise

  await page.waitForSelector('.card-content > .mat-form-auth > .w-100:nth-child(1) > .mat-form-field-wrapper > .mat-form-field-flex')
  await page.click('.card-content > .mat-form-auth > .w-100:nth-child(1) > .mat-form-field-wrapper > .mat-form-field-flex')
  
  await page.type('.w-100 #mat-input-0', 'EMAIL')

  await page.waitForSelector('.w-100 #mat-input-1')
  await page.click('.w-100 #mat-input-1')
  await page.type('.w-100 #mat-input-1', 'PASSWORD')

  await page.waitForSelector('.card > .card-content > .mat-form-auth > .float-right > .mat-button-wrapper')
  await page.click('.card > .card-content > .mat-form-auth > .float-right > .mat-button-wrapper')

  await delay(4000);

  await page.waitForSelector('.card-body > .ml-2 > .mat-fab > .mat-button-wrapper > .mat-icon')
  await page.click('.card-body > .ml-2 > .mat-fab > .mat-button-wrapper > .mat-icon')
   
  await browser.close()
})()

NOTA: Se ha intriducido un slowmotion slowMo: 50 para que el comportamiento parezca mas humano y un delay await delay(4000) para que la web cargue por completo antes de realizar el click.

Para probarlo tan solo hay que ejecutarlo del siguiente modo:

node login.js

Si te ha gustado el artículo puedes invitarme a un RedBull aquí