Encontrei a ferramenta perfeita para criação de web crawler, o puppeteer é a lib certa para criar robôs de forma fácil e rápida !

Eu já mostrei para vocês como fazer um web crawler usando javascript e nodeJS. Nesse projeto fizemos um crawler muito simples que pegava a previsão do tempo informando se o dia será de sol ou chuva. O código desse ultimo post funciona para a maioria dos projeto, mas imagine que você quer fazer a raspagem de um site que precisa de login.

“Então, COMO FARIA RASPAGEM/SACRPING em um site que precisa de login ??” é isso que vamos aprender aqui hoje usando uma lib sensacional !!

O que é o puppeteer  ?

Primeiramente vou te apresentar essa maravilha chamada puppeteer. De forma geral, o puppeteer pode controlar um navegador como o chromium através do node. Com ele você pode injetar scripts para tomar ações em qualquer site ou para coletar informações. É como ligar o crome e rodar o script que você fez direto no console.

Você pode ler mais sobre o projeto no repositório oficial deles clicando bem aqui.

O projeto InstaBot

Já faz um bom tempo que eu quero criar algo sólido para o instagram. Eu queria muito criar um bot que fosse capaz de interagir no instagram como se fosse um usuário. Mas para isso eu preciso coletar uma quantidade muito grande de dados e ensinar muita coisa para uma IA. Porém, a vontade de fazer algo sólido ainda é mais forte. Nesse projeto nos vamos fazer login em uma conta do instagram e coletar algumas informações do seu usuário. (Na verdade eu queria muito fazer um bot para seguir pessoas mas acho que fere as políticas de uso do insta. Então não vai rolar).

Como eu não quero prejudicar ou ferir nenhuma política de uso, nesse artigo vamos nos limitar apenas em pegar algumas informações da nossa conta.

O que é um browser Headless?

Um Browser Headless é um tipo de navegador que não tem uma interface gráfica, porém, ainda funciona como um navegador. Basicamente ele te permite acessar páginas web através de linhas de código.

Para exemplificar: Imagine que você acessa a página do google.com. Para isso você abre seu navegador, digitar google.com na barra de busca e imediatamente a página é carregada. Você só vê a parte visual de tudo mas o seu navegador fez muita coisa para te mostrar essa página.

  1. Ele baixa o HTML onde está hospedado a página
  2. Analisa o HTML para encontrar imagens, fontes, javascripts, css e qualquer outro arquivo que precisa ser baixado
  3. Baixa todos esse arquivos e processa cada um deles.
  4. Carrega e executa/renderiza imagens e js
  5. e pronto, página carregada…

Um  browser headless faz isso tudo mas não mostra o resultado visual da página já que o foco é apenas o código. Dessa forma evitamos algumas etapas que podem geral alguns megas a mais na nossa memória. Além disso, os browsers headless geralmente permite um melhor controle do que é feito no lado cliente, ou seja, você consegue executar ações de forma mais fáceis utilizando linhas de código.

Iniciando um projeto com Puppeteer

Para esse projeto vamos fazer apenas o básico e uma demonstração de como fazer login no instagram usando o Puppeteer. Na verdade, o método que você vai aprender serve para qualquer site.

Vamos começar criando um novo projeto instalando o Puppeteer usando yarn init -y  && yarn add puppeteer

Você pode usar o NPM se preferir…

Legal, agora com os pacotes instalados é hora de começar a programar. Crie um novo documento chamado index.js

Vamos importar o puppeteer usando requires. Vamos criar também uma função anônima para executar assim que o arquivo for carregado.

const puppeteer = require("puppeteer");

(async () => {

// Code ...
  
})();

Ok, agora vamos fazer o puppeteer abrir o browser em uma página específica. no nosso caso a página de login do instagram. Para fazer isso vamos instanciar um browser e em seguida usar o métodos de carregamento de página. Isso seria equivalente a abrir o chrome e acessar o instagram.com só que através de código.

const puppeteer = require("puppeteer");

(async () => {
 // Criar uma instância para um browser
 const browser = await puppeteer.launch({
  headless: false, // Essa opção abre o uma janela do navegador
  args: ["--no-sandbox"],
});

// literalmente a página
const page = await browser.newPage();

// Acessa a página do instagram.
await page.goto("https://www.instagram.com", { waitUntil: "networkidle0" });

})();

Repare que na linha 6 eu coloco a opção headless como false Isso por que eu quero ver o navegador sendo aberto e se mexendo sozinho. Você pode mudar para true e esperar o resultado.

Fazendo login no instagram com web crawler

Agora que já entramos na página de login o próximo passo seria digitar nosso login, nossa senha e apertar o botão Entrar. O puppeteer tem alguns método para lidar com esse tipo de interação de forma mais fácil.

const puppeteer = require("puppeteer");

(async () => {
 // Criar uma instância para um browser
 const browser = await puppeteer.launch({
  headless: false, // Essa opção abre o uma janela do navegador
  args: ["--no-sandbox"],
});

// literalmente a página
const page = await browser.newPage();

// Acessa a página do instagram.
await page.goto("https://www.instagram.com", { waitUntil: "networkidle0" });
await page.waitFor(2500); // espera 2 segundo e meio para a próxma linha 

await page.click(`input[type="text"]`); // Da um click falso no input de login
await page.keyboard.type("MEU_LOGIN_DO_INSTA"); // digita uma string no input
await page.click('input[type="password"]'); //Da um click falso no input de sennha
await page.keyboard.type("MINHA_SENHA"); // digita uma string no input

await page.click(".L3NKy"); // Clica em um elemento HTML cujo a classe é ".L3NKy"

})();

