Voltar ao blogue
Guias
Mihnea-Octavian ManolacheLast updated on Mar 31, 202612 min read

O Guia Definitivo de Web Scraping e Automatização para o Playwright em 2023

O Guia Definitivo de Web Scraping e Automatização para o Playwright em 2023

A extração de dados da Web e a automação andam de mãos dadas no mundo digital atual. Desde sites de comparação de preços até empresas baseadas em dados, a capacidade de extrair e processar dados da Web tornou-se parte integrante de muitos empreendimentos online.

Conheça o Playwright: uma ferramenta que permite automatizar tarefas de web scraping e testes com facilidade. O Playwright permite controlar um navegador headless, dando-lhe a capacidade de extrair dados e interagir com sites de forma rápida e eficiente.

Neste artigo, exploraremos as capacidades do Playwright para automação e scraping. Mostrar-lhe-ei como instalar e configurar o Playwright, fornecerei exemplos de código para tarefas comuns e discutirei técnicas avançadas, tais como o tratamento de formulários de login, a captura de ecrãs e muito mais.

O que é o Playwright?

O Playwright é uma biblioteca Node.js de código aberto e multiplataforma desenvolvida pela Microsoft que permite automatizar tarefas num navegador web. Foi concebido para ser fiável e fácil de usar, com suporte para funcionalidades web modernas, como CSS3 e JavaScript.

O Playwright pode ser utilizado para tarefas como testar aplicações web, automatizar tarefas baseadas na web e web scraping. É construído com base na popular biblioteca de testes web Puppeteer e tem como objetivo fornecer uma API mais intuitiva e fácil de manter.

O Playwright suporta vários navegadores, incluindo Chromium, Firefox e WebKit. Isto significa que pode utilizá-lo para automatizar tarefas e extrair dados em diferentes navegadores. O Playwright permite-lhe alternar facilmente entre navegadores e tirar partido das suas funcionalidades exclusivas.

Introdução

Para instalar e configurar o Playwright numa máquina local, terá de ter o Node.js e o npm (o gestor de pacotes para o Node.js) instalados. Se ainda não os tiver, pode descarregá-los e instalá-los a partir do site oficial do Node.js.

Depois de instalar o Node.js e o npm, pode instalar o Playwright seguindo estes passos:

  • Abra um terminal ou prompt de comando
  • Crie uma pasta chamada `playwright` onde ficará o código do nosso projeto
  • Vá para a pasta recém-criada
  • Execute o comando `npm init` para inicializar o projeto (e criar o ficheiro package.json)
  • Instale a dependência necessária utilizando o comando `npm install playwright`

Scraping básico com o Playwright

Crie um ficheiro chamado `index.js` e cole o seguinte código:

const { chromium } = require('playwright');

(async () => {

    // Launch a Chromium browser

    const browser = await chromium.launch();

    // Create a new page in the browser

    const page = await browser.newPage();

    // Navigate to a website

    await page.goto('https://coinmarketcap.com');

    // Get the page content

    const content = await page.content();

    // Display the content

    console.log(content);

    // Close the browser

    await browser.close();

})();

Este código irá iniciar um navegador Chromium sem interface gráfica, criar uma nova página, navegar até à página inicial do CoinMarketCap, obter o conteúdo da página, registar o conteúdo e, em seguida, fechar o navegador.

Pode utilizar código semelhante para iniciar os outros navegadores suportados (Firefox e WebKit), importando o módulo apropriado e substituindo «chromium» por «firefox» ou «webkit».

Encontrar elementos para extração de dados

Agora que temos uma base para o nosso scraper, vamos extrair alguns dados do site de destino. Neste exemplo, iremos recuperar o nome e o preço das primeiras 10 moedas apresentadas na página.

Para visualizar a árvore DOM da página inicial do CoinMarketCap, abra o site num navegador, clique com o botão direito do rato num nome de moeda e selecione «Inspecionar». Isto abrirá as Ferramentas de Programador e exibirá a árvore DOM.

Selecionar os seletores certos é uma arte em si. Neste caso, o elemento de tabela que queremos selecionar é o contexto. Esta tabela tem uma classe chamada «cmc-table», que será útil para os nossos objetivos.

