Voltar ao blogue
Ciência da recolha de dados da Web
Mihai Maxim3 de março de 202311 min de leitura

Perguntas comuns sobre Web Scraping - Respostas e dicas

Perguntas comuns sobre Web Scraping - Respostas e dicas

Porque é que o meu scraper não consegue ver os mesmos dados que o meu browser?

You've written a script to fetch HTML from a website, but you're not getting the full data. You've tested your selectors in the browser and they should work, right? Not always. Websites that rely on JavaScript to render won't work with a simple GET request. There are libraries like Puppeteer and Selenium that use headless browsers to render JavaScript. They allow you to make the request in the context of a browser and wait for JavaScript to finish executing. This way, you can get the full HTML. You may not always need a headless browser to get the missing data. Search for <script> tags in the HTML. The missing data could be hidden inside <script> tags as JavaScript variables.

Como é que posso recolher dados de um sítio Web que utiliza classes CSS geradas?

Alguns sítios Web utilizam bibliotecas que criam automaticamente nomes de classe únicos para diferentes componentes da página. Isto pode dificultar a utilização de selectores CSS tradicionais para selecionar elementos específicos.

Uma solução é usar expressões XPath em vez disso. Os selectores XPath baseiam-se na disposição da página, em vez de nomes de classes específicos. Isto significa que, mesmo que os nomes das classes mudem, o seletor XPath continuará a ser capaz de localizar o elemento pretendido.

Por exemplo, se tiver um componente HTML com o seguinte aspeto:

<div class="container">

    <div class="subcontainer_af21">

        <ul class="ul_ax1">

            <li class="li_adef">

                <a href="https://link1">Winter Storm</a>

            </li>

        </ul>

        <ul class="ul_cgt4">

            <li class="li_ocv2">

                <a href="https://lin2">SpaceX</a>

            </li>

        </ul>

    </div>

</div>

You can select the second <a> element with:

//div[@class='container']/div/ul[2]/li/a

O cheerio é mais rápido do que o Puppeteer?

Sim, o Cheerio é geralmente considerado mais rápido que o Puppeteer. Isso ocorre porque o Cheerio é uma biblioteca do lado do servidor que trabalha diretamente com o conteúdo HTML. O Puppeteer é uma biblioteca de automação de navegador que controla um navegador sem cabeça para carregar páginas da Web e interagir com elas. O Cheerio é limitado no sentido de que só pode trabalhar com páginas estáticas, não tem a capacidade de interagir com o navegador como o Puppeteer faz

Os selectores XPath são melhores do que os selectores CSS?

Depende do contexto. Se pretender extrair dados com base na posição dos elementos, o XPath é a melhor escolha. No entanto, se pretender extrair dados com base em propriedades como classe ou id, os selectores CSS são uma melhor opção.

O Playwright é melhor do que o Puppeteer?

Ambos oferecem funcionalidades semelhantes, mas. O Playwright suporta vários navegadores, incluindo Chrome, Firefox e Safari. O Puppeteer suporta apenas o Chrome e o Chromium.

O Playwright tem um melhor suporte para trabalhar com vários separadores e janelas. Também tem suporte incorporado para lidar com contextos do navegador, cookies e armazenamento. O Playwright é mais adequado para projectos complexos.

Como posso evitar os bloqueios de IP?

Em geral, pode tentar espaçar os seus pedidos. Utilizar IPs diferentes. Utilizar proxies. Tentar alterar a impressão digital do navegador. Para a maioria das pessoas, esta é uma batalha interminável. A boa notícia é que não precisa de ser assim. Pode utilizar a nossa solução, WebScrapingAPI. O WebScrapingAPI fornece uma API que tratará de todo o trabalho pesado para si. Ela pode executar JavaScript, girar proxies e até mesmo lidar com CAPTCHAs. Nunca terá de se preocupar com o facto de o seu IP ser banido. Mas não acredite na nossa palavra. Pode experimentá-lo gratuitamente.

Como extrair texto de HTML com BeautifulSoup?