SHOW !!! Se tudo deu certo até aqui você já é capaz de fazer login em qualquer site usando essa lindeza de lib. E é tudo bem simples como no código acima. Você só precisa fazer a seleção do elemento HTML assim como faria no console do navegador e depois injetar via código os textos corretos. Você pode usar esse mesmo método para logar no facebook, gmail ou qualquer outro lugar.

Navegando entre páginas usando web crawler

Legal, agora vamos navegar para a página de perfil de usuário, é nela que encontramos as informações básicas do seu perfil. Vamos extrair da página a quantidade de postagens, os numero de seguidores e o numero de pessoas sendo seguidas.

const puppeteer = require("puppeteer");

(async () => {
  // Criar uma instância para um browser
  const browser = await puppeteer.launch({
    headless: false, // Essa opção abre o uma janela do navegador
    args: ["--no-sandbox"],
  });

  // literalmente a página
  const page = await browser.newPage();

  // Acessa a página do instagram.
  await page.goto("https://www.instagram.com", { waitUntil: "networkidle0" });
  await page.waitFor(2500); // espera 2 segundo e meio para a próxma linha

  await page.click(`input[type="text"]`); // Da um click falso no input de login
  await page.keyboard.type("MEU_LOGIN_DO_INSTA"); // digita uma string no input
  await page.click('input[type="password"]'); //Da um click falso no input de sennha
  await page.keyboard.type("MINHA_SENHA"); // digita uma string no input
  await page.click(".L3NKy"); // Clica em um elemento HTML cujo a classe é ".L3NKy"

  await page.waitFor(2500);// espera 2 segundo e meio para a próxma linha


// ----- navegação 
  await page.click("button.aOOlW"); // Isso aqui é só para fechar um modal que aparece...

  await page.click("nav a._2dbep.qNELH.kIKUG"); // Clica em um elemento HTML, no caso o ícon que direciona para o nosso perfil.

  await page.waitForNavigation(); // Esspera a navegação terminar

// ----- navegação 
})();

O bloco de código extra é bem simples. Primeiro ele clica no botão fecha de um modal que costuma aparecer quando entramos no instagram pela web. Depois ele clica no ícone do “meu perfil”, esse ícone esta dentro de <nav> e é uma tag <a> com as classes _2dbep .qNELH .kIKUG por fim ele espera a navegação ser concluída.

Agora vamos pegar as informações da página usando os seletores de javascript. Por fim retornar tudo em um objeto e fechar o browser.

const puppeteer = require("puppeteer");

(async () => {
  ....

  // O metodo evaluate permite rodar scripts JS dentro da página.
  // Usando uma função de call back 
  let data = await page.evaluate(() => {
    const infos = document.querySelectorAll(".g47SY"); // Pega todos os valores contidos .g47SY e distribui em um array

    const posts = infos[0].textContent;
    const followers = infos[1].textContent;
    const following = infos[2].textContent;

    return {
      posts,
      followers,
      following,
    };
  });
  console.log(data);

  await browser.close();
  
})();

Se tudo der certo até aqui você deve ter un web crawler que abre um navegador, faz login no instagram, navega até a página de perfil e pega as informações básicas da conta. Isso tudo é fantástico!!

O código final fica assim …

const puppeteer = require("puppeteer");
require('dotenv').config({path: __dirname + '/.env'});

(async () => {
  
  const browser = await puppeteer.launch({
    headless: false, // Essa opção abre o uma janela do navegador
    args: ["--no-sandbox"],
  });

  const page = await browser.newPage();

  // Acessa a página do instagram.
  await page.goto("https://www.instagram.com", { waitUntil: "networkidle0" });
  await page.waitFor(2500); // espera 2 segundo e meio para a próxma linha

  await page.click(`input[type="text"]`);
  await page.keyboard.type(process.env.LOGIN); // digita uma string no input
  await page.click('input[type="password"]'); //Da um click falso no input de sennha
  await page.keyboard.type(process.env.PASSW); // digita uma string no input
  await page.waitFor(2500);
  
  await page.click(".L3NKy"); 
  await page.waitFor(2500);
  await page.click("button.aOOlW"); 
  await page.click("nav a._2dbep.qNELH.kIKUG"); 
  await page.waitForNavigation();

  let data = await page.evaluate(() => {
    const infos = document.querySelectorAll(".g47SY"); 

    const posts = infos[0].textContent;
    const followers = infos[1].textContent;
    const following = infos[2].textContent;

    return {
      posts,
      followers,
      following,
    };
  });
  console.log(data);

  await browser.close();
  
})();

 

Conclusão

Eu fico muito impressionado com o nível de abstração de algumas bibliotecas. O verdadeiro papel de uma lib é facilitar o trabalho duro e repetitivo de uma aplicação específica e nesse quesito os desenvolvedores do puppeteer mandaram muuuito bem. O que você achou desse tutorial ? Manda sua opinião nos comentários !!