This page looks best with JavaScript enabled

NodeJS/Puppeteer

 ·  🎃 kr0m

Automating actions on web interfaces is a very interesting field. In a previous article, we explained how to do it using Python/Selenium. This time, we will use NodeJS/Puppeteer. The example will log in to a web form and then click on a specific button.

You can find the project on Github: https://github.com/puppeteer/puppeteer

Install Node.js:

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()
})()

NOTE: A slow motion slowMo: 50 has been introduced to make the behavior appear more human-like, and a delay await delay(4000) has been added to allow the web to fully load before performing the click.

To test it, simply execute it as follows:

node login.js

If you liked the article, you can treat me to a RedBull here