Cheerio e Puppeteer são duas bibliotecas Node.js que lhe permitem navegar programaticamente na Internet. Devido a isto, ambas são escolhas populares para aqueles que desejam construir um raspador da web node.js a partir do zero.
A fim de comparar o Cheerio com o Puppeteer, vamos construir um simples raspador da web com o Cheerio e um raspador da web com o Puppeteer. Utilizaremos ambas as ferramentas para raspar todos os links do blogue de In Plain English, uma plataforma de programação popular.
Mas antes de começarmos, vamos ver o que vamos discutir neste artigo:
- Diferenças entre Cheerio e Puppeteer
- Construir um Raspador da Web com o Cheerio
- Construir um Raspador da Web com o Puppeteer
- Conclusão
Diferenças entre Cheerio e Puppeteer
Há muitas diferenças entre essas 2 bibliotecas, e cada uma delas vem com as suas próprias características especiais que pode aproveitar para a raspagem da web.
Cheerio
- Cheerio é um analisador DOM, capaz de analisar ficheiros HTML e XML.
- É uma implementação rápida e simples do núcleo jQuery concebida especificamente para o servidor.
- Se planeia usar isto para raspar um sítio web, terá de usar o Cheerio em conjunto com uma biblioteca de cliente http do Node.js como o https://axios-http.com/docs/introAxios.
- O Cheerio não mostra o sítio web como um navegador (não aplica CSS nem carrega recursos externos).
- Devido a isto, terá dificuldade em tentar raspar SPAs construídas com tecnologias de vanguarda como a React.
- O Cheerio não pode interagir com um sítio (por exemplo, não pode clicar em botões) nem aceder ao conteúdo de scripts.
- Tem uma curva de aprendizagem fácil graças à sua sintaxe simples. Os usuários de jQuery se sentirão em casa aqui.
- O Cheerio é rápido em comparação com o Puppeteer.
Puppeteer
- O Puppeteer é uma ferramenta de automatização do navegador. Tem acesso a todo o motor do navegador (geralmente o Chromium).
- Isto torna-o uma opção mais versátil, em comparação com o Cheerio.
- Pode executar JavaScript, tornando-o capaz de raspar páginas dinâmicas como aplicações de página única (SPAs).
- O Puppeteer pode interagir com sítios web, o que significa que pode ser usado para clicar em botões, digitar em formulários de registo, etc.
- Tem uma curva de aprendizagem íngreme, uma vez que tem mais funcionalidades e requer frequentemente o uso de código assíncrono (ou seja, promessas/async await).
- O Puppeteer é lento em comparação com o Cheerio.
Construir um Raspador da Web com o Cheerio
Primeiro, vamos criar uma pasta chamada ‘raspador’ para o nosso código. Dentro de ‘raspador’, correr npm init -y
ou yarn init -y
, dependendo de ter optado por usar npm
ou yarn
.
Agora que temos a nossa pasta pronta e package.json
inicializado, vamos instalar os nossos pacotes.
Nota: Pode consultar o nosso guia principal de raspagem da web com node.js que inclui o uso de Cheerio e Axios para raspagem da web com mais detalhe.
Passo 1 – Instalação de Cheerio
Para instalar o Cheerio, execute o seguinte comando no seu terminal:
// using npm
npm install cheerio
// or using yarn
yarn add cheerio
Passo 2 – Instalação de Axios
Axios é uma biblioteca popular para fazer pedidos HTTP no Node.js. Pode ser utilizado para fazer chamadas de API, obter dados de sítios web, e muito mais.
Para o instalar, execute o seguinte comando no seu terminal:
// using npm
npm install axios
// or using yarn
yarn add axios
Utilizamos Axios para fazer pedidos HTTP para o sítio web que pretendemos raspar. A resposta que obtemos do sítio web é sob a forma de HTML, que podemos então analisar e extrair a informação de que precisamos utilizando o Cheerio.
Passo 3 – Preparar o nosso raspador
Vamos entrar na nossa pasta ‘raspador’ e criar um ficheiro chamado cheerio.js
.
Aqui está a estrutura básica do código para começar com a raspagem da web usando Cheerio e Axios:
const axios = require('axios');
const cheerio = require('cheerio');
axios
.get("https://plainenglish.io/blog")
.then((response) => {
// Initialize links array which we will push the links to later
let links = [];
// HTML Markup
const body = response.data;
// Load HTML data and initialize cheerio
const $ = cheerio.load(body);
// CSS selector for the target element
const element = ".PostPreview_container__82q9E";
// Loop through each matching element and extract the text content
$(element).each(function () {
// Loop through each matching element and get the href attribute of each element
const _link = $(this).find("a").prop("href");
// We check if the link is undefined because cheerio will return undefined if the element doesn't exist
if (_link !== undefined) {
// Add the link to the links array
links.push(`https://plainenglish.io` + _link);
}
});
return links;
})
.then((response) => {
console.log(response);
});
No código acima, precisamos primeiro as bibliotecas Axios e Cheerio.
Passo 5 – Processamento dos dados
A seguir, fazemos um pedido get()
para “https://plainenglish.io/blog”. Porque o Axios é assíncrono, nós encadeamos a nossa função get()
com then()
.
Inicializamos uma matriz de links vazia para capturar os links que planeamos raspar.
Passamos então o response.data
de Axios para Cheerio com:
// HTML Markup
const body = response.data;
// Load HTML data and initialize cheerio
const $ = cheerio.load(body);
We choose which selector we plan to target, in our case:
// CSS selector for the target element
const element = ".PostPreview_container__82q9E";
Passo 5 – Processamento dos dados
Depois, fazemos um laço através de cada elemento correspondente, encontramos a etiqueta <a>
, e agarramos o valor da propriedade href
. Para cada partida, empurramo-la para a nossa matriz de links:
// Loop through each matching element and extract the text content
$(element).each(function () {
// Loop through each matching element and get the href attribute of each element
const _link = $(this).find("a").prop("href");
// We check if the link is undefined because cheerio will return undefined if the element doesn't exist
if (_link !== undefined) {
// Add the link to the links array
links.push(`https://plainenglish.io` + _link);
}
});
Depois os devolvemos, encadeamos outro then()
e enviamos ao console.log
a nossa resposta.
Passo 6 – Resultados finais
Finalmente, se abrirmos um terminal de dentro da nossa pasta ‘raspador’, podemos correr o node.js cheerio.js
. Isto irá executar todo o código do nosso ficheiro cheerio.js
. Deverá ver os URLs da nossa matriz de links a serem enviados para a consola. Ficará algo parecido com isto:
'https://plainenglish.io/blog/how-to-implement-a-search-bar-in-react-js',
'https://plainenglish.io/blog/how-to-build-data-driven-surveys-with-react-rest-api-surveyjs',
'https://plainenglish.io/blog/handle-errors-in-angular-with-httpclient-and-rxjs',
'https://plainenglish.io/blog/deploying-a-localhost-server-with-node-js-and-express-js',
'https://plainenglish.io/blog/complete-guide-to-data-center-migration',
'https://plainenglish.io/blog/build-a-stripe-app-with-typescript-and-node-js-part-2',
... 861 more items
E assim mesmo, conseguimos raspar o sítio In Plain English!
A partir daqui, podemos ir um passo mais longe e guardar os dados num ficheiro, em vez de simplesmente enviá-los para a consola.
O Cheerio e o Axios facilitam a execução de raspagem da web no Node.js. Com apenas algumas linhas de código, é possível extrair dados de sítios web e utilizá-los para vários fins.
Construir um Raspador da Web com Puppeteer
Vamos para a nossa pasta ‘raspador’ e criemos um ficheiro chamado puppeteer.js
. Já inicializámos o nosso package.json
, mas se saltou para esta secção, vá em frente e inicialize agora esse ficheiro.
Uma vez inicializado, vamos instalar o Puppeteer.
Passo 1 – Instalação do Puppeteer
Para instalar o Puppeteer, executar um dos seguintes comandos:
// using npm
npm install puppeteer
// or using yarn
yarn add puppeteer
Passo 2 – Preparar o nosso raspador
Vamos para a nossa pasta ‘raspador’ e criemos um ficheiro chamado puppeteer.js
.
Aqui está a estrutura básica do código para começar com a raspagem da web usando o Puppeteer:
const puppeteer = require("puppeteer");
// Because everything in Puppeteer is asynchronous,
// we wrap all of our code inside of an async IIFE
(async () => {
// Initialize links array which we will push the links to later
let links = [];
// Launch Puppeteer
const browser = await puppeteer.launch();
// Create a new page
const page = await browser.newPage();
// Go to URL
await page.goto("https://plainenglish.io/blog");
// Set screen size
await page.setViewport({ width: 1080, height: 1024 });
// CSS selector for the target element
const element = ".PostPreview_container__82q9E";
// Get all matching elements
const elements = await page.$$(element);
// Wrapped with Promise.all to wait for all promises to resolve before continuing
const _links = await Promise.all(
// Get the href attribute of each element
elements.map(async (el) => el.evaluate((el) => el.children[0].href))
);
if (_links.length) {
// If there are any links
_links.forEach((url) => {
// Loop through each link
links.push(url); // Add the link to the links array
});
}
console.log(links);
await browser.close();
})();
No código acima, precisamos primeiro a biblioteca Puppeteer.
Passo 3 – Criação de uma IIFE
A seguir, criamos uma expressão de função imediatamente invocada (IIFE). Como tudo no Puppeteer é assíncrono, colocamos async no início. Em outras palavras, temos isto:
(async () => {
// ...code goes here
}()
Dentro da nossa IIFE assimétrica, criamos uma matriz de links vazia, que utilizaremos para capturar os links do blogue que estamos a raspar.
// Initialize links array which we will push the links to later
let links = []
A seguir, executamos o Puppeteer, abrimos uma nova página, navegamos para um URL, e definimos o suporte de visualização da página (o tamanho da tela).
// Launch Puppeteer
const browser = await puppeteer.launch();
// Create a new page
const page = await browser.newPage();
// Go to URL
await page.goto("https://plainenglish.io/blog");
// Set screen size
await page.setViewport({ width: 1080, height: 1024 });
Por defeito, o Puppeteer corre em ‘modo sem cabeça’. Isto significa que não abre um navegador que se possa ver visualmente. No entanto, definimos um tamanho de visualização pois queremos que o Puppeteer navegue pelo sítio a uma certa largura e altura.
Nota: Se decidir que gostaria de ver o que o “Puppeteer” está a fazer em tempo real, pode passar a opção “headless: false” como parâmetro, assim:
// Launch Puppeteer
const browser = await puppeteer.launch({ headless: false });
Passo 5 – Processamento dos dados
A partir daqui, escolhemos qual é o seletor que pretendemos visar, no nosso caso:
// CSS selector for the target element
const element = ".PostPreview_container__82q9E";
E executamos o que equivale à querySelectorAll()
para o nosso elemento alvo:
// Get all matching elements
const elements = await page.$$(element);
Nota: $$
não é o mesmo que querySelectorAll
, por isso não espere ter acesso a todas as mesmas coisas.
Passo 5 – Processamento dos dados
Agora que temos os nossos elementos armazenados dentro de elementos, mapeamos cada elemento para retirar a propriedade href
:
// Wrapped with Promise.all to wait for all promises to resolve before continuing
const _links = await Promise.all(
// Get the href attribute of each element
elements.map(async (el) => el.evaluate((el) => el.children[0].href))
);
No nosso caso de uso específico, temos el.children[0]
, pois sei que o primeiro elemento secundário do nosso elemento alvo é uma etiqueta a, e é a etiqueta a cujo valor eu quero.
Em seguida, fazemos um laço através de cada elemento mapeado e empurramos o valor para a nossa matriz de links, desta forma:
if (_links.length) {
// If there are any links
_links.forEach((url) => {
// Loop through each link
links.push(url); // Add the link to the links array
});
}
Finalmente, enviamos os links ao console.log
, e depois fechamos o navegador:
console.log(links);
await browser.close();
Nota: Se não fechar o navegador, este permanecerá aberto e o seu terminal ficará suspenso.
Passo 6 – Resultados finais
Agora, se abrirmos um terminal de dentro da nossa pasta ‘raspador’, podemos executar node.js puppeteer.js
. Isto executará todo o código do nosso ficheiro puppeteer.js
. Deverá ver os URLs da nossa matriz de links a serem enviados para a consola. Ficará algo parecido com isto:
'https://plainenglish.io/blog/how-to-implement-a-search-bar-in-react-js',
'https://plainenglish.io/blog/how-to-build-data-driven-surveys-with-react-rest-api-surveyjs',
'https://plainenglish.io/blog/handle-errors-in-angular-with-httpclient-and-rxjs',
'https://plainenglish.io/blog/deploying-a-localhost-server-with-node-js-and-express-js',
'https://plainenglish.io/blog/complete-guide-to-data-center-migration',
'https://plainenglish.io/blog/build-a-stripe-app-with-typescript-and-node-js-part-2',
... 861 more items
E assim mesmo, conseguimos raspar o sítio web com o Puppeteer!
Puppeteer é uma ferramenta poderosa para raspar e automatizar tarefas de navegação na web. Fornece uma API rica para tarefas de raspagem e automatização de navegação na web. Pode utilizá-la para extrair informação de sítios web, gerar capturas de ecrã e PDFs, e realizar muitas outras tarefas.
Se quiser usar o Puppeteer para raspar os principais sítios, deve considerar integrar o Puppeteer com um proxy, para evitar ficar bloqueado.
Nota: Existem outras alternativas ao “Puppeteer”, tais como o Selenium, ou o IDE para Raspador da Web. Ou, se quiser poupar tempo, pode saltar todo o processo de raspagem da web completamente, procurando conjuntos de dados prontos.
Conclusão
Se procura raspar páginas estáticas sem a necessidade de interações tais como cliques e envios de formulários (ou qualquer tipo de tratamento de eventos), o Cheerio é a escolha ideal.
No entanto, se o sítio web depende do JavaScript para a injeção de conteúdo, ou se precisa de tratar eventos, é necessário o Puppeteer.
Qualquer que seja a abordagem que decidir, vale a pena notar que este caso de uso específico foi bastante simples. Se tentar raspar algo mais complexo, como um sítio web dinâmico (YouTube, Twitter, ou Facebook, por exemplo), poderá encontrar-se em águas bastante profundas.
Se procura raspar sítios web e não quer perder semanas a tentar decifrar uma solução, talvez seja melhor procurar uma solução pronta a usar, tal como o IDE para Raspador da Web.
O IDE da Bright Data inclui funções de raspagem pré-fabricadas, infraestrutura proxy de desbloqueio sofisticada incorporada, scripts de navegador em JavaScript, depuração, e vários modelos de raspagem prontos a usar para sítios web populares.