Voltar ao blogue
Guias
Robert SfichiLast updated on Apr 28, 202615 min read

Web Scraping com JavaScript e Node.Js

Web Scraping com JavaScript e Node.Js

Sejamos honestos. A partir de agora, o volume de dados na Internet só vai aumentar cada vez mais. Não há realmente nada que possamos fazer quanto a isso. É aqui que os Web Scrapers entram em cena.

No artigo a seguir, vamos mostrar-lhe como criar o seu próprio Web Scraper usando JavaScript como linguagem de programação principal.

Compreender o Web Scraping com JavaScript

Um web scraper é um software que ajuda a automatizar o processo tedioso de recolher dados úteis de sites de terceiros. Normalmente, este procedimento envolve fazer um pedido a uma página web específica, ler o código HTML e decompor esse código para recolher alguns dados.

Por que razão alguém deveria extrair dados?

Digamos que queira criar uma plataforma de comparação de preços. Precisa dos preços de vários artigos de algumas lojas online. Uma ferramenta de web scraping pode ajudá-lo a fazer isso em poucos minutos.

Talvez esteja a tentar obter novos contactos para a sua empresa ou até mesmo os preços mais favoráveis de voos ou hotéis. Enquanto navegávamos pela web, a pesquisar para este artigo, deparámo-nos com o Brisk Voyage.

O Brisk Voyage é uma aplicação web que ajuda os seus utilizadores a encontrar viagens de fim de semana baratas e de última hora. Utilizando algum tipo de tecnologia de web scraping, conseguem verificar constantemente os preços de voos e hotéis. Quando o web scraper encontra uma viagem com um preço excepcionalmente baixo, o utilizador recebe um e-mail com as instruções de reserva.

Para que servem os web scrapers?

Os programadores utilizam web scrapers para todo o tipo de recolha de dados, mas os casos mais comuns são os seguintes:

  • Análise de mercado
  • Comparação de preços
  • Geração de leads
  • Investigação académica
  • Recolha de conjuntos de dados de treino e teste para Aprendizagem Automática

Quais são os desafios do Web Scraping com JavaScript e Node.js?

Sabe aquelas pequenas caixas de seleção que o obrigam a admitir que não é um robô? Bem, nem sempre conseguem manter os bots afastados.

Mas na maioria das vezes conseguem, e quando os motores de busca descobrem que está a tentar fazer web scraping no site deles sem permissão, restringem o seu acesso.

Outro obstáculo que os web scrapers enfrentam é representado pelas alterações na estrutura de um site. Uma pequena alteração na estrutura do site pode fazer-nos perder muito tempo. As ferramentas de web scraping requerem atualizações frequentes para se adaptarem e realizarem o trabalho.

Outro desafio que os web scrapers enfrentam é o chamado geo-bloqueio. Com base na sua localização física, um site pode bloquear completamente o seu acesso se as solicitações vierem de regiões não confiáveis.

Para combater estes desafios e ajudá-lo a concentrar-se na criação do seu produto, criámos a WebScrapingAPI. É uma API escalável de nível empresarial e fácil de usar que o ajuda a recolher e gerir dados HTML. Somos obcecados pela velocidade, utilizamos uma rede global de proxies rotativos e já temos mais de 10 000 clientes a utilizar os nossos serviços. Se achar que não tem tempo para construir o web scraper do zero, pode experimentar a WebScrapingAPI utilizando o plano gratuito.

APIs: A forma fácil de fazer web scraping

A maioria das aplicações web fornece uma API que permite aos utilizadores aceder aos seus dados de uma forma pré-determinada e organizada. O utilizador faz um pedido a um ponto final específico e a aplicação responde com todos os dados que o utilizador solicitou especificamente. Na maioria das vezes, os dados já estarão formatados como um objeto JSON.

Ao utilizar uma Interface de Programação de Aplicações, normalmente não tem de se preocupar com os obstáculos anteriormente apresentados. Seja como for, as APIs também podem receber atualizações. Nesta situação, o utilizador tem de estar sempre atento à API que está a utilizar e atualizar o código em conformidade para não perder a sua funcionalidade.

Além disso, a documentação de uma API é muito importante. Se a funcionalidade de uma API não estiver claramente documentada, o utilizador acaba por perder muito tempo.

Compreender a Web

Uma boa compreensão da Internet requer muito conhecimento. Vamos fazer uma breve introdução a todos os termos de que precisa para compreender melhor o web scraping.