Para encontrar o seletor do nome da moeda, teremos de descer na árvore DOM. O elemento que procuramos está localizado dentro do elemento `.cmc-table tbody tr td:nth-child(3) a .name-area p`.

Como regra geral, é importante ser o mais preciso possível ao selecionar elementos, pois isso minimizará o número de erros que precisam de ser tratados.

Usando a mesma técnica, podemos encontrar o seletor para o preço, que é `.cmc-table tbody tr td:nth-child(3) a span`. Para recapitular, eis a nossa lista de seletores:

  • Nome: `.cmc-table tbody tr td:nth-child(3) a .name-area p`
  • Preço: `.cmc-table tbody tr td:nth-child(4) a span`

Extração de dados

Usando os seletores que identificámos anteriormente, vamos extrair os dados da página web e armazená-los numa lista. A função utilitária $$eval devolve uma matriz de elementos que correspondem a um seletor, avaliados no contexto do DOM da página.

Vamos substituir a linha console.log(content); por isto:

// Extract the currencies data

const currencies = await page.$$eval('.cmc-table tbody tr:nth-child(-n+10)', trs => {

    const data = []

    trs.forEach(tr => {

        data.push({

            name: tr.querySelector('td:nth-child(3) a .name-area p').innerHTML,

            price: tr.querySelector('td:nth-child(4) a span').innerHTML,

        })

    })

    return data

})

// Display the results

console.log(currencies)

Este código utiliza a função $$eval para selecionar os primeiros 10 elementos tr dentro do .cmc-table. Em seguida, percorre esses elementos, seleciona as células de dados da tabela utilizando os seletores que identificámos anteriormente e extrai o seu conteúdo de texto. Os dados são devolvidos como uma matriz de objetos.

Pode ler mais sobre a função $$eval na documentação oficial.

O código completo tem o seguinte aspeto:

const { chromium } = require('playwright');

(async () => {

    // Launch a Chromium browser

    const browser = await chromium.launch();

    // Create a new page in the browser

    const page = await browser.newPage();

    // Navigate to a website

    await page.goto('https://coinmarketcap.com');

    // Extract the currencies data

    const currencies = await page.$$eval('.cmc-table tbody tr:nth-child(-n+10)', trs => {

   	 const data = []

   	 trs.forEach(tr => {

   		 data.push({

   			 name: tr.querySelector('td:nth-child(3) a .name-area p').innerHTML,

   			 price: tr.querySelector('td:nth-child(4) a span').innerHTML,

   		 })

   	 })

   	 return data

    })

    // Display the results

    console.log(currencies)

    // Close the browser

    await browser.close();

})();

Tratamento de Conteúdo Dinâmico

Apenas extraímos as primeiras 10 moedas porque é esse o número que o CoinMarketCap carrega no carregamento inicial da página. Para extrair mais, precisamos de realizar uma ação humana, que consiste em percorrer a página. Felizmente, o Playwright é adequado para esta tarefa.

Vamos começar por refatorar a função $$eval que utilizámos anteriormente e implementar a paginação. Vamos chamar a esta nova função extractData:

const extractData = async (page, currentPage, perPage = 10) => {

}

Ampliamos o seletor :nth-child selecionando itens em etapas (elementos de 0 a 10, de 11 a 21, de 22 a 32, etc.). Definimos o seletor inicial (primeiros 10 elementos):

let selector = `:nth-child(-n+${currentPage * perPage})`;

Por último, mas não menos importante, adicionamos suporte para as páginas seguintes. O código fica assim:

if(currentPage > 1) {

    selector = `:nth-child(n+${(currentPage - 1) + perPage}):nth-child(-n+${(currentPage * perPage) + 1})`;

}

A função final ficará assim:

const extractData = async (page, currentPage, perPage = 10) => {

    let selector = `:nth-child(-n+${currentPage * perPage})`;

    if(currentPage > 1) {

   	 selector = `:nth-child(n+${(currentPage - 1) + perPage}):nth-child(-n+${(currentPage * perPage) + 1})`;

    }

    return await page.$$eval(`.cmc-table tbody tr${selector}`, trs => {

   	 const data = [];

   	 trs.forEach(tr => {

   		 data.push({

   			 name: tr.querySelector('td:nth-child(3) a .name-area p').innerHTML,

   			 price: tr.querySelector('td:nth-child(4) a span').innerHTML,

   		 });

   	 });

   	 return data;

    });

};

