¿ Cómo hacer una api para tomar captura a un website ?

Podemos hacerlo, con Puppeteer, Vercel y café. Estaremos ejecutando una instancia de Chrome en una función serverless que se ejecuta en cada request qué hacemos, está potente, lo sé. Pero hagámoslo “por la anécdota” : ). Además así aprendemos juntos y aprovechamos a jugar un poco con las funciones serverless de Vercel.

Vercel , una compañia latinoamérica fundada por Guillermo Rauch. Es una plataforma de servicios serverless (similar a Netlify) muy, muy popular en el mundo dev ^^.

La imágen de cover(La misma del SEO) es la captura actual del ejemplo funcional

Iniciemos

Primero, los recursos necesarios. Para hacer este proyecto necesitaremos:

  • NodeJS
  • Npm (Yarn ?)
  • Una cuenta en Vercel
  • Vercel CLI
  • Un editor de texto (VsCode)
  • Navegador ?

Nodejs

Para instalarlo recomiendo usar NVM(Node Version Manager). Acá los scripts de instalación: https://github.com

Npm

Si instalamos una versión de Node mayor o igual a la 10.x vendrá npm por default, así que saltemos este paso

Si usas una versión menor a la 10.x lee un poco acá de cómo poder instalarlo: https://npmjs.com . psst, si usas una distro de ubuntu hace: sudo apt install npm

Cuenta en vercel

Crea tu cuenta en este link: https://vercel.com

Vercel CLI

npm i -g vercel

Shut up, show me the code

Okay, okay, ahora sí, veamos código.

Recuerdas lo que mencioné de que estaríamos instanciando Chrome dentro de una función serverless ?. Ahora te explicare un poco de porque es posible.

Google tiene un producto llamado Puppeteer, es un navegador headless que corre con Chromium. te da un montón de API’s para que podás controlarlo en NodeJs.

A pesar de ser “headless” ( Que corre sin UI ) necesitamos los binarios de dicho navegador para que funcione. Eso agrega peso a nuestro límite de 50MB permitido por las funciones lambda.

No solamente eso, un proyecto en Puppeteer con todas las dependencias pesaría más de 150MB, eso no lo hace posible para correr en una lambda. Bien, cómo lo solucionamos ? … Hay muchas versiones de “forks” de puppeteer para agregar a tus funciones y además para las distintas Clouds que existen (GCP, AWS, etc).

Para esta ocasión estaremos usando un módulo llamado “chrome-aws-lambda” y no usaremos la versión completa de puppeteer, más bien solamente su núcleo, con el paquete “puppeteer-core”

Carpeta del proyecto

Creamos la carpeta en dónde vivirá nuestra app : )

mkdir puppeteer-vercel-cap && cd puppeteer-vercel-cap

Iniciando nuestro proyecto

npm init -y

Este comando iniciará un proyecto para usar npm y tomará la ruta dónde estemos para su configuración

sudo npm install --save chrome-aws-lambda

Instalamos chrome-aws-lambda

sudo npm install --save puppeteer-core

Instalamos puppeteer-core

Ahora , a hacer link con nuestro proyecto en vercel

vercel

En consola se mostrará un url, prueba si esta todo bien y continuemos.

Creamos la ruta dónde estará nuestra api

mkdir api

La documentación de Vercel se dice que todas las rutas/archivos dentro de esta carpeta se servirán en nuestro website, por ejemplo el archivo api/hola.js , estará disponible para nosotros en un url cómo: https://URL_BASE/api/hola

Para esta ocasión lo que haremos será nombrar nuestro archivo cómo index.js así estará disponible cómo el índice en nuestra ruta /api

nano api/index.js

Ahora copiamos el código ejemplo para tomar la captura.

const chromium = require("chrome-aws-lambda")
const URL = `https://vercel.com/home`
const SEO_RESOLUTION = { width: 1200, height: 630 }
module.exports = async (req, res) => {
  const browser = await chromium.puppeteer.launch({
    args: [...chromium.args, "--hide-scrollbars", "--disable-web-security"],
    defaultViewport: chromium.defaultViewport,
    executablePath: await chromium.executablePath,
    headless: true,
    ignoreHTTPSErrors: true,
  })
  const page = await browser.newPage()
  page.setViewport(SEO_RESOLUTION)
  await page.goto(URL, { waitUntil: "networkidle0" })
  const screenShotBuffer = await page.screenshot()
  res.writeHead(200, {
    "Content-Type": "image/png",
    "Content-Length": Buffer.byteLength(screenShotBuffer),
  })
  res.end(screenShotBuffer)
}

  • Para pegar en consola hace CTRL + SHIFT + v
  • Para guardar los cambios: CTRL + o , luego ENTER y por último para salir CTRL + x
  • Si quieres ver si todo se escribió correctamente ejecutá: cat api/index.js

Por cierto, en este caso cómo ejemplo tomaremos la captura al home de Vercel: https://vercel.com . Puedes cambiarlo si gustas : ).

Corriendo la versión de prueba (En tu PC)

vercel dev

Esto iniciará un server en tu PC en el puerto 3000. Para ver si todo anda bien xD, puedes testear acá: http://localhost:3000/api

Just ship it 🚀!

vercel --prod

Esto iniciará el proceso para crear una URL pública para compartir con tus amigos del proyecto : ‘ )

Fin 😭?

Eso es todo amigos, muchas gracias por tu lectura ^^ . Te pido compartas esto con tus conocidos si te gustó y si no te gustó, también, así los molestas : )

Por cierto este ejemplo abre la ventana a muchaaas cosas. Reportes, imágenes que se actualizan en cada fetch ( cómo los trucos en github y perfiles con data que casi son dashboards ). Creación de imágenes con datos personalizables, tests serverless de UI, scrappers, etc, etc, etc.

Ejemplo funcional: https://puppeteer-vercel-screenshot.vercel.app

Ver el código del proyecto en Github

PD: El código en Github está un poco más “documentado”, 😁

👋HEY
WANNA READ MORE STUFF ?

Sure, take me there