Web Scraping com Puppeteer Advanced Node.JS

Gabriel Cioci em Jul 28 2021

Em vez de utilizar ferramentas comerciais, muitos programadores preferem criar os seus próprios web scrapers. Embora os produtos disponíveis tenham caraterísticas mais completas, não podemos negar os resultados que estes bots podem trazer ou a diversão de fazer o seu próprio.

No artigo a seguir, você descobrirá as etapas a serem seguidas para criar seu próprio raspador da Web usando o Node.js e o Puppeteer. Vamos codificar um aplicativo que carrega um site, faz uma captura de tela, faz login no site usando um navegador headless e coleta alguns dados em várias páginas. A sua aplicação irá crescer em complexidade à medida que for progredindo.

Uma visão geral do Web Scraping com o Puppeteer

O Google projetou o Puppeteer para fornecer uma interface simples, mas poderosa, em Node.js para automatizar testes e várias tarefas usando o mecanismo do navegador Chromium. Ele é executado sem cabeça por padrão, mas pode ser configurado para executar o Chrome ou Chromium completo.

A API criada pela equipa do Puppeteer utiliza o protocolo DevTools para assumir o controlo de um navegador Web, como o Chrome, e executar diferentes tarefas, como:

  • Faça capturas de ecrã e crie PDFs de páginas
  • Automatizar o envio de formulários
  • Testes de IU (clicar em botões, introdução de dados pelo teclado, etc.)
  • Extrair um SPA e gerar conteúdo pré-renderizado (Server-Side Rendering)

A maioria das acções que pode fazer manualmente no browser também pode ser feita com o Puppeteer. Além disso, podem ser automatizadas para que possa poupar mais tempo e concentrar-se noutros assuntos.

O Puppeteer também foi construído para ser amigável ao desenvolvedor. As pessoas familiarizadas com outras estruturas de teste populares, como o Mocha, sentir-se-ão em casa com o Puppeteer e encontrarão uma comunidade ativa que oferece suporte para o Puppeteer. Isto levou a um enorme crescimento da popularidade entre os programadores.

É claro que o Puppeteer não é adequado apenas para testes. Afinal de contas, se ele pode fazer qualquer coisa que um navegador padrão pode fazer, então ele pode ser extremamente útil para raspadores da web. Nomeadamente, pode ajudar a executar código javascript para que o scraper possa alcançar o HTML da página e imitar o comportamento normal do utilizador, percorrendo a página ou clicando em secções aleatórias.

Estas funcionalidades tão necessárias fazem dos navegadores sem cabeça um componente essencial para qualquer ferramenta comercial de extração de dados e para todos os raspadores da Web, exceto os mais simples e caseiros.

Pré-requisitos

Antes de mais, certifique-se de que tem versões actualizadas do Node.js e do Puppeteer instaladas na sua máquina. Se não for esse o caso, pode seguir os passos abaixo para instalar todos os pré-requisitos.

Pode descarregar e instalar o Node.js a partir daqui. O gerenciador de pacotes padrão do Node, o npm, vem pré-instalado com o Node.js.

Para instalar a biblioteca Puppeteer, pode executar o seguinte comando no diretório raiz do seu projeto:

npm install puppeteer
# ou "yarn add puppeteer"

Tenha em atenção que quando instala o Puppeteer, este também descarrega a versão mais recente do Chromium que tem a garantia de funcionar com a API.

Marionetista em ação

Há muitas coisas diferentes que pode fazer com a biblioteca. Uma vez que o nosso foco principal é a recolha de dados da Web, vamos falar sobre os casos de utilização que mais provavelmente lhe interessam se quiser extrair dados da Web.

Tirar uma captura de ecrã

Vamos começar com um exemplo básico. Vamos escrever um script que tira uma captura de ecrã de um sítio Web à nossa escolha.

Tenha em mente que o Puppeteer é uma biblioteca baseada em promessas (ele executa chamadas assíncronas para a instância do Chrome sem cabeça sob o capô). Portanto, vamos manter o código limpo usando async/await.

Primeiro, crie um novo ficheiro chamado index.js no diretório raiz do seu projeto.

Dentro desse ficheiro, precisamos de definir uma função assíncrona e envolvê-la em todo o código do Puppeteer.

const puppeteer = require('puppeteer')

async function snapScreenshot() {
try {
const URL = 'https://old.reddit.com/'
const browser = await puppeteer.launch()
const page = await browser.newPage()

await page.goto(URL)
await page.screenshot({ path: 'screenshot.png' })

await browser.close()
} catch (error) {
console.error(error)
}
}

snapScreenshot()

Primeiro, uma instância do navegador é iniciada usando o comando puppeteer.launch(). Em seguida, criamos uma nova página usando a instância do navegador. Para navegar para o sítio Web pretendido, podemos utilizar o método goto(), passando o URL como parâmetro. Para tirar uma fotografia do ecrã, utilizamos o método screenshot(). Também precisamos de passar a localização onde a imagem será guardada.

Note que o Puppeteer define um tamanho de página inicial para 800×600px, que define o tamanho da captura de ecrã. É possível personalizar o tamanho da página usando o método setViewport().

Não se esqueça de fechar a instância do navegador. Depois, tudo o que tem de fazer é executar node index.js no terminal.

É mesmo assim tão simples! Agora deve ver um novo ficheiro chamado screenshot.png na pasta do seu projeto.

Enviar um formulário

Se, por alguma razão, o sítio Web que pretende extrair não mostrar o conteúdo a menos que tenha iniciado sessão, pode automatizar o processo de início de sessão com o Puppeteer.

Em primeiro lugar, temos de inspecionar o Web site que estamos a extrair e encontrar os campos de início de sessão. Podemos fazer isso clicando com o botão direito do rato no elemento e escolhendo a opção Inspecionar.