Agora é hora de voltar ao nosso código do scraper, implementar a rolagem e ampliar a extração de dados. Fazemos todo o trabalho após esta linha:

await page.goto('https://coinmarketcap.com');

Redefinimos a variável currencies:

// Extract the currencies data

let currencies = await extractData(page, 1, 10);

Usando a função evaluate, fazemos o scroll da página para 1,5x da janela de visualização. Isto irá acionar o carregamento dos próximos elementos da tabela:

// Scroll the page to a little more than the viewport height

await page.evaluate(() => {

    window.scrollTo(0, window.innerHeight * 1.5);

});

O segundo de espera dará à interface do utilizador algum tempo para preencher a tabela com os dados recuperados da API:

// Wait for the new elements to load

await page.waitForTimeout(1000);

Por fim, vamos extrair os dados da segunda página e registar os resultados:

// Extract the next 10 elements

currencies = [...currencies, ...await extractData(page, 2, 10)]

// Display the results

console.log(currencies)

O código completo do scraper deve ficar assim:

const { chromium } = require('playwright');

const extractData = async (page, currentPage, perPage = 10) => {

    let selector = `:nth-child(-n+${currentPage * perPage})`;

    if(currentPage > 1) {

   	 selector = `:nth-child(n+${(currentPage - 1) + perPage}):nth-child(-n+${(currentPage * perPage) + 1})`;

    }

    return await page.$$eval(`.cmc-table tbody tr${selector}`, trs => {

   	 const data = [];

   	 trs.forEach(tr => {

   		 data.push({

   			 name: tr.querySelector('td:nth-child(3) a .name-area p').innerHTML,

   			 price: tr.querySelector('td:nth-child(4) a span').innerHTML,

   		 });

   	 })

   	 return data;

    })

};

(async () => {

    // Launch a Chromium browser

    const browser = await chromium.launch();

    // Create a new page in the browser

    const page = await browser.newPage();

    // Navigate to a website

    await page.goto('https://coinmarketcap.com');

    // Extract the currencies data

    let currencies = await extractData(page, 1, 10)

    // Scroll the page to a little more than the viewport height

    await page.evaluate(() => {

   	 window.scrollTo(0, window.innerHeight * 1.5);

    });

    // Wait for the new elements to load

    await page.waitForTimeout(1000);

    // Extract the next 10 elements

    currencies = [...currencies, ...await extractData(page, 2, 10)];

    // Display the results

    console.log(currencies);

    // Close the browser

    await browser.close();

})();

Para recapitular, o scraper irá abrir a página inicial do CoinMarketCap, extrair os dados das primeiras 10 moedas, percorrer a página, extrair os dados das próximas 10 moedas e apresentar os resultados.

Deve obter resultados semelhantes a estes:

[

  { name: 'Bitcoin', price: '$16,742.58' },

  { name: 'Ethereum', price: '$1,244.45' },

  { name: 'Tether', price: '$0.9997' },

  { name: 'USD Coin', price: '$1.00' },

  { name: 'BNB', price: '$255.78' },

  { name: 'XRP', price: '$0.335' },

  { name: 'Binance USD', price: '$1.00' },

  { name: 'Dogecoin', price: '$0.07066' },

  { name: 'Cardano', price: '$0.2692' },

  { name: 'Polygon', price: '$0.7762' },

  { name: 'Dai', price: '$0.9994' },

  { name: 'Litecoin', price: '$73.80' },

  { name: 'Polkadot', price: '$4.59' },

  { name: 'Solana', price: '$12.95' },

  { name: 'TRON', price: '$0.0505' },

  { name: 'Shiba Inu', price: '$0.000008234' },

  { name: 'Uniswap', price: '$5.29' },

  { name: 'Avalanche', price: '$11.43' },

  { name: 'UNUS SED LEO', price: '$3.47' },

  { name: 'Wrapped Bitcoin', price: '$16,725.03' },

  { name: 'Cosmos', price: '$9.97' }

]