O HTTP, ou Protocolo de Transferência de Hipertexto, é a base de qualquer troca de dados na Web. Como o nome sugere, o HTTP é uma convenção cliente-servidor. Um cliente HTTP, como um navegador da Web, abre uma ligação a um servidor HTTP e envia uma mensagem, do tipo: «Olá! Como vai isso? Importas-te de me passar essas imagens?». O servidor normalmente oferece uma resposta, como o código HTML, e encerra a ligação.

Digamos que precisa de visitar o Google. Se digitar o endereço no navegador da Web e premir Enter, o cliente HTTP (o navegador) enviará a seguinte mensagem ao servidor:

GET / HTTP/1.1
Host: google.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/web\p,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Connection: keep-aliveUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

A primeira linha da mensagem contém o método de pedido (GET), o caminho para o qual fizemos o pedido (no nosso caso é apenas '/' porque apenas acedemos a www.google.com), a versão do protocolo HTTP e vários cabeçalhos, como Connection ou User-Agent.

Vamos falar sobre os campos de cabeçalho mais importantes para o processo:

  • Host: O nome de domínio do servidor ao qual acedeu depois de digitar o endereço no navegador da Web e pressionar Enter.
  • User-Agent: Aqui podemos ver detalhes relativos ao cliente que efetuou a solicitação. Eu uso um MacBook, como pode ver na parte __(Macintosh; Intel Mac OS X 10_11_6)__, e o Chrome como navegador da Web __(Chrome/56.0.2924.87)__.
  • Accept: Ao utilizar este cabeçalho, o cliente restringe o servidor a enviar-lhe apenas determinados tipos de respostas, como application/JSON ou text/plain.
  • Referrer: Este campo de cabeçalho contém o endereço da página que está a fazer o pedido. Os sites utilizam este cabeçalho para alterar o seu conteúdo com base na origem do utilizador.

Uma resposta do servidor pode ter o seguinte aspeto:

HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu) Content-Type: text/html; charset=utf-8 
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>The content of the document</body>
</html>

Como pode ver, na primeira linha está o código de resposta HTTP: **200 OK. Isto significa que a ação de scraping foi bem-sucedida.

Agora, se tivéssemos enviado a solicitação usando um navegador da Web, ele teria analisado o código HTML, obtido todos os outros recursos, como CSS, arquivos JavaScript e imagens, e renderizado a versão final da página da Web. Nas etapas abaixo, vamos tentar automatizar esse processo.

Compreender o Web Scraping com Node.Js

O JavaScript foi inicialmente criado para ajudar os seus utilizadores a adicionar conteúdo dinâmico a websites. No início, não conseguia interagir diretamente com um computador ou com os seus dados. Quando acede a um website, o JavaScript é lido pelo navegador e transformado em algumas linhas de código que o computador consegue processar.

Apresentamos o Node.js, a ferramenta que ajuda o JavaScript a ser executado não só no lado do cliente, mas também no lado do servidor. O Node.js pode ser definido como um JavaScript gratuito e de código aberto para programação no lado do servidor. Ajuda os seus utilizadores a criar e executar aplicações de rede rapidamente.

const http = require('http');
const port = 8000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello world!');
});
server.listen(port, () => {
  console.log(`Server running on port 8000.`);
});

Se não tiver o Node.js instalado, consulte o passo seguinte para obter as instruções. Caso contrário, crie um novo ficheiro index.js e execute-o digitando no terminal node index.js, abra um navegador e aceda a localhost:8000. Deverá ver a seguinte sequência: «Hello world!».

Ferramentas necessárias

Chrome - Siga o guia de instalação aqui.

  • VSCode - Pode descarregá-lo nesta página e seguir as instruções para o instalar no seu dispositivo.
  • Node.js - Antes de começar a usar o Axios, o Cheerio ou o Puppeteer, precisamos de instalar o Node.js e o Node Package Manager. A forma mais fácil de instalar o Node.js e o NPM é obter um dos instaladores da fonte oficial do Node.js e executá-lo.

Após a instalação, pode verificar se o Node.Js está instalado executando node -v e npm -v numa janela de terminal. A versão deve ser superior à v14.15.5. Se estiver com dificuldades neste processo, existe uma forma alternativa de instalar o Node.Js.

Agora, vamos criar um novo projeto NPM. Crie uma nova pasta para o projeto e execute npm init -y. Agora vamos instalar as dependências.

  • Axios - uma biblioteca JavaScript utilizada para efetuar pedidos HTTP a partir do Node.js. Execute npm install axios na pasta recém-criada.
  • Cheerio - uma biblioteca de código aberto que nos ajuda a extrair informações úteis através da análise de marcação e do fornecimento de uma API para manipular os dados resultantes. Para utilizar o Cheerio, pode selecionar tags de um documento HTML utilizando seletores. Um seletor tem o seguinte aspeto: $("div"). Este seletor específico ajuda-nos a selecionar todos os elementos <div> numa página.