Pode utilizar a biblioteca BeautifulSoup. Aqui está um exemplo de extração de texto utilizando a função .get_text():

from bs4 import BeautifulSoup

html_doc = """

<html>

 <head>

   <title>title of the page</title>

 </head>

 <body>

   <p>a paragraph</p>

   <a href='https://link.com'>a link</a>

 </body>

</html>

"""

soup = BeautifulSoup(html_doc, 'html.parser')

paragraph_text = soup.find('p').text

print(paragraph_text)

#Prints 'a paragraph'

link_text = soup.find('a').text

print(link_text)

#Prints 'a link'

all_text = soup.get_text()

print(all_text)

"""

title of the page

a paragraph

a link

"""

Como extrair texto de HTML com o Selenium?

Eis como o pode fazer no Selenium:

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'caminho/para/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# obtém todos os elementos h2

content = driver.find_element(By.TAG_NAME, "h2")

print(content.text)

# Imprime 'Do artigo em destaque de hoje'

Como selecionar elementos HTML por texto com o BeautifulSoup?

With BeautifulSoup, you can use the soup.find method with the text=re.compile("<text>") parameter:

from bs4 import BeautifulSoup

import re

html_doc = """

<html>

<body>

  <p class="my_paragraph">a paragraph.</p>

  <p class="my_paragraph">another paragraph.</p>

</body>

</html>

"""

soup = BeautifulSoup(html_doc, 'html.parser')

# find the first pTag that contains the text 'a par'

pTag = soup.find("p", text=re.compile("a par"))

print(pTag)

Como selecionar elementos HTML por texto com o Selenium?

No Selenium, pode fazê-lo com XPath:

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'caminho/para/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# obtém todos os elementos com a classe vector-body

span = driver.find_element(By.XPATH, "//span[contains(text(), 'Did')]")

print(span.text)

# Imprime 'Did you know ...'

driver.quit()

Como encontrar elementos HTML com selectores CSS no BeautifulSoup?

Eis como o pode fazer com BeautifulSoup e os métodos find e find_all:

from bs4 import BeautifulSoup

html_doc = """

<html>

  <body>

    <p class="my_paragraph">First paragraph.</p>

    <p class="my_paragraph">Second paragraph..</p>

    <p>Last paragraph.</p>

  </body>

</html>

"""

soup = BeautifulSoup(html_doc, 'html.parser')

# find all elements with class 'my_paragraph

elements = soup.find_all(class_="my_paragraph")

for element in elements:

    print(element.text)

# prints 'First paragraph.' and 'Second paragraph..'

Como encontrar elementos HTML por classe com o Selenium?

Eis como o pode fazer com o Selenium:

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'caminho/para/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# obtém todos os elementos com a classe vector-body

elements = driver.find_elements(By.CLASS_NAME, "vector-body")

for element in elements:

   print(element.text)

driver.quit()

Como utilizar o XPath com o BeautifulSoup?

Necessitará da biblioteca Python lxml:

import requests

from bs4 import BeautifulSoup

from lxml import etree

response = requests.get("https://en.wikipedia.org/wiki/Main_Page")

soup = BeautifulSoup(response.content, 'html.parser')

dom = etree.HTML(str(body))

xpath_str = '//h1//text()'

print(dom.xpath(xpath_str))

#Imprime ['Página Principal', 'Bem-vindo à ', 'Wikipedia']

Como esperar que a página seja carregada no Selenium?

Se pretender simplesmente esperar um determinado tempo antes de atingir o tempo limite ao tentar encontrar qualquer elemento, pode utilizar a função driver.implicitly_wait(time_in_secods):

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'C:/Users/Michael/Desktop/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.implicitly_wait(10)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

element = driver.find_element(By.ID, "not_found_id")

# o elemento não existe, mas espera 10 segundos por ele

text = element.text

print(text)

# Fechar o navegador

driver.quit()

Também pode optar por esperar até que uma determinada condição seja cumprida:

from selenium import webdriver

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

DRIVER_PATH = 'C:/Users/Michael/Desktop/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# Aguardar até que o elemento com o id 'content' esteja presente na página