Técnicas avançadas

Agora que abordámos os conceitos básicos do web scraping com o Playwright, tais como criar um scraper, encontrar seletores, extrair dados e implementar a rolagem infinita, é hora de aprofundar algumas das funcionalidades mais avançadas que o Playwright tem para oferecer.

Estas incluem tirar capturas de ecrã, preencher formulários, utilizar XPaths em vez de seletores de classe e utilizar proxies para contornar bloqueios de IP.

Tirar uma captura de ecrã

Uma das vantagens de tirar capturas de ecrã durante o web scraping é que permite ver como um site ou aplicação web se apresenta em diferentes navegadores e resoluções.

Isto pode ser particularmente útil para programadores, que podem usar capturas de ecrã para depurar problemas de layout e testar a aparência das suas aplicações web em diferentes plataformas.

Para tirar uma captura de ecrã de página inteira, pode utilizar o método screenshot do objeto Page. Aqui está um exemplo:

const screenshot = await page.screenshot();

Este código tira uma captura de ecrã de toda a página e devolve-a como um Buffer. A função `screenshot` aceita propriedades. Podemos definir o caminho onde queremos que a captura de ecrã seja guardada e se a captura de ecrã deve conter apenas a janela de visualização ou a página inteira.

Este é o código completo:

const { chromium } = require('playwright');

(async () => {

    const browser = await chromium.launch();

    const page = await browser.newPage();

    await page.goto('https://coinmarketcap.com');

    // Take a full page screenshot and save the file

    await page.screenshot({

   	 path: "screenshot.png",

   	 fullPage: false

    });

    await browser.close();

})();

Pode guardar este código num ficheiro chamado `screenshot.js` e executá-lo com o comando `node screenshot.js`. Após a execução, será criado um ficheiro `screenshot.png` na pasta do seu projeto.

Podemos tirar uma captura de ecrã de uma área da página utilizando a propriedade `clip`. Precisamos de definir quatro propriedades:

  • x: o deslocamento horizontal a partir do canto superior esquerdo
  • y: o deslocamento vertical a partir do canto superior esquerdo
  • width: a largura da área
  • height: a altura da área

A função de captura de ecrã com a propriedade clip definida ficará assim:

// Take a screenshot of a part of the page

await page.screenshot({

    path: "screenshot.png",

    fullPage: false,

    clip: {

        x: 50,

        y: 50,

        width: 320,

        height: 160

    }

});

Preenchimento de formulários

Uma das vantagens de usar o Playwright é que ele permite aceder a páginas protegidas. Ao emular ações humanas, como clicar em botões, percorrer a página e preencher formulários, o Playwright consegue contornar os requisitos de início de sessão e aceder a conteúdos restritos.

Vamos usar o Playwright para aceder à nossa conta do Reddit (se não tiveres uma conta do Reddit, cria uma agora mesmo!).

Vá para a página de login e use as técnicas que aprendemos na secção «Encontrar elementos para extração de dados» para extrair as classes das entradas de nome de utilizador e palavra-passe.

Os seletores devem ficar assim:

  • Campo de nome de utilizador: `#loginUsername`
  • Campo de senha: `#loginPassword`
  • Botão Enviar: `button[type=”submit”]`

Vamos utilizar estes seletores no código. Crie um ficheiro `login.js` e cole este código:

const { chromium } = require('playwright');

(async () => {

    const browser = await chromium.launch();

    const page = await browser.newPage();

    await page.goto('https://reddit.com/login');

    // Fill up the form

    await page.fill('#loginUsername', "YOUR_REDDIT_USERNAME");

    await page.fill('#loginPassword', "YOUR_REDDIT_PASSWORD");

    // Click the submit button

    await page.click('button[type="submit"]');

    // Wait for the new page to load

    await page.waitForNavigation()

    // Take a screenshot of the new page

    await page.screenshot({

   	 path: "reddit.png",

   	 fullPage: false

    });

    // Close the browser

    await browser.close();

})();