Para instalar o Cheerio, execute npm install cheerio na pasta do projeto.

  • Puppeteer - uma biblioteca Node.js que permite controlar o Chrome ou o Chromium através de uma API de alto nível.

Para utilizar o Puppeteer, tem de o instalar utilizando um comando semelhante: npm install puppeteer. Note que, ao instalar este pacote, será também instalada uma versão recente do Chromium que é garantidamente compatível com a sua versão do Puppeteer.

Inspeção da fonte de dados

Primeiro, tem de aceder ao site que pretende rastrear utilizando o Chrome ou qualquer outro navegador web. Para rastrear com sucesso os dados de que necessita, tem de compreender a estrutura do site.

Inspeção do site alvo

Depois de conseguir aceder ao site, utilize-o tal como um utilizador normal faria. Se acedeu ao subreddit /r/dundermifflin, pode ver as publicações na página principal clicando nelas, verificando os comentários e os votos positivos, e até ordenando as publicações pelo número de votos durante um período de tempo específico.

Como pode ver, o site contém uma lista de publicações, e cada publicação tem alguns votos positivos e alguns comentários.

É possível compreender grande parte dos dados de um site apenas olhando para o seu URL. Neste caso, https://www.old.reddit.com/r/DunderMifflin representa o URL base, o caminho que nos leva à comunidade Reddit de «The Office». À medida que começa a ordenar as publicações pelo número de votos, pode ver que a URL base muda para https://www.old.reddit.com/r/DunderMifflin/top/?t=year.

Os parâmetros de consulta são extensões da URL que são usadas para ajudar a definir conteúdos ou ações específicas com base nos dados que estão a ser passados. No nosso caso, «?t=year» representa o período de tempo selecionado para o qual queremos ver as publicações com mais votos positivos.

Desde que permaneça neste subreddit específico, a URL base permanecerá a mesma. A única coisa que mudará são os parâmetros de consulta. Podemos considerá-los como os filtros aplicados à base de dados para recuperar os dados que pretendemos. Pode alterar o período de tempo para ver apenas as publicações mais votadas no último mês ou na última semana, bastando para isso alterar a URL.

Inspeção utilizando ferramentas de programador

Nos passos seguintes, vais aprender mais sobre como a informação está organizada na página. Vais precisar de fazer isto para compreender melhor o que podemos realmente extrair da nossa fonte.

As ferramentas de programador ajudam-no a explorar interativamente o Modelo de Objetos de Documento (DOM) do site. Vamos utilizar as ferramentas de programador no Chrome, mas pode utilizar qualquer navegador web com o qual se sinta à vontade. No Chrome, pode abri-las clicando com o botão direito do rato em qualquer ponto da página e selecionando a opção «Inspecionar».

No novo menu que apareceu no ecrã, selecione o separador «Elementos». Isto apresentará a estrutura HTML interativa do site.

Pode interagir com o site editando a sua estrutura, expandindo e recolhendo elementos, ou mesmo eliminando-os. Note que estas alterações só serão visíveis para si.

Expressões regulares e o seu papel

As expressões regulares, também conhecidas como RegEx, ajudam-no a criar regras que lhe permitem encontrar e gerir diferentes cadeias de caracteres. Se alguma vez precisar de analisar grandes quantidades de informação, dominar o mundo das expressões regulares pode poupar-lhe muito tempo.

Quando se começa a usar regex, parece um pouco complicado, mas a verdade é que são bastante fáceis de usar. Vejamos o seguinte exemplo: \d. Ao usar esta expressão, pode facilmente selecionar qualquer dígito de 0 a 9. Claro que existem outras muito mais complexas, como: ^(\(\d{3}\)|^\d{3}[.-]?)?\d{3}[.-]?\d{4}$. Esta corresponde a um número de telefone, com ou sem parênteses à volta do indicativo, ou com ou sem pontos para separar os números.

Como pode ver, as expressões regulares são bastante fáceis de usar e podem ser muito poderosas se dedicar tempo suficiente a dominá-las.

Compreender o Cheerio.js

Depois de ter instalado com sucesso todas as dependências apresentadas anteriormente e inspecionado o DOM usando as ferramentas de desenvolvedor, pode passar para a extração propriamente dita.

Uma coisa que deve ter em mente é que, se a página que está a tentar extrair for uma SPA (Aplicação de Página Única), o Cheerio pode não ser a melhor solução. A razão é que o Cheerio não consegue realmente pensar como um navegador web. É por isso que, nos passos seguintes, vamos usar o Puppeteer. Mas, até lá, vamos descobrir o quão poderoso é o Cheerio.

