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/aO 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 visibleComo 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 visibleConcluir
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.