wait = WebDriverWait(driver, 10)

element = wait.until(EC.presence_of_element_located((By.ID, "content")))

element = driver.find_element(By.ID, "content")

text = element.text

print(text)

# Fechar o navegador

driver.quit()

Como encontrar elementos HTML com selectores CSS no Puppeteer?

No Puppeteer, pode utilizar as funções page.$() e page.$$() para selecionar elementos com selectores CSS. A função page.$() é utilizada para encontrar o primeiro elemento que corresponde ao seletor. A função page.$$() é utilizada para encontrar todos os elementos que correspondem ao seletor.

const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch({

    headless: false,

  });

 

  const page = await browser.newPage();

  await page.goto('https://www.scrapethissite.com/pages/simple/');

  // Extract the first odd row element 

  const firstOddRow = await page.$('.container .row');

  console.log(await firstOddRow.evaluate(node => node.textContent));

  // Extract all the odd rows

  const allOddRows = await page.$$('.container .row');

  for (const oddRow of allOddRows) {

    console.log(await oddRow.evaluate(node => node.textContent));

  }

  await browser.close();

})();

Como encontrar elementos HTML com selectores CSS no Playwright?

Eis como o pode fazer com o Playwright. É muito semelhante ao Puppeteer:

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

(async () => {

  const browser = await chromium.launch({

    headless: false,

  });

  const context = await browser.newContext();

  const page = await context.newPage();

  await page.goto('https://www.scrapethissite.com/pages/simple/');

  // Extract the first odd row element

  const firstOddRow = await page.$('.container .row');

  console.log(await firstOddRow.textContent());

  // Extract all the odd rows

  const allOddRows = await page.$$('.container .row');

  for (const oddRow of allOddRows ) {

    console.log(await oddRow.textContent());

  }

  await browser.close();

})();

Como encontrar elementos HTML com selectores CSS no cheerio?

Com o cheerio, terá de ir buscar o HTML (usei a biblioteca request para o fazer) e depois passá-lo para a biblioteca cheerio:

const request = require('request');

const cheerio = require('cheerio');

const url = 'https://www.scrapethissite.com/pages/simple/';

request(url, (error, response, html) => {

  if (!error && response.statusCode === 200) {

    const $ = cheerio.load(html);

    const firstOddRow = $('.container .row').first();

    console.log(firstOddRow.text());

    const allOddRows = $('.container .row');

    allOddRows.each((i, oddRow) => {

      console.log($(oddRow).text());

    });

  }

});

Como utilizar o XPath com o Puppeteer?

Com o Puppeteer, pode utilizar a função page.$x() para selecionar elementos com selectores XPath:

const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch();

  const page = await browser.newPage();

  await page.goto('https://www.scrapethissite.com/pages/forms/');

  // Extract the table header elements

  const allTableHeaders = await page.$x('//table/tbody/tr[1]//th');

  for(let i = 0; i < allTableHeaders.length; i++) {

    const header = await page.evaluate(el => el.textContent, allTableHeaders[i]);

    console.log(header.trim());

  }

  await browser.close();

})();

// Output:

// Team Name

// Year

// Wins

// Losses

// OT Losses

// Win %

// Goals For (GF)

// Goals Against (GA)

// + / -

Como utilizar o XPath com o Playwright?

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

(async () => {

  const browser = await chromium.launch({

    headless: false,

  });

  const context = await browser.newContext();

  const page = await context.newPage();

  await page.goto('https://www.scrapethissite.com/pages/forms/');

  // Extract the table header elements

  const allTableHeaders = await page.locator('xpath=//table/tbody/tr[1]//th').all();

 

  for (let i = 0; i < allTableHeaders.length; i++) {

    const headerText = await allTableHeaders[i].innerText();

    console.log(headerText);

  }

  await browser.close();

})();

Qualquer string de seletor que comece com // ou ... é assumido como um seletor xpath. Por exemplo, o Playwright converte '//html/body' para 'xpath=//html/body'.