Para testar a funcionalidade do Cheerio, vamos tentar recolher todos os títulos das publicações no subreddit apresentado anteriormente: /r/dundermifflin.

Vamos criar um novo ficheiro chamado index.js e escrever ou simplesmente copiar as seguintes linhas:

const axios = require("axios");
const cheerio = require("cheerio");
const fetchTitles = async () => {
	try {
		const response = await axios.get('https://old.reddit.com/r/DunderMifflin/');
                const html = response.data;
		const $ = cheerio.load(html);
		const titles = [];
		$('div > p.title > a').each((_idx, el) => {
			const title = $(el).text()
			titles.push(title)
		});
		return titles;
	} catch (error) {
		throw error;
	}};
fetchTitles().then((titles) => console.log(titles));

Para compreender melhor o código escrito acima, vamos explicar o que a função assíncrona fetchTitles() faz:

Primeiro, fazemos um pedido GET ao antigo site do Reddit utilizando a biblioteca Axios. O resultado dessa solicitação é então carregado pelo Cheerio na linha 10. Usando as ferramentas de desenvolvedor, descobrimos que os elementos que contêm as informações desejadas são algumas tags âncora. Para garantir que selecionemos apenas as tags âncora que contêm o título da publicação, vamos selecionar também seus elementos pais usando o seguinte seletor: $('div > p.title &g;t; a')

Para obter cada título individualmente e não apenas um grande bloco de letras sem sentido, temos de percorrer cada publicação utilizando a função each(). Por fim, chamar text() em cada item irá devolver-me o título dessa publicação específica.

Para o executar, basta digitar node index.js no terminal e premir Enter. Deverá ver uma matriz contendo todos os títulos das publicações.

DOM para NodeJS

Como o DOM de uma página web não está diretamente disponível para o Node.js, podemos usar o JSDOM. De acordo com a sua documentação, o JSDOM é uma implementação em JavaScript puro de muitos padrões web, nomeadamente os padrões DOM e HTML do WHATWG, para utilização com o Node.js.

Por outras palavras, utilizando o JSDOM, podemos criar um DOM e manipulá-lo utilizando os mesmos métodos que usaríamos para manipular o DOM do navegador web.

O JSDOM permite-lhe interagir com um site que precisa de rastrear. Se estiver familiarizado com a manipulação do DOM do navegador web, compreender a funcionalidade do JSDOM não exigirá muito esforço.

Para compreender melhor como o JSDOM funciona, vamos instalá-lo, criar um novo ficheiro index.js e digitar ou copiar o seguinte código:

const { JSDOM } = require('jsdom')
const { document } = new JSDOM(
  '<h1 class="string">Dunder mifflin, the people person\'s paper people!</h2>'
).window
const string = document.querySelector('.string')
console.log(string.innerHTML)
string.textContent = 'Hello world'
console.log(string.innerHTML)

Como pode ver, o JSDOM cria um novo Modelo de Objetos de Documento (DOM) que pode ser manipulado utilizando o mesmo método que usamos para manipular o DOM do navegador. Na linha 3, é criado um novo elemento h1 no DOM. Utilizando a classe atribuída ao título, selecionamos o elemento na linha 7 e alteramos o seu conteúdo na linha 10. Pode ver a diferença imprimindo o elemento DOM antes e depois da alteração.

Para o executar, abra um novo terminal, digite node index.js e prima Enter.

É claro que pode realizar ações muito mais complexas utilizando o JSDOM, como abrir uma página web e interagir com ela, preencher formulários e clicar em botões.

Pelo que vale a pena, o JSDOM é uma boa opção, mas o Puppeteer ganhou muita popularidade nos últimos anos.

Compreender o Puppeteer: como desvendar páginas JavaScript

Usando o Puppeteer, pode fazer a maioria das coisas que faria manualmente num navegador web, como preencher um formulário, gerar capturas de ecrã de páginas ou automatizar testes de interface do utilizador.

Vamos tentar compreender melhor a sua funcionalidade tirando uma captura de ecrã da comunidade Reddit /r/dundermifflin. Se já instalaste a dependência, passa para o próximo passo. Caso contrário, executa npm i puppeteer na pasta do projeto. Agora, cria um novo ficheiro index.js e digita ou copia o seguinte código:

const puppeteer = require('puppeteer')
async function takeScreenshot() {
	try {
		const URL = 'https://www.old.reddit.com/r/dundermifflin/'
		const browser = await puppeteer.launch()
		const page = await browser.newPage()
		await page.goto(URL)
		await page.pdf({ path: 'page.pdf' })
		await page.screenshot({ path: 'screenshot.png' })
		await browser.close()
	} catch (error) {
		console.error(error)
	}
}
takeScreenshot()