Para executar o código e tirar uma captura de ecrã da página protegida, basta digitar node login.js no terminal. Após alguns segundos, uma captura de ecrã chamada reddit.png aparecerá no diretório do seu projeto.

Infelizmente, não posso partilhar a captura de ecrã resultante convosco, uma vez que a maior parte da minha conta do Reddit não é adequada para o ambiente de trabalho.

Podes ler mais sobre a autenticação com o Playwright na documentação oficial.

Usar o XPath para extração de dados

O XPath pode ser uma escolha mais estável para web scraping, pois é menos provável que mude do que os nomes de classe. Sites como o Reddit e o Google atualizam frequentemente os seus nomes de classe, o que pode causar problemas para os scrapers que dependem deles.

Em contrapartida, as expressões XPath baseiam-se na estrutura do documento HTML e são menos suscetíveis de alteração. Isto significa que pode utilizar o XPath para identificar elementos de forma mais fiável e estável, mesmo em sites que atualizam frequentemente os seus nomes de classe.

Como resultado, a utilização do XPath pode ajudá-lo a criar um scraper web mais robusto e resiliente, menos propenso a falhar quando o site é atualizado.

Neste artigo, abordaremos apenas superficialmente o que pode fazer com o XPath. Para um guia mais abrangente, consulte este artigo.

Voltemos ao Reddit, abramos um subreddit e as Ferramentas do Desenvolvedor. Vou usar o subreddit /r/webscraping, mas pode escolher qualquer subreddit que desejar.

Se examinar a árvore DOM, poderá notar que as classes dos elementos parecem ser geradas aleatoriamente. Utilizar estas classes diminuiria a fiabilidade do scraper e exigiria manutenção contínua.

Clique com o botão direito do rato na tag `h3`, vá a Copiar e selecione `Copiar XPath`. O resultado deve ficar assim:

//*[@id="t3_104ocrd"]/div[3]/div[2]/div[1]/a/div/h3

Antes de usarmos esta regra, vamos remover a parte @id para que o caminho abranja todas as publicações e não apenas a primeira.

Está na hora de pôr isto a funcionar. Crie o ficheiro `xpath.js` e cole este código:

const { chromium } = require('playwright');

(async () => {

    const browser = await chromium.launch();

    const page = await browser.newPage();

    await page.goto('https://reddit.com/r/webscraping');

    const titles = await page.$$eval("//*/div[3]/div[2]/div[1]/a/div/h3", element => {

   	 const data = []

   	 element.forEach(el => {

   		 data.push(el.innerHTML)

   	 })

   	 return data

    })

    console.log(titles)

    // Close the browser

    await browser.close();

})();

Para executar o código, use o comando `node xpath.js`. Isto irá devolver uma lista de títulos do subreddit que selecionou. Por exemplo, a minha lista fica assim:

[

  'A Year of Writing about Web Scraping in Review',

  'Linkedin Comments Scraper - Script to scrape comments (including name, profile picture, designation, email(if present), and comment) from a LinkedIn post from the URL of the post.',

  'Best Proxy Lists?',

  'Sorry if this is the wrong sub, but is it possible to extract an email from an old youtube account?',

  'Looking for people with datasets for sale!',

  "Are reddit's classes names change periodically (those with random letters and numbers and what not)",

  'Scrape Videos from multiple websites',

  'Anyone want to write me a program that can automate generating a pdf of a magazine subscription?',

  'Scraping a Dynamic Webpage with rSelenium',

  'Is there a way to convert LinkedIn Sales Navigator URLs to a LinkedIn public URL?',

  'Gurufocus / Implemented new cloudflare protection?',

  'Scraper to collect APY data from Web3 frontends'

]

Podes ler mais sobre o XPath na documentação oficial do Playwright. Podes encontrá-la aqui.

Playwright vs. Os Outros

O Playwright, o Puppeteer e o Selenium WebDriver são todas ferramentas que podem ser usadas para web scraping e automação.