imagem do blogue

No meu caso, as entradas estão dentro de um formulário com a classe login-form. Podemos introduzir as credenciais de início de sessão utilizando o método type().

Além disso, se você quiser ter certeza de que ele faz as ações corretas, você pode adicionar o parâmetro headless e defini-lo como false quando você iniciar a instância do Puppeteer. Verá então como o Puppeteer faz todo o processo por si.

const puppeteer = require('puppeteer')

async function login() {
try {
const URL = 'https://old.reddit.com/'
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()

await page.goto(URL)

await page.type('.login-form input[name="user"]', 'EMAIL@gmail.com')
await page.type('.login-form input[name="passwd"]', 'PASSWORD')

await Promise.all([
page.click('.login-form .submit button'),
page.waitForNavigation(),
]);

await browser.close()

} catch (error) {
console.error(error)
}
}

login()

Para simular um clique do rato, podemos utilizar o método click(). Depois de clicarmos no botão de login, devemos esperar que a página seja carregada. Podemos fazer isso com o método waitForNavigation().

Se tivermos introduzido as credenciais corretas, devemos estar ligados agora!

Extrair várias páginas

Vou usar o subreddit /r/learnprogramming para este artigo. Então, queremos navegar até o site, pegar o título e a URL de cada post. Para isso, usaremos o método evaluate().

O código deve ter o seguinte aspeto:

const puppeteer = require('puppeteer')

async function tutorial() {
try {
const URL = 'https://old.reddit.com/r/learnprogramming/'
const browser = await puppeteer.launch()
const page = await browser.newPage()

await page.goto(URL)
let data = await page.evaluate(() => {
let results = []
let items = document.querySelectorAll('.thing')
items.forEach((item) => {
results.push({
url: item.getAttribute('data-url'),
title: item.querySelector('.title').innerText,
})
})
return results
})

console.log(data)
await browser.close()

} catch (error) {
console.error(error)
}
}

tutorial()

Usando o método Inspecionar apresentado anteriormente, podemos pegar todos os posts, visando o seletor .thing. Nós iteramos através deles e, para cada um, obtemos a URL e o título e os colocamos em um array.

Depois de todo o processo estar concluído, pode ver o resultado na sua consola.

imagem do blogue

Ótimo, já recolhemos a primeira página. Mas como é que fazemos o scraping de várias páginas deste subreddit?

É mais simples do que pensa. Aqui está o código:

const puppeteer = require('puppeteer')

async function tutorial() {
try {
const URL = 'https://old.reddit.com/r/learnprogramming/'
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()

await page.goto(URL)
let pagesToScrape = 5;
let currentPage = 1;
let data = []
while (currentPage <= pagesToScrape) {
let newResults = await page.evaluate(() => {
let results = []
let items = document.querySelectorAll('.thing')
items.forEach((item) => {
results.push({
url: item.getAttribute('data-url'),
text: item.querySelector('.title').innerText,
})
})
return results
})
data = data.concat(newResults)
if (currentPage < pagesToScrape) {
await page.click('.next-button a')
await page.waitForSelector('.thing')
await page.waitForSelector('.next-button a')
}
currentPage++;
}
console.log(data)
await browser.close()
} catch (error) {
console.error(error)
}
}

tutorial()

Precisamos de uma variável para saber quantas páginas queremos extrair e outra variável para a página atual. Enquanto a página atual for menor ou igual ao número de páginas que queremos recolher, recolhemos o URL e o título de cada publicação na página. Depois de cada página ser recolhida, concatenamos os novos resultados com os que já foram recolhidos.

Em seguida, clicamos no botão da página seguinte e repetimos o processo de recolha de dados até atingirmos o número pretendido de páginas extraídas. Também precisamos de incrementar a página atual após cada página.

Uma opção ainda mais fácil

Parabéns! Construiu com sucesso o seu próprio web scraper com o Puppeteer. Espero que tenhas gostado do tutorial!

Mesmo assim, o script que criámos neste guia não pode fazer muito trabalho duro. Faltam-lhe alguns aspectos fundamentais para que a recolha de dados da Web seja perfeita. Utilizar proxies móveis ou residenciais e resolver CAPTCHAs são apenas algumas das funcionalidades em falta.

Se estiver à procura de uma forma mais profissional de extrair dados, veja o que o WebScrapingAPI pode fazer e veja se é uma boa opção. Existe um pacote gratuito, pelo que só tem de investir 30 minutos do seu tempo.

Boa raspagem da Web!

Notícias e actualizações

Mantenha-se atualizado com os mais recentes guias e notícias sobre raspagem da Web, subscrevendo a nossa newsletter.

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Artigos relacionados

miniatura
GuiasSaiba como contornar a deteção do Cloudflare com o melhor navegador Selenium

Saiba qual é o melhor browser para contornar os sistemas de deteção Cloudflare enquanto faz web scraping com o Selenium.

Mihnea-Octavian Manolache
avatar do autor
Mihnea-Octavian Manolache
9 min. de leitura
miniatura
GuiasComo construir um raspador e descarregar um ficheiro com o Puppeteer

Descubra 3 formas de descarregar ficheiros com o Puppeteer e construa um web scraper que faz exatamente isso.

Mihnea-Octavian Manolache
avatar do autor
Mihnea-Octavian Manolache
8 min. de leitura
miniatura
GuiasO melhor guia de raspagem e automação da Web para 2023

Saiba como usar o Playwright para raspagem e automação da Web com nosso guia abrangente. Desde a configuração básica até técnicas avançadas, este guia cobre tudo.

Suciu Dan
avatar do autor
Suciu Dan
16 min leitura