Criámos a função assíncrona takeScreenshot().

Como pode ver, primeiro é iniciada uma instância do navegador utilizando o comando puppeteer.launch(). Em seguida, criamos uma nova página e, ao chamar a função goto() utilizando o URL como parâmetro, a página criada anteriormente será direcionada para esse URL específico. Os métodos pdf() e screenshot() ajudam-nos a criar um novo ficheiro PDF e uma imagem que contém a página web como componente visual.

Por fim, a instância do navegador é fechada na linha 13. Para executá-lo, digite node index.js no terminal e pressione Enter. Deverá ver dois novos ficheiros na pasta projects chamados page.pdf e screenshot.png.

Alternativa ao Puppeteer

Se não se sentir à vontade para usar o Puppeteer, pode sempre recorrer a uma alternativa como o NightwatchJS, o NightmareJS ou o CasperJS.

Tomemos o Nightmare como exemplo. Como utiliza o Electron em vez do Chromium, o tamanho do pacote é um pouco menor. O Nightmare pode ser instalado executando o comando npm install nightmare. Vamos tentar replicar o processo anteriormente bem-sucedido de capturar uma imagem da página utilizando o Nightmare em vez do Puppeteer.

Vamos criar um novo ficheiro index.js e digitar ou copiar o seguinte código:

const Nightmare = require('nightmare')
const nightmare = new Nightmare()
return nightmare.goto('https://www.old.reddit.com/r/dundermifflin')
	.screenshot('./nightmare-screenshot.png')
 	.end()
	.then(() => {
		console.log('Done!')
	})
	.catch((err) => {
		console.error(err)
	})

Como pode ver na linha 2, criamos uma nova instância do Nightmare, direcionamos o navegador para a página web da qual queremos fazer a captura de ecrã, tiramos e guardamos a captura de ecrã na linha 5 e encerramos a sessão do Nightmare na linha 6.

Para o executar, digite node index.js no terminal e prima Enter. Deverá ver dois novos ficheiros, nightmare-screenshot.png, na pasta projects.

Principais conclusões

Se ainda está aqui, parabéns! Tem toda a informação necessária para criar o seu próprio web scraper. Vamos dedicar um minuto a resumir o que aprendeu até agora:

  • Um web scraper é um software que ajuda a automatizar o processo tedioso de recolher dados úteis de sites de terceiros.
  • As pessoas utilizam web scrapers para todo o tipo de recolha de dados: análise de mercado, comparação de preços ou geração de leads.
  • Clientes HTTP, como os navegadores web, ajudam-no a fazer pedidos a um servidor e a aceitar uma resposta.
  • O JavaScript foi inicialmente criado para ajudar os seus utilizadores a adicionar conteúdo dinâmico a sites. O Node.js é uma ferramenta que ajuda o JavaScript a funcionar não só no lado do cliente, mas também no lado do servidor.
  • O Cheerio é uma biblioteca de código aberto que nos ajuda a extrair informações úteis através da análise de HTML e do fornecimento de uma API para manipular os dados resultantes.
  • O Puppeteer é uma biblioteca Node.js utilizada para controlar o Chrome ou o Chromium, fornecendo uma API de alto nível. Graças a ela, pode realizar a maioria das tarefas que faria manualmente num navegador web, como preencher um formulário, gerar capturas de ecrã de páginas ou automatizar processos.
  • É possível compreender grande parte dos dados de um site apenas olhando para o seu URL.
  • As ferramentas de desenvolvimento ajudam-no a explorar interativamente o Modelo de Objetos de Documento (DOM) do site.
  • As expressões regulares ajudam-no a criar regras que permitem encontrar e gerir diferentes cadeias de caracteres.
  • O JSDOM é uma ferramenta que cria um novo Modelo de Objetos de Documento que pode ser manipulado utilizando o mesmo método que utiliza para manipular o DOM do navegador.

Esperamos que as instruções tenham sido claras e que tenha conseguido obter todas as informações necessárias para o seu próximo projeto. Se ainda assim sentir que não quer fazê-lo sozinho, pode sempre experimentar a WebScrapingAPI.

Obrigado por terem acompanhado até ao fim!

Sobre o autor
Robert Sfichi, Desenvolvedor Full-Stack @ WebScrapingAPI
Robert SfichiDesenvolvedor Full-Stack

Robert Sfichi é membro da equipa da WebScrapingAPI, contribuindo para o produto e ajudando a criar soluções fiáveis que apoiam a plataforma e os seus utilizadores.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.