Como encontrar elementos HTML por texto no Puppeteer?

No Puppeteer, a forma mais simples de encontrar elementos por texto é utilizar a função XPath text():

const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch({

    headless: false,

  });

  const page = await browser.newPage();

  await page.goto('https://en.wikipedia.org/wiki/Web_scraping');

   // Select all the p tags texts that contain the word "prevent" 

   const pTags = await page.$x('//p[contains(text(), "prevent")]/text()');

   for(let i = 0; i < pTags.length; i++) {

     const pTag = await page.evaluate(el => el.textContent, pTags[i]);

     console.log(pTag,"\n");

   }

  await browser.close();

})();

//Output:

There are methods that some websites use to prevent web scraping, such as detecting and disallowing bots from crawling (viewing) their pages. In response, there are web scraping systems that rely on using techniques in ...     

Como encontrar elementos HTML por texto no Playwright?

Se pretender encontrar elementos por texto no Playwright, pode utilizar a função allInnerTexts() em combinação com XPath.

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

(async () => {

  const browser = await chromium.launch({

    headless: false,

  });

  const context = await browser.newContext();

  const page = await context.newPage();

  await page.goto('https://en.wikipedia.org/wiki/Web_scraping');

  // Select all the p tags texts that contain the word "prevent" 

  const pTags  = await page.locator('//p[contains(text(), "prevent")]').allInnerTexts();

 

  for (let i = 0; i < pTags.length; i++) {

    console.log(pTags[i], "\n");

  }

  await browser.close();

})();

Como encontrar elementos HTML por texto no cheerio?

const request = require('request');

const cheerio = require('cheerio');

const url = 'https://en.wikipedia.org/wiki/Web_scraping';

request(url, (error, response, html) => {

  if (!error && response.statusCode === 200) {

    const $ = cheerio.load(html);

  // Select all the p tags texts that contain the word "prevent" 

    const elements = $('p').filter((i, el) => $(el).text().includes('prevent'));

    elements.each((i, el) => {

        console.log($(el).text());

    });

  }

});

Como esperar pelos selectores no Puppeteer?

No Puppeteer, pode utilizar a função page.waitForSelector() para esperar que um elemento específico apareça na página antes de continuar com o script. Pode utilizá-la com selectores CSS e XPath:

await page.waitForSelector('.basic-element', { timeout: 10000 });

await page.waitForXPath("//div[@class='basic-element']"), { timeout: 10000 });

O parâmetro timeout especifica o tempo máximo de espera em ms.

Também é possível esperar que um elemento atinja um determinado estado:

await page.waitForSelector('.basic-element', { visible: true });

// wait until the element becomes visible

Como esperar pelos selectores no Playwright?

O Playwright é semelhante ao Puppeteer. Pode utilizar o método page.waitForSelector() para esperar que um elemento específico apareça na página.

await page.waitForSelector('.element-class', { timeout: 10000 });

Também é possível esperar que um elemento atinja um determinado estado:

 await page.waitForSelector('.basic-element', { state: 'visible' });

 // wait for element to become visible

Concluir

A raspagem da Web é um assunto vasto e este artigo apenas cobre a superfície. Escolher a ferramenta certa para o seu caso de uso específico é crucial. Por exemplo, se quiser fazer scraping de um site usando JavaScript, a biblioteca cheerio é uma boa opção. No entanto, se o site requer JavaScript para carregar completamente, Puppeteer ou Playwright são melhores opções. A raspagem da Web é um desafio, mas entender as ferramentas pode poupar muitas dores de cabeça. Espero que este artigo tenha alargado a sua perspetiva e desejo-lhe as maiores felicidades nos seus esforços de Web scraping.

Sobre o autor
Mihai Maxim, Desenvolvedor Full Stack na WebScrapingAPI
Mihai MaximDesenvolvedor Full Stack

Mihai Maxim é um programador Full Stack na WebScrapingAPI, contribuindo em todas as áreas do produto e ajudando a criar ferramentas e funcionalidades fiáveis para a 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.