O Playwright, desenvolvido pela Microsoft, é uma ferramenta mais recente que pretende ser uma solução «completa» para a automação web. Suporta vários navegadores (Chromium, Firefox e WebKit) e várias linguagens de programação (JavaScript, TypeScript, Python e C#).

O Puppeteer é uma ferramenta desenvolvida pela Google para web scraping e automação, baseada no Protocolo Chrome DevTools. É utilizada principalmente com JavaScript e possui muitas funcionalidades, incluindo a captura de ecrãs, a geração de PDFs e a interação com o DOM.

O Selenium WebDriver é uma ferramenta para automação e testes na Web que suporta várias linguagens de programação e navegadores. Está voltado para testes e pode exigir mais configuração do que algumas outras ferramentas.

Comparando o desempenho

O desempenho é uma consideração importante na escolha de uma ferramenta de web scraping. Nesta secção, iremos comparar o desempenho do Playwright, do Puppeteer e do Selenium WebDriver para ver qual a ferramenta mais rápida e eficiente.

Durante os nossos testes, descobrimos que o Playwright e o Puppeteer apresentavam tempos de resposta quase idênticos no que diz respeito a tarefas de web scraping e automação. No entanto, o Selenium WebDriver foi significativamente mais lento no arranque, em comparação com as outras duas ferramentas.

Conclusão

O web scraping permite extrair e processar dados de sites, proporcionando uma grande quantidade de informações e oportunidades para empresas e indivíduos. Alguns benefícios do web scraping incluem:

  • Poupança de custos: O web scraping pode ser uma forma económica de recolher dados, uma vez que permite evitar a necessidade de adquirir bases de dados ou APIs dispendiosas.
  • Eficiência de tempo: A extração de grandes quantidades de dados pode ser feita muito mais rapidamente do que a recolha manual.
  • Dados atualizados: O web scraping pode ajudá-lo a manter os seus dados atualizados, permitindo-lhe extrair e atualizar regularmente as suas fontes de dados.

O Playwright é uma ferramenta poderosa para web scraping, oferecendo uma variedade de funcionalidades que o tornam a escolha preferida de muitos utilizadores. Algumas vantagens de utilizar o Playwright incluem:

  • Compatibilidade com o Chromium: O Playwright é construído com base no Chromium, o projeto de navegador de código aberto que alimenta o Google Chrome, dando-lhe acesso às funcionalidades mais recentes da plataforma web e a uma ampla gama de compatibilidade com websites.
  • Suporte para vários navegadores: O Playwright permite-lhe automatizar tarefas em vários navegadores, incluindo o Chrome, o Firefox e o Safari.
  • Facilidade de utilização: O Playwright possui uma API simples e intuitiva, facilitando o início de tarefas de web scraping e automação.
  • Versatilidade: O Playwright pode ser utilizado para uma vasta gama de tarefas, incluindo web scraping, testes e automação.

Em geral, os benefícios do web scraping e as vantagens de utilizar o Playwright tornam-no uma ferramenta essencial para quem procura extrair e processar dados da web.

Se procura uma solução mais fácil para as suas necessidades de web scraping, considere utilizar a WebScrapingAPI. O nosso serviço permite-lhe extrair dados de qualquer site sem a necessidade de lidar com as complexidades da configuração e manutenção de um web scraper.

Com o WebScrapingAPI, basta enviar um pedido HTTP à nossa API com o URL do site que pretende extrair, e nós devolvemos-lhe os dados no formato da sua preferência (JSON, HTML, PNG).

A nossa API trata de todo o trabalho pesado por si, incluindo contornar CAPTCHAs, lidar com bloqueios de IP e lidar com conteúdo dinâmico.

Então, porquê desperdiçar tempo e recursos a criar e a manter o seu próprio web scraper quando pode usar a WebScrapingAPI e obter os dados de que precisa com apenas algumas requisições simples à API? Experimente-nos e veja como podemos ajudar a otimizar as suas necessidades de web scraping.

Sobre o autor
Mihnea-Octavian Manolache, Desenvolvedor Full Stack @ WebScrapingAPI
Mihnea-Octavian ManolacheDesenvolvedor Full Stack

Mihnea-Octavian Manolache é engenheiro Full Stack e DevOps na WebScrapingAPI, onde desenvolve funcionalidades do produto e mantém a infraestrutura que garante o bom funcionamento da plataforma.

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.