14 Web Scraping com BeautifulSoup
De colecionador de figurinhas para coletor de dados: extraindo informações da web!
14.1 O que você vai aprender neste capítulo?
- O que é Web Scraping e quando usar essa técnica
- HTML básico: entendendo a estrutura de páginas web (tags, classes, IDs)
- BeautifulSoup: como usar a biblioteca para fazer parsing de HTML
- Seletores: como encontrar elementos específicos na página
- requests + BeautifulSoup: combinando requisições HTTP com parsing
- Exemplos práticos: extrair títulos, preços, links e dados estruturados
- Ética e legalidade: boas práticas e responsabilidade no scraping
- Projetos reais: criar sistemas de coleta de dados da web
🎓 Vindo do Capítulo 13? Perfeito! Agora que você sabe criar APIs, vamos extrair dados de páginas web!
🎯 Meta: Ao final deste capítulo, você vai conseguir extrair dados de páginas web, processar HTML e criar sistemas de coleta de informações da internet.
⚠️ Por que isso importa: Web scraping é uma ferramenta poderosa! Use com responsabilidade, respeitando os termos de uso dos sites e implementando delays entre requisições.
14.2 De Colecionador de Figurinhas para Coletor de Dados
14.2.1 Analogia Perfeita: Colecionador de Figurinhas
Imagine que você é um colecionador de figurinhas e quer completar seu álbum:
- Álbum (Site web): Onde estão todas as figurinhas organizadas
- Figurinhas (Dados): As informações que você quer coletar
- Colecionador (Seu código): Você que vai extrair as figurinhas
- Tesoura (BeautifulSoup): Ferramenta para “recortar” as figurinhas
- Cola (Salvar dados): Como você organiza as figurinhas coletadas
Em programação, funciona assim:
- Site web: Página com dados organizados em HTML
- Dados: Informações que você quer extrair (títulos, preços, links)
- Seu código Python: Programa que vai coletar os dados
- BeautifulSoup: Biblioteca que “recorta” os dados do HTML
- Arquivo/banco: Onde você salva os dados coletados
14.2.2 O que é Web Scraping?
Web Scraping é o processo de extrair dados automaticamente de páginas web.
É como ser um colecionador digital que:
- 📖 Lê páginas web automaticamente
- ✂️ Recorta as informações que precisa
- 📁 Organiza os dados coletados
- 💾 Salva em arquivos ou bancos de dados
14.2.3 Quando usar Web Scraping?
- 📊 Análise de preços: Comparar preços de produtos
- 📰 Coleta de notícias: Extrair manchetes e artigos
- 📈 Dados financeiros: Cotações de ações e moedas
- 🏠 Imóveis: Preços e características de casas
- 🎬 Filmes: Informações de filmes e séries
- 📚 Livros: Dados de livros e autores
14.2.4 Exemplo prático
Sem scraping (problema):
- Você precisa acessar 100 sites manualmente
- Copiar e colar informações uma por uma
- Organizar tudo em planilhas
- Atualizar dados regularmente
Com scraping (solução):
- Seu código acessa os sites automaticamente
- Extrai todas as informações de uma vez
- Organiza os dados automaticamente
- Atualiza quando você quiser
💡 Exemplo: Sites como Google, Amazon e Netflix usam scraping para coletar dados de outros sites e oferecer serviços melhores!
14.3 HTML Básico - Entendendo a Estrutura das Páginas
14.3.1 O que é HTML?
HTML (HyperText Markup Language) é a linguagem que estrutura as páginas web. É como o esqueleto de uma página!
14.3.3 Classes e IDs
Explicação:
class="produto": Classe - pode ser usada várias vezesid="titulo-principal": ID - deve ser único na páginahref="/comprar": Atributo - propriedade do elemento
14.3.4 Estrutura de uma Página Web
<!DOCTYPE html>
<html>
<head>
<title>Minha Loja</title>
</head>
<body>
<header>
<h1>Bem-vindo à Minha Loja</h1>
</header>
<main>
<div class="produtos">
<div class="produto">
<h2>Notebook</h2>
<p class="preco">R$ 2.500</p>
</div>
<div class="produto">
<h2>Mouse</h2>
<p class="preco">R$ 50</p>
</div>
</div>
</main>
<footer>
<p>© 2024 Minha Loja</p>
</footer>
</body>
</html>14.3.5 Como BeautifulSoup “Lê” HTML
BeautifulSoup transforma HTML em uma árvore que você pode navegar:
# HTML de exemplo
html = """
<div class="produtos">
<div class="produto">
<h2>Notebook</h2>
<p class="preco">R$ 2.500</p>
</div>
<div class="produto">
<h2>Mouse</h2>
<p class="preco">R$ 50</p>
</div>
</div>
"""
# BeautifulSoup organiza assim:
# div.produtos
# div.produto
# h2: "Notebook"
# p.preco: "R$ 2.500"
# div.produto
# h2: "Mouse"
# p.preco: "R$ 50"💡 Dica: Você não precisa ser expert em HTML! Apenas entender que páginas web são como documentos estruturados com tags que organizam o conteúdo.
14.4 BeautifulSoup - Sua Ferramenta de Scraping
14.4.1 Instalando BeautifulSoup
14.4.2 Primeiro Exemplo: Extraindo Títulos
from bs4 import BeautifulSoup
import requests
# HTML de exemplo (simulando uma página web)
html_exemplo = """
<html>
<head>
<title>Minha Loja Online</title>
</head>
<body>
<h1>Produtos em Promoção</h1>
<div class="produtos">
<div class="produto">
<h2>Notebook Gamer</h2>
<p class="preco">R$ 2.500,00</p>
</div>
<div class="produto">
<h2>Mouse Óptico</h2>
<p class="preco">R$ 50,00</p>
</div>
<div class="produto">
<h2>Teclado Mecânico</h2>
<p class="preco">R$ 120,00</p>
</div>
</div>
</body>
</html>
"""
# Criar objeto BeautifulSoup
soup = BeautifulSoup(html_exemplo, 'html.parser')
# Extrair título da página
titulo = soup.find('title').text
print(f"Título da página: {titulo}")
# Extrair todos os títulos h2 (nomes dos produtos)
produtos = soup.find_all('h2')
print("\nProdutos encontrados:")
for i, produto in enumerate(produtos, 1):
print(f"{i}. {produto.text}")Saída esperada:
Título da página: Minha Loja Online
Produtos encontrados:
1. Notebook Gamer
2. Mouse Óptico
3. Teclado Mecânico
14.4.3 Seletores Básicos
# Extrair por tag
titulos = soup.find_all('h2')
# Extrair por classe
precos = soup.find_all('p', class_='preco')
# Extrair por ID
titulo_principal = soup.find('h1')
# Extrair primeiro elemento
primeiro_produto = soup.find('div', class_='produto')
# Extrair texto de um elemento
texto_preco = soup.find('p', class_='preco').text14.4.4 Exemplo Prático: Extraindo Preços
# Extrair todos os preços
precos = soup.find_all('p', class_='preco')
print("Preços encontrados:")
for preco in precos:
print(f"- {preco.text}")
# Extrair produtos completos (nome + preço)
produtos = soup.find_all('div', class_='produto')
print("\nProdutos completos:")
for produto in produtos:
nome = produto.find('h2').text
preco = produto.find('p', class_='preco').text
print(f"📦 {nome} - {preco}")Saída esperada:
Preços encontrados:
- R$ 2.500,00
- R$ 50,00
- R$ 120,00
Produtos completos:
📦 Notebook Gamer - R$ 2.500,00
📦 Mouse Óptico - R$ 50,00
📦 Teclado Mecânico - R$ 120,00
14.5 Scraping de Sites Reais - requests + BeautifulSoup
14.5.1 Combinando requests e BeautifulSoup
import requests
from bs4 import BeautifulSoup
import time
def extrair_titulos_noticias(url):
"""Extrai títulos de notícias de um site"""
try:
# Fazer requisição HTTP
response = requests.get(url)
response.raise_for_status() # Verificar se deu erro
# Criar objeto BeautifulSoup
soup = BeautifulSoup(response.content, 'html.parser')
# Extrair títulos (ajuste os seletores conforme o site)
titulos = soup.find_all('h2') # ou 'h3', 'h1', etc.
print(f"📰 Encontrados {len(titulos)} títulos:")
for i, titulo in enumerate(titulos[:5], 1): # Mostrar apenas os 5 primeiros
print(f"{i}. {titulo.get_text().strip()}")
return titulos
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar o site: {e}")
return None
# Exemplo de uso (substitua pela URL real)
# titulos = extrair_titulos_noticias('https://exemplo.com/noticias')14.5.2 Scraping Responsável - Boas Práticas
import requests
from bs4 import BeautifulSoup
import time
import random
def scraping_responsavel(url):
"""Faz scraping respeitando o site"""
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
try:
# Delay aleatório entre requisições (1-3 segundos)
time.sleep(random.uniform(1, 3))
# Fazer requisição com headers
response = requests.get(url, headers=headers)
response.raise_for_status()
# Parse do HTML
soup = BeautifulSoup(response.content, 'html.parser')
return soup
except requests.exceptions.RequestException as e:
print(f"❌ Erro: {e}")
return None
# Exemplo de uso
# soup = scraping_responsavel('https://exemplo.com')14.5.3 Exemplo Prático: Extrair Dados de Produtos
def extrair_produtos_loja(url):
"""Extrai informações de produtos de uma loja online"""
soup = scraping_responsavel(url)
if not soup:
return None
produtos = []
# Encontrar todos os produtos (ajuste os seletores)
items = soup.find_all('div', class_='produto') # ou outro seletor
for item in items:
try:
nome = item.find('h3').text.strip()
preco = item.find('span', class_='preco').text.strip()
link = item.find('a').get('href')
produtos.append({
'nome': nome,
'preco': preco,
'link': link
})
except AttributeError:
continue # Pular se não encontrar algum elemento
return produtos
# Exemplo de uso
# produtos = extrair_produtos_loja('https://loja-exemplo.com')
# for produto in produtos:
# print(f" {produto['nome']} - {produto['preco']}")14.5.4 Salvando Dados Coletados
import json
import csv
def salvar_dados_json(dados, arquivo):
"""Salva dados em arquivo JSON"""
with open(arquivo, 'w', encoding='utf-8') as f:
json.dump(dados, f, ensure_ascii=False, indent=2)
print(f"✅ Dados salvos em {arquivo}")
def salvar_dados_csv(dados, arquivo):
"""Salva dados em arquivo CSV"""
if not dados:
return
with open(arquivo, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=dados[0].keys())
writer.writeheader()
writer.writerows(dados)
print(f"✅ Dados salvos em {arquivo}")
# Exemplo de uso
# produtos = extrair_produtos_loja('https://exemplo.com')
# salvar_dados_json(produtos, 'produtos.json')
# salvar_dados_csv(produtos, 'produtos.csv')💡 Dica: Sempre teste seus seletores primeiro! Use o navegador (F12) para inspecionar o HTML e encontrar os seletores corretos.
14.6 Exercícios Práticos (respostas no final da página)
🚀 Hora de praticar! Aqui estão 25 exercícios organizados por dificuldade. Cada exercício tem solução completa com explicação linha por linha!
14.6.1 MUITO FÁCIL (Nível 1)
1. Extrator de Títulos H1 Crie uma função que extrai todos os títulos <h1> de uma página HTML.
- Exemplo: Input → HTML com 3 títulos H1 | Output → Lista com os 3 títulos
2. Extrator de Links Extraia todos os links (<a>) de uma página e mostre apenas os URLs.
- Exemplo: Input → HTML com 5 links | Output → Lista com 5 URLs
3. Contador de Imagens Crie uma função que conta quantas imagens (<img>) existem em uma página.
- Exemplo: Input → HTML com 10 imagens | Output →
10
4. Extrator de Parágrafos Extraia o texto de todos os parágrafos (<p>) de uma página.
- Exemplo: Input → HTML com 3 parágrafos | Output → Lista com os 3 textos
5. Extrator por Classe Crie uma função que encontra elementos por classe CSS específica.
- Exemplo: Input → HTML com elementos classe “preco” | Output → Lista com elementos da classe
14.6.2 FÁCIL (Nível 2)
6. Scraper de Produtos Crie um scraper que extrai títulos e preços de produtos de uma loja online.
- Exemplo: Input → HTML de loja | Output →
[{"nome": "Notebook", "preco": "R$ 2500"}]
7. Extrator de Contato Extraia informações de contato (email, telefone) de uma página de empresa.
- Exemplo: Input → HTML com contatos | Output →
{"email": "contato@empresa.com", "telefone": "11999999999"}
8. Coletor de Imagens Crie uma função que coleta todas as imagens e seus atributos alt.
- Exemplo: Input → HTML com imagens | Output →
[{"src": "img1.jpg", "alt": "Produto 1"}]
9. Extrator de Tabelas Extraia dados de uma tabela HTML e salve em formato CSV.
- Exemplo: Input → Tabela HTML | Output → Arquivo CSV com dados
10. Scraper de Notícias Crie um scraper que coleta manchetes de notícias de um site.
- Exemplo: Input → Site de notícias | Output →
["Manchete 1", "Manchete 2", "Manchete 3"]
14.6.3 MÉDIO (Nível 3)
11. Monitor de Preços Crie um sistema que monitora preços de produtos em múltiplos sites.
- Exemplo: Input → URLs de 3 lojas | Output → Comparação de preços
12. Extrator de Perfis Extraia informações de perfis de usuários de uma rede social.
- Exemplo: Input → Perfil de usuário | Output →
{"nome": "João", "seguidores": 1000}
13. Scraper de Imóveis Crie um scraper que coleta dados de imóveis (preço, localização, características).
- Exemplo: Input → Site de imóveis | Output →
[{"preco": "R$ 500000", "localizacao": "São Paulo"}]
14. Extrator de Filmes Extraia dados de filmes/séries de um site de streaming.
- Exemplo: Input → Site de streaming | Output →
[{"titulo": "Filme A", "genero": "Ação"}]
15. Scraper de Vagas Crie um sistema que coleta informações de vagas de emprego.
- Exemplo: Input → Site de vagas | Output →
[{"cargo": "Desenvolvedor", "salario": "R$ 8000"}]
14.6.4 DIFÍCIL (Nível 4)
16. Scraper com Paginação Crie um scraper que navega por múltiplas páginas (paginação).
- Exemplo: Input → Site com 5 páginas | Output → Dados de todas as 5 páginas
17. Extrator de Gráficos Extraia dados de gráficos e visualizações de dados de sites.
- Exemplo: Input → Site com gráficos | Output → Dados numéricos dos gráficos
18. Monitor de Mudanças Crie um sistema que monitora mudanças em páginas web ao longo do tempo.
- Exemplo: Input → URL para monitorar | Output → Relatório de mudanças
19. Extrator de APIs JavaScript Extraia dados de APIs que são carregadas via JavaScript.
- Exemplo: Input → Site com dados via JS | Output → Dados extraídos
20. Scraper Anti-Bloqueio Crie um scraper que contorna proteções básicas contra scraping.
- Exemplo: Input → Site com proteção | Output → Dados extraídos com sucesso
14.6.5 MUITO DIFÍCIL (Nível 5)
21. Sistema de Monitoramento Crie um sistema completo de monitoramento de preços com alertas.
- Exemplo: Input → Produtos para monitorar | Output → Sistema com alertas automáticos
22. Scraper com Autenticação Extraia dados de sites com autenticação e sessões.
- Exemplo: Input → Site que requer login | Output → Dados extraídos após autenticação
23. Scraper Distribuído Crie um scraper distribuído que roda em múltiplas máquinas.
- Exemplo: Input → Lista de URLs | Output → Scraping distribuído em várias máquinas
24. Scraper Anti-CAPTCHA Extraia dados de sites com proteções avançadas (CAPTCHA, rate limiting).
- Exemplo: Input → Site com CAPTCHA | Output → Dados extraídos contornando proteções
25. Scraper Adaptativo Crie um sistema de scraping que se adapta automaticamente a mudanças no HTML.
- Exemplo: Input → Site que muda HTML | Output → Scraper que se adapta automaticamente
14.7 Respostas e Explicações
14.7.1 MUITO FÁCIL (Nível 1)
1. Extrator de Títulos H1
from bs4 import BeautifulSoup
def extrair_titulos_h1(html):
"""Extrai todos os títulos H1 de uma página HTML"""
soup = BeautifulSoup(html, 'html.parser')
titulos = soup.find_all('h1')
return [titulo.get_text().strip() for titulo in titulos]
# Exemplo de uso
html_exemplo = """
<html>
<head><title>Minha Página</title></head>
<body>
<h1>Título Principal</h1>
<h1>Outro Título</h1>
<p>Parágrafo normal</p>
<h1>Terceiro Título</h1>
</body>
</html>
"""
titulos = extrair_titulos_h1(html_exemplo)
print("Títulos encontrados:")
for i, titulo in enumerate(titulos, 1):
print(f"{i}. {titulo}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa a biblioteca BeautifulSoup para parsing de HTML - Linha 3:
def extrair_titulos_h1(html):- Define função que recebe HTML como parâmetro - Linha 4:
"""Extrai todos os títulos H1 de uma página HTML"""- Docstring explicando função - Linha 5:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup para parsear HTML - Linha 6:
titulos = soup.find_all('h1')- Encontra todos os elementos H1 na página - Linha 7:
return [titulo.get_text().strip() for titulo in titulos]- Retorna lista com textos dos títulos - Linha 9:
# Exemplo de uso- Comentário explicativo - Linhas 10-20: Define HTML de exemplo para teste
- Linha 22:
titulos = extrair_titulos_h1(html_exemplo)- Chama função com HTML de exemplo - Linha 23:
print("Títulos encontrados:")- Imprime cabeçalho - Linha 24:
for i, titulo in enumerate(titulos, 1):- Percorre títulos com numeração - Linha 25:
print(f"{i}. {titulo}")- Imprime cada título numerado
2. Extrator de Links
from bs4 import BeautifulSoup
def extrair_links(html):
"""Extrai todos os links de uma página HTML"""
soup = BeautifulSoup(html, 'html.parser')
links = soup.find_all('a')
return [link.get('href') for link in links if link.get('href')]
# Exemplo de uso
html_exemplo = """
<html>
<body>
<a href="https://www.google.com">Google</a>
<a href="https://www.github.com">GitHub</a>
<a href="/pagina-interna">Página Interna</a>
<a href="#topo">Topo</a>
</body>
</html>
"""
links = extrair_links(html_exemplo)
print("Links encontrados:")
for i, link in enumerate(links, 1):
print(f"{i}. {link}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 3:
def extrair_links(html):- Define função para extrair links - Linha 4:
"""Extrai todos os links de uma página HTML"""- Docstring explicando função - Linha 5:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 6:
links = soup.find_all('a')- Encontra todos os elementos de link - Linha 7:
return [link.get('href') for link in links if link.get('href')]- Retorna URLs dos links - Linha 9:
# Exemplo de uso- Comentário explicativo - Linhas 10-18: Define HTML de exemplo com links
- Linha 20:
links = extrair_links(html_exemplo)- Chama função com HTML de exemplo - Linha 21:
print("Links encontrados:")- Imprime cabeçalho - Linha 22:
for i, link in enumerate(links, 1):- Percorre links com numeração - Linha 23:
print(f"{i}. {link}")- Imprime cada link numerado
3. Contador de Imagens
from bs4 import BeautifulSoup
def contar_imagens(html):
"""Conta quantas imagens existem em uma página HTML"""
soup = BeautifulSoup(html, 'html.parser')
imagens = soup.find_all('img')
return len(imagens)
# Exemplo de uso
html_exemplo = """
<html>
<body>
<img src="imagem1.jpg" alt="Primeira imagem">
<img src="imagem2.png" alt="Segunda imagem">
<img src="imagem3.gif" alt="Terceira imagem">
<p>Texto com <img src="imagem4.jpg" alt="Quarta imagem"> inline</p>
</body>
</html>
"""
quantidade = contar_imagens(html_exemplo)
print(f"Total de imagens encontradas: {quantidade}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 3:
def contar_imagens(html):- Define função para contar imagens - Linha 4:
"""Conta quantas imagens existem em uma página HTML"""- Docstring explicando função - Linha 5:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 6:
imagens = soup.find_all('img')- Encontra todos os elementos de imagem - Linha 7:
return len(imagens)- Retorna quantidade de imagens encontradas - Linha 9:
# Exemplo de uso- Comentário explicativo - Linhas 10-18: Define HTML de exemplo com imagens
- Linha 20:
quantidade = contar_imagens(html_exemplo)- Chama função com HTML de exemplo - Linha 21:
print(f"Total de imagens encontradas: {quantidade}")- Imprime resultado
4. Extrator de Parágrafos
from bs4 import BeautifulSoup
def extrair_paragrafos(html):
"""Extrai o texto de todos os parágrafos de uma página HTML"""
soup = BeautifulSoup(html, 'html.parser')
paragrafos = soup.find_all('p')
return [paragrafo.get_text().strip() for paragrafo in paragrafos]
# Exemplo de uso
html_exemplo = """
<html>
<body>
<h1>Título da Página</h1>
<p>Este é o primeiro parágrafo da página.</p>
<p>Este é o segundo parágrafo com mais informações.</p>
<div>
<p>Parágrafo dentro de uma div.</p>
</div>
<p>Último parágrafo da página.</p>
</body>
</html>
"""
paragrafos = extrair_paragrafos(html_exemplo)
print("Parágrafos encontrados:")
for i, paragrafo in enumerate(paragrafos, 1):
print(f"{i}. {paragrafo}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 3:
def extrair_paragrafos(html):- Define função para extrair parágrafos - Linha 4:
"""Extrai o texto de todos os parágrafos de uma página HTML"""- Docstring explicando função - Linha 5:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 6:
paragrafos = soup.find_all('p')- Encontra todos os elementos de parágrafo - Linha 7:
return [paragrafo.get_text().strip() for paragrafo in paragrafos]- Retorna textos dos parágrafos - Linha 9:
# Exemplo de uso- Comentário explicativo - Linhas 10-20: Define HTML de exemplo com parágrafos
- Linha 22:
paragrafos = extrair_paragrafos(html_exemplo)- Chama função com HTML de exemplo - Linha 23:
print("Parágrafos encontrados:")- Imprime cabeçalho - Linha 24:
for i, paragrafo in enumerate(paragrafos, 1):- Percorre parágrafos com numeração - Linha 25:
print(f"{i}. {paragrafo}")- Imprime cada parágrafo numerado
5. Extrator por Classe
from bs4 import BeautifulSoup
def extrair_por_classe(html, classe):
"""Encontra elementos por classe CSS específica"""
soup = BeautifulSoup(html, 'html.parser')
elementos = soup.find_all(class_=classe)
return [elemento.get_text().strip() for elemento in elementos]
# Exemplo de uso
html_exemplo = """
<html>
<body>
<div class="produto">
<h2>Notebook</h2>
<p class="preco">R$ 2.500,00</p>
</div>
<div class="produto">
<h2>Mouse</h2>
<p class="preco">R$ 50,00</p>
</div>
<p class="preco">Preço especial: R$ 100,00</p>
</body>
</html>
"""
precos = extrair_por_classe(html_exemplo, 'preco')
print("Preços encontrados:")
for i, preco in enumerate(precos, 1):
print(f"{i}. {preco}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 3:
def extrair_por_classe(html, classe):- Define função que recebe HTML e nome da classe - Linha 4:
"""Encontra elementos por classe CSS específica"""- Docstring explicando função - Linha 5:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 6:
elementos = soup.find_all(class_=classe)- Encontra elementos com classe específica - Linha 7:
return [elemento.get_text().strip() for elemento in elementos]- Retorna textos dos elementos - Linha 9:
# Exemplo de uso- Comentário explicativo - Linhas 10-22: Define HTML de exemplo com elementos de classe ‘preco’
- Linha 24:
precos = extrair_por_classe(html_exemplo, 'preco')- Chama função para classe ‘preco’ - Linha 25:
print("Preços encontrados:")- Imprime cabeçalho - Linha 26:
for i, preco in enumerate(precos, 1):- Percorre preços com numeração - Linha 27:
print(f"{i}. {preco}")- Imprime cada preço numerado
14.7.2 FÁCIL (Nível 2)
6. Scraper de Produtos
from bs4 import BeautifulSoup
def extrair_produtos(html):
"""Extrai títulos e preços de produtos de uma loja online"""
soup = BeautifulSoup(html, 'html.parser')
produtos = []
# Encontrar todos os produtos
itens = soup.find_all('div', class_='produto')
for item in itens:
try:
nome = item.find('h3').get_text().strip()
preco = item.find('span', class_='preco').get_text().strip()
produtos.append({'nome': nome, 'preco': preco})
except AttributeError:
continue
return produtos
# Exemplo de uso
html_exemplo = """
<html>
<body>
<div class="produto">
<h3>Notebook Gamer</h3>
<span class="preco">R$ 2.500,00</span>
</div>
<div class="produto">
<h3>Mouse Óptico</h3>
<span class="preco">R$ 50,00</span>
</div>
<div class="produto">
<h3>Teclado Mecânico</h3>
<span class="preco">R$ 120,00</span>
</div>
</body>
</html>
"""
produtos = extrair_produtos(html_exemplo)
print("Produtos encontrados:")
for produto in produtos:
print(f"📦 {produto['nome']} - {produto['preco']}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 3:
def extrair_produtos(html):- Define função para extrair produtos - Linha 4:
"""Extrai títulos e preços de produtos de uma loja online"""- Docstring explicando função - Linha 5:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 6:
produtos = []- Inicializa lista para armazenar produtos - Linha 8:
# Encontrar todos os produtos- Comentário explicativo - Linha 9:
itens = soup.find_all('div', class_='produto')- Encontra todos os elementos de produto - Linha 11:
for item in itens:- Percorre cada produto encontrado - Linha 12:
try:- Inicia bloco try para tratamento de erros - Linha 13:
nome = item.find('h3').get_text().strip()- Extrai nome do produto - Linha 14:
preco = item.find('span', class_='preco').get_text().strip()- Extrai preço do produto - Linha 15:
produtos.append({'nome': nome, 'preco': preco})- Adiciona produto à lista - Linha 16:
except AttributeError:- Captura erro se elemento não for encontrado - Linha 17:
continue- Pula para próximo produto se houver erro
7. Extrator de Contato
from bs4 import BeautifulSoup
import re
def extrair_contatos(html):
"""Extrai informações de contato (email, telefone) de uma página de empresa"""
soup = BeautifulSoup(html, 'html.parser')
# Extrair emails
emails = []
email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
texto = soup.get_text()
emails = re.findall(email_pattern, texto)
# Extrair telefones
telefones = []
telefone_pattern = r'\(?\d{2}\)?[-.\s]?\d{4,5}[-.\s]?\d{4}'
telefones = re.findall(telefone_pattern, texto)
return {
'emails': list(set(emails)), # Remove duplicatas
'telefones': list(set(telefones)) # Remove duplicatas
}
# Exemplo de uso
html_exemplo = """
<html>
<body>
<h1>Contato da Empresa</h1>
<p>Email: contato@empresa.com</p>
<p>Telefone: (11) 99999-9999</p>
<p>WhatsApp: 11 88888-8888</p>
<p>Email comercial: vendas@empresa.com</p>
</body>
</html>
"""
contatos = extrair_contatos(html_exemplo)
print("Contatos encontrados:")
print(f"Emails: {contatos['emails']}")
print(f"Telefones: {contatos['telefones']}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import re- Importa módulo de expressões regulares - Linha 4:
def extrair_contatos(html):- Define função para extrair contatos - Linha 5:
"""Extrai informações de contato (email, telefone) de uma página de empresa"""- Docstring explicando função - Linha 6:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 8:
# Extrair emails- Comentário explicativo - Linha 9:
emails = []- Inicializa lista para emails - Linha 10:
email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'- Padrão regex para emails - Linha 11:
texto = soup.get_text()- Obtém todo o texto da página - Linha 12:
emails = re.findall(email_pattern, texto)- Encontra todos os emails no texto - Linha 14:
# Extrair telefones- Comentário explicativo - Linha 15:
telefones = []- Inicializa lista para telefones - Linha 16:
telefone_pattern = r'\(?\d{2}\)?[-.\s]?\d{4,5}[-.\s]?\d{4}'- Padrão regex para telefones - Linha 17:
telefones = re.findall(telefone_pattern, texto)- Encontra todos os telefones no texto
8. Coletor de Imagens
from bs4 import BeautifulSoup
def coletar_imagens(html):
"""Coleta todas as imagens e seus atributos alt"""
soup = BeautifulSoup(html, 'html.parser')
imagens = soup.find_all('img')
resultado = []
for img in imagens:
resultado.append({
'src': img.get('src', ''),
'alt': img.get('alt', ''),
'title': img.get('title', '')
})
return resultado
# Exemplo de uso
html_exemplo = """
<html>
<body>
<img src="logo.png" alt="Logo da empresa" title="Logo">
<img src="produto1.jpg" alt="Notebook Gamer">
<img src="produto2.jpg" alt="Mouse Óptico" title="Mouse">
<img src="banner.jpg" alt="">
</body>
</html>
"""
imagens = coletar_imagens(html_exemplo)
print("Imagens encontradas:")
for i, img in enumerate(imagens, 1):
print(f"{i}. SRC: {img['src']}")
print(f" ALT: {img['alt']}")
print(f" TITLE: {img['title']}")
print()Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 3:
def coletar_imagens(html):- Define função para coletar imagens - Linha 4:
"""Coleta todas as imagens e seus atributos alt"""- Docstring explicando função - Linha 5:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 6:
imagens = soup.find_all('img')- Encontra todos os elementos de imagem - Linha 8:
resultado = []- Inicializa lista para armazenar dados das imagens - Linha 9:
for img in imagens:- Percorre cada imagem encontrada - Linha 10:
resultado.append({- Adiciona dicionário com dados da imagem - Linha 11:
'src': img.get('src', ''),- Extrai atributo src (URL da imagem) - Linha 12:
'alt': img.get('alt', ''),- Extrai atributo alt (texto alternativo) - Linha 13:
'title': img.get('title', '')- Extrai atributo title (título da imagem) - Linha 14:
})- Fecha dicionário - Linha 16:
return resultado- Retorna lista com dados das imagens
9. Extrator de Tabelas
from bs4 import BeautifulSoup
import csv
def extrair_tabela_csv(html, arquivo_csv):
"""Extrai dados de uma tabela HTML e salva em formato CSV"""
soup = BeautifulSoup(html, 'html.parser')
tabela = soup.find('table')
if not tabela:
return False
# Encontrar cabeçalhos
cabecalhos = []
th_elements = tabela.find('tr').find_all('th')
for th in th_elements:
cabecalhos.append(th.get_text().strip())
# Encontrar dados
dados = []
rows = tabela.find_all('tr')[1:] # Pular primeira linha (cabeçalho)
for row in rows:
cells = row.find_all('td')
if cells: # Se a linha tem células
linha = []
for cell in cells:
linha.append(cell.get_text().strip())
dados.append(linha)
# Salvar em CSV
with open(arquivo_csv, 'w', newline='', encoding='utf-8') as arquivo:
writer = csv.writer(arquivo)
writer.writerow(cabecalhos)
writer.writerows(dados)
return True
# Exemplo de uso
html_exemplo = """
<html>
<body>
<table>
<tr>
<th>Nome</th>
<th>Idade</th>
<th>Cidade</th>
</tr>
<tr>
<td>João Silva</td>
<td>25</td>
<td>São Paulo</td>
</tr>
<tr>
<td>Maria Santos</td>
<td>30</td>
<td>Rio de Janeiro</td>
</tr>
</table>
</body>
</html>
"""
sucesso = extrair_tabela_csv(html_exemplo, 'dados.csv')
if sucesso:
print("✅ Tabela extraída e salva em dados.csv")
else:
print("❌ Erro ao extrair tabela")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import csv- Importa módulo CSV para trabalhar com arquivos CSV - Linha 4:
def extrair_tabela_csv(html, arquivo_csv):- Define função que recebe HTML e nome do arquivo - Linha 5:
"""Extrai dados de uma tabela HTML e salva em formato CSV"""- Docstring explicando função - Linha 6:
soup = BeautifulSoup(html, 'html.parser')- Cria objeto BeautifulSoup - Linha 7:
tabela = soup.find('table')- Encontra elemento de tabela - Linha 9:
if not tabela:- Verifica se tabela foi encontrada - Linha 10:
return False- Retorna False se tabela não for encontrada - Linha 12:
# Encontrar cabeçalhos- Comentário explicativo - Linha 13:
cabecalhos = []- Inicializa lista para cabeçalhos - Linha 14:
th_elements = tabela.find('tr').find_all('th')- Encontra elementos de cabeçalho - Linha 15:
for th in th_elements:- Percorre elementos de cabeçalho - Linha 16:
cabecalhos.append(th.get_text().strip())- Adiciona texto do cabeçalho à lista
10. Scraper de Notícias
from bs4 import BeautifulSoup
import requests
def coletar_manchetes(url):
"""Coleta manchetes de notícias de um site"""
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Encontrar manchetes (ajuste os seletores conforme o site)
manchetes = soup.find_all('h2') # ou 'h1', 'h3', etc.
resultado = []
for manchete in manchetes:
texto = manchete.get_text().strip()
if texto: # Se não estiver vazio
resultado.append(texto)
return resultado
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar o site: {e}")
return None
# Exemplo de uso (com HTML simulado)
html_exemplo = """
<html>
<body>
<h1>Portal de Notícias</h1>
<h2>Manchete 1: Novidades em Tecnologia</h2>
<h2>Manchete 2: Economia em Destaque</h2>
<h2>Manchete 3: Esportes do Dia</h2>
<p>Parágrafo normal</p>
<h2>Manchete 4: Política Nacional</h2>
</body>
</html>
"""
# Simular resposta de site
soup = BeautifulSoup(html_exemplo, 'html.parser')
manchetes = soup.find_all('h2')
print("Manchetes encontradas:")
for i, manchete in enumerate(manchetes, 1):
print(f"{i}. {manchete.get_text().strip()}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para fazer requisições HTTP - Linha 4:
def coletar_manchetes(url):- Define função que recebe URL do site - Linha 5:
"""Coleta manchetes de notícias de um site"""- Docstring explicando função - Linha 6:
try:- Inicia bloco try para tratamento de erros - Linha 7:
response = requests.get(url)- Faz requisição HTTP para o site - Linha 8:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 10:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup com conteúdo da página - Linha 12:
# Encontrar manchetes (ajuste os seletores conforme o site)- Comentário explicativo - Linha 13:
manchetes = soup.find_all('h2')- Encontra todos os elementos H2 (manchetes) - Linha 15:
resultado = []- Inicializa lista para armazenar manchetes - Linha 16:
for manchete in manchetes:- Percorre cada manchete encontrada - Linha 17:
texto = manchete.get_text().strip()- Extrai texto da manchete - Linha 18:
if texto:- Verifica se texto não está vazio - Linha 19:
resultado.append(texto)- Adiciona manchete à lista
14.7.3 MÉDIO (Nível 3)
11. Monitor de Preços
from bs4 import BeautifulSoup
import requests
import time
import json
def monitorar_precos(urls_produtos):
"""Monitora preços de produtos em múltiplos sites"""
resultados = []
for url in urls_produtos:
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Extrair informações do produto (ajuste seletores conforme site)
nome = soup.find('h1').get_text().strip()
preco = soup.find('span', class_='preco').get_text().strip()
resultados.append({
'url': url,
'nome': nome,
'preco': preco,
'data': time.strftime('%Y-%m-%d %H:%M:%S')
})
# Delay entre requisições
time.sleep(2)
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar {url}: {e}")
continue
return resultados
# Exemplo de uso
urls_exemplo = [
'https://loja1.com/produto1',
'https://loja2.com/produto1',
'https://loja3.com/produto1'
]
# Simular HTML de produtos
html_produto1 = """
<html>
<body>
<h1>Notebook Gamer XYZ</h1>
<span class="preco">R$ 2.500,00</span>
</body>
</html>
"""
html_produto2 = """
<html>
<body>
<h1>Notebook Gamer XYZ</h1>
<span class="preco">R$ 2.300,00</span>
</body>
</html>
"""
# Simular monitoramento
produtos = [
{'url': 'loja1.com', 'nome': 'Notebook Gamer XYZ', 'preco': 'R$ 2.500,00'},
{'url': 'loja2.com', 'nome': 'Notebook Gamer XYZ', 'preco': 'R$ 2.300,00'},
{'url': 'loja3.com', 'nome': 'Notebook Gamer XYZ', 'preco': 'R$ 2.400,00'}
]
print("Comparação de preços:")
for produto in produtos:
print(f"🏪 {produto['url']}: {produto['preco']}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays e timestamps - Linha 4:
import json- Importa json para trabalhar com dados JSON - Linha 6:
def monitorar_precos(urls_produtos):- Define função que recebe lista de URLs - Linha 7:
"""Monitora preços de produtos em múltiplos sites"""- Docstring explicando função - Linha 8:
resultados = []- Inicializa lista para armazenar resultados - Linha 10:
for url in urls_produtos:- Percorre cada URL de produto - Linha 11:
try:- Inicia bloco try para tratamento de erros - Linha 12:
response = requests.get(url)- Faz requisição HTTP para o site - Linha 13:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 15:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 17:
# Extrair informações do produto (ajuste seletores conforme site)- Comentário explicativo - Linha 18:
nome = soup.find('h1').get_text().strip()- Extrai nome do produto - Linha 19:
preco = soup.find('span', class_='preco').get_text().strip()- Extrai preço do produto
12. Extrator de Perfis
from bs4 import BeautifulSoup
import requests
def extrair_perfil_usuario(url_perfil):
"""Extrai informações de perfil de usuário de uma rede social"""
try:
response = requests.get(url_perfil)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Extrair informações do perfil (ajuste seletores conforme site)
nome = soup.find('h1', class_='nome-usuario').get_text().strip()
seguidores = soup.find('span', class_='seguidores').get_text().strip()
seguindo = soup.find('span', class_='seguindo').get_text().strip()
posts = soup.find('span', class_='posts').get_text().strip()
perfil = {
'nome': nome,
'seguidores': seguidores,
'seguindo': seguindo,
'posts': posts,
'url': url_perfil
}
return perfil
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar perfil: {e}")
return None
# Exemplo de uso
html_perfil = """
<html>
<body>
<div class="perfil">
<h1 class="nome-usuario">João Silva</h1>
<div class="stats">
<span class="posts">150</span>
<span class="seguidores">1.250</span>
<span class="seguindo">300</span>
</div>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_perfil, 'html.parser')
nome = soup.find('h1', class_='nome-usuario').get_text().strip()
seguidores = soup.find('span', class_='seguidores').get_text().strip()
print(f"👤 Nome: {nome}")
print(f"👥 Seguidores: {seguidores}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 4:
def extrair_perfil_usuario(url_perfil):- Define função que recebe URL do perfil - Linha 5:
"""Extrai informações de perfil de usuário de uma rede social"""- Docstring explicando função - Linha 6:
try:- Inicia bloco try para tratamento de erros - Linha 7:
response = requests.get(url_perfil)- Faz requisição HTTP para o perfil - Linha 8:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 10:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 12:
# Extrair informações do perfil (ajuste seletores conforme site)- Comentário explicativo - Linha 13:
nome = soup.find('h1', class_='nome-usuario').get_text().strip()- Extrai nome do usuário - Linha 14:
seguidores = soup.find('span', class_='seguidores').get_text().strip()- Extrai número de seguidores - Linha 15:
seguindo = soup.find('span', class_='seguindo').get_text().strip()- Extrai número de seguindo - Linha 16:
posts = soup.find('span', class_='posts').get_text().strip()- Extrai número de posts
13. Scraper de Imóveis
from bs4 import BeautifulSoup
import requests
import re
def extrair_imoveis(url_site):
"""Extrai dados de imóveis (preço, localização, características)"""
try:
response = requests.get(url_site)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Encontrar todos os imóveis
imoveis = soup.find_all('div', class_='imovel')
resultado = []
for imovel in imoveis:
try:
preco = imovel.find('span', class_='preco').get_text().strip()
localizacao = imovel.find('span', class_='localizacao').get_text().strip()
quartos = imovel.find('span', class_='quartos').get_text().strip()
banheiros = imovel.find('span', class_='banheiros').get_text().strip()
resultado.append({
'preco': preco,
'localizacao': localizacao,
'quartos': quartos,
'banheiros': banheiros
})
except AttributeError:
continue
return resultado
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar site: {e}")
return None
# Exemplo de uso
html_imoveis = """
<html>
<body>
<div class="imovel">
<span class="preco">R$ 500.000</span>
<span class="localizacao">São Paulo, SP</span>
<span class="quartos">3 quartos</span>
<span class="banheiros">2 banheiros</span>
</div>
<div class="imovel">
<span class="preco">R$ 750.000</span>
<span class="localizacao">Rio de Janeiro, RJ</span>
<span class="quartos">4 quartos</span>
<span class="banheiros">3 banheiros</span>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_imoveis, 'html.parser')
imoveis = soup.find_all('div', class_='imovel')
print("Imóveis encontrados:")
for i, imovel in enumerate(imoveis, 1):
preco = imovel.find('span', class_='preco').get_text().strip()
localizacao = imovel.find('span', class_='localizacao').get_text().strip()
print(f"{i}. {preco} - {localizacao}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import re- Importa módulo de expressões regulares - Linha 5:
def extrair_imoveis(url_site):- Define função que recebe URL do site de imóveis - Linha 6:
"""Extrai dados de imóveis (preço, localização, características)"""- Docstring explicando função - Linha 7:
try:- Inicia bloco try para tratamento de erros - Linha 8:
response = requests.get(url_site)- Faz requisição HTTP para o site - Linha 9:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 11:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 13:
# Encontrar todos os imóveis- Comentário explicativo - Linha 14:
imoveis = soup.find_all('div', class_='imovel')- Encontra todos os elementos de imóvel - Linha 16:
resultado = []- Inicializa lista para armazenar dados dos imóveis - Linha 17:
for imovel in imoveis:- Percorre cada imóvel encontrado - Linha 18:
try:- Inicia bloco try para tratamento de erros - Linha 19:
preco = imovel.find('span', class_='preco').get_text().strip()- Extrai preço do imóvel - Linha 20:
localizacao = imovel.find('span', class_='localizacao').get_text().strip()- Extrai localização do imóvel
14. Extrator de Filmes
from bs4 import BeautifulSoup
import requests
def extrair_filmes(url_site):
"""Extrai dados de filmes/séries de um site de streaming"""
try:
response = requests.get(url_site)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Encontrar todos os filmes/séries
conteudos = soup.find_all('div', class_='conteudo')
resultado = []
for conteudo in conteudos:
try:
titulo = conteudo.find('h3', class_='titulo').get_text().strip()
genero = conteudo.find('span', class_='genero').get_text().strip()
ano = conteudo.find('span', class_='ano').get_text().strip()
avaliacao = conteudo.find('span', class_='avaliacao').get_text().strip()
resultado.append({
'titulo': titulo,
'genero': genero,
'ano': ano,
'avaliacao': avaliacao
})
except AttributeError:
continue
return resultado
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar site: {e}")
return None
# Exemplo de uso
html_filmes = """
<html>
<body>
<div class="conteudo">
<h3 class="titulo">Vingadores: Ultimato</h3>
<span class="genero">Ação</span>
<span class="ano">2019</span>
<span class="avaliacao">8.4/10</span>
</div>
<div class="conteudo">
<h3 class="titulo">Stranger Things</h3>
<span class="genero">Drama</span>
<span class="ano">2016</span>
<span class="avaliacao">8.7/10</span>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_filmes, 'html.parser')
conteudos = soup.find_all('div', class_='conteudo')
print("Filmes/Séries encontrados:")
for i, conteudo in enumerate(conteudos, 1):
titulo = conteudo.find('h3', class_='titulo').get_text().strip()
genero = conteudo.find('span', class_='genero').get_text().strip()
print(f"{i}. {titulo} ({genero})")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 4:
def extrair_filmes(url_site):- Define função que recebe URL do site de streaming - Linha 5:
"""Extrai dados de filmes/séries de um site de streaming"""- Docstring explicando função - Linha 6:
try:- Inicia bloco try para tratamento de erros - Linha 7:
response = requests.get(url_site)- Faz requisição HTTP para o site - Linha 8:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 10:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 12:
# Encontrar todos os filmes/séries- Comentário explicativo - Linha 13:
conteudos = soup.find_all('div', class_='conteudo')- Encontra todos os elementos de conteúdo - Linha 15:
resultado = []- Inicializa lista para armazenar dados dos filmes - Linha 16:
for conteudo in conteudos:- Percorre cada conteúdo encontrado - Linha 17:
try:- Inicia bloco try para tratamento de erros - Linha 18:
titulo = conteudo.find('h3', class_='titulo').get_text().strip()- Extrai título do filme - Linha 19:
genero = conteudo.find('span', class_='genero').get_text().strip()- Extrai gênero do filme
15. Scraper de Vagas
from bs4 import BeautifulSoup
import requests
def extrair_vagas(url_site):
"""Extrai informações de vagas de emprego"""
try:
response = requests.get(url_site)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Encontrar todas as vagas
vagas = soup.find_all('div', class_='vaga')
resultado = []
for vaga in vagas:
try:
cargo = vaga.find('h3', class_='cargo').get_text().strip()
empresa = vaga.find('span', class_='empresa').get_text().strip()
salario = vaga.find('span', class_='salario').get_text().strip()
localizacao = vaga.find('span', class_='localizacao').get_text().strip()
resultado.append({
'cargo': cargo,
'empresa': empresa,
'salario': salario,
'localizacao': localizacao
})
except AttributeError:
continue
return resultado
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar site: {e}")
return None
# Exemplo de uso
html_vagas = """
<html>
<body>
<div class="vaga">
<h3 class="cargo">Desenvolvedor Python</h3>
<span class="empresa">Tech Corp</span>
<span class="salario">R$ 8.000 - R$ 12.000</span>
<span class="localizacao">São Paulo, SP</span>
</div>
<div class="vaga">
<h3 class="cargo">Analista de Dados</h3>
<span class="empresa">Data Solutions</span>
<span class="salario">R$ 6.000 - R$ 9.000</span>
<span class="localizacao">Rio de Janeiro, RJ</span>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_vagas, 'html.parser')
vagas = soup.find_all('div', class_='vaga')
print("Vagas encontradas:")
for i, vaga in enumerate(vagas, 1):
cargo = vaga.find('h3', class_='cargo').get_text().strip()
empresa = vaga.find('span', class_='empresa').get_text().strip()
print(f"{i}. {cargo} - {empresa}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 4:
def extrair_vagas(url_site):- Define função que recebe URL do site de vagas - Linha 5:
"""Extrai informações de vagas de emprego"""- Docstring explicando função - Linha 6:
try:- Inicia bloco try para tratamento de erros - Linha 7:
response = requests.get(url_site)- Faz requisição HTTP para o site - Linha 8:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 10:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 12:
# Encontrar todas as vagas- Comentário explicativo - Linha 13:
vagas = soup.find_all('div', class_='vaga')- Encontra todos os elementos de vaga - Linha 15:
resultado = []- Inicializa lista para armazenar dados das vagas - Linha 16:
for vaga in vagas:- Percorre cada vaga encontrada - Linha 17:
try:- Inicia bloco try para tratamento de erros - Linha 18:
cargo = vaga.find('h3', class_='cargo').get_text().strip()- Extrai cargo da vaga - Linha 19:
empresa = vaga.find('span', class_='empresa').get_text().strip()- Extrai empresa da vaga - Linha 20:
salario = vaga.find('span', class_='salario').get_text().strip()- Extrai salário da vaga - Linha 21:
localizacao = vaga.find('span', class_='localizacao').get_text().strip()- Extrai localização da vaga
14.7.4 DIFÍCIL (Nível 4)
16. Scraper com Paginação
from bs4 import BeautifulSoup
import requests
import time
def scraper_com_paginacao(url_base, max_paginas=5):
"""Scraper que navega por múltiplas páginas (paginação)"""
todos_dados = []
for pagina in range(1, max_paginas + 1):
try:
# Construir URL da página
if '?' in url_base:
url_pagina = f"{url_base}&page={pagina}"
else:
url_pagina = f"{url_base}?page={pagina}"
print(f"📄 Acessando página {pagina}...")
response = requests.get(url_pagina)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Extrair dados da página atual
itens = soup.find_all('div', class_='item')
if not itens: # Se não há itens, parar
print(f"⏹️ Nenhum item encontrado na página {pagina}. Parando.")
break
for item in itens:
try:
titulo = item.find('h3').get_text().strip()
preco = item.find('span', class_='preco').get_text().strip()
todos_dados.append({
'pagina': pagina,
'titulo': titulo,
'preco': preco
})
except AttributeError:
continue
# Delay entre páginas
time.sleep(2)
except requests.exceptions.RequestException as e:
print(f"❌ Erro na página {pagina}: {e}")
continue
return todos_dados
# Exemplo de uso
url_base = "https://exemplo.com/produtos"
# Simular dados de múltiplas páginas
dados_simulados = [
{'pagina': 1, 'titulo': 'Produto A', 'preco': 'R$ 100'},
{'pagina': 1, 'titulo': 'Produto B', 'preco': 'R$ 200'},
{'pagina': 2, 'titulo': 'Produto C', 'preco': 'R$ 300'},
{'pagina': 2, 'titulo': 'Produto D', 'preco': 'R$ 400'},
]
print("Dados coletados de múltiplas páginas:")
for dados in dados_simulados:
print(f"Página {dados['pagina']}: {dados['titulo']} - {dados['preco']}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays - Linha 5:
def scraper_com_paginacao(url_base, max_paginas=5):- Define função com URL base e número máximo de páginas - Linha 6:
"""Scraper que navega por múltiplas páginas (paginação)"""- Docstring explicando função - Linha 7:
todos_dados = []- Inicializa lista para armazenar todos os dados - Linha 9:
for pagina in range(1, max_paginas + 1):- Percorre páginas de 1 até max_paginas - Linha 10:
try:- Inicia bloco try para tratamento de erros - Linha 12:
# Construir URL da página- Comentário explicativo - Linha 13:
if '?' in url_base:- Verifica se URL já tem parâmetros - Linha 14:
url_pagina = f"{url_base}&page={pagina}"- Adiciona parâmetro page com & - Linha 15:
else:- Se não tem parâmetros - Linha 16:
url_pagina = f"{url_base}?page={pagina}"- Adiciona parâmetro page com ? - Linha 18:
print(f"📄 Acessando página {pagina}...")- Mostra progresso - Linha 20:
response = requests.get(url_pagina)- Faz requisição para a página - Linha 21:
response.raise_for_status()- Verifica se requisição foi bem-sucedida
17. Extrator de Gráficos
from bs4 import BeautifulSoup
import requests
import re
import json
def extrair_dados_graficos(url):
"""Extrai dados de gráficos e visualizações de dados de sites"""
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Procurar por dados em JavaScript (comum em gráficos)
scripts = soup.find_all('script')
dados_graficos = []
for script in scripts:
if script.string:
# Procurar por padrões de dados JSON
json_pattern = r'data:\s*(\[.*?\])'
matches = re.findall(json_pattern, script.string)
for match in matches:
try:
dados = json.loads(match)
dados_graficos.extend(dados)
except json.JSONDecodeError:
continue
# Procurar por elementos com classes relacionadas a gráficos
elementos_grafico = soup.find_all(['div', 'span'], class_=re.compile(r'chart|graph|data'))
for elemento in elementos_grafico:
texto = elemento.get_text().strip()
if texto and re.match(r'^\d+$', texto): # Se é um número
dados_graficos.append(int(texto))
return dados_graficos
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar site: {e}")
return None
# Exemplo de uso
html_grafico = """
<html>
<body>
<script>
var chartData = {
data: [10, 20, 30, 40, 50]
};
</script>
<div class="chart-container">
<span class="data-point">15</span>
<span class="data-point">25</span>
<span class="data-point">35</span>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_grafico, 'html.parser')
scripts = soup.find_all('script')
print("Dados de gráficos encontrados:")
for script in scripts:
if script.string and 'data:' in script.string:
print(f"Script encontrado: {script.string[:50]}...")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import re- Importa módulo de expressões regulares - Linha 4:
import json- Importa módulo json para trabalhar com dados JSON - Linha 6:
def extrair_dados_graficos(url):- Define função que recebe URL do site - Linha 7:
"""Extrai dados de gráficos e visualizações de dados de sites"""- Docstring explicando função - Linha 8:
try:- Inicia bloco try para tratamento de erros - Linha 9:
response = requests.get(url)- Faz requisição HTTP para o site - Linha 10:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 12:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 14:
# Procurar por dados em JavaScript (comum em gráficos)- Comentário explicativo - Linha 15:
scripts = soup.find_all('script')- Encontra todos os elementos script - Linha 17:
dados_graficos = []- Inicializa lista para armazenar dados dos gráficos - Linha 19:
for script in scripts:- Percorre cada script encontrado - Linha 20:
if script.string:- Verifica se script tem conteúdo - Linha 22:
# Procurar por padrões de dados JSON- Comentário explicativo - Linha 23:
json_pattern = r'data:\s*(\[.*?\])'- Padrão regex para encontrar dados JSON
18. Monitor de Mudanças
from bs4 import BeautifulSoup
import requests
import time
import hashlib
def monitorar_mudancas(url, intervalo=60):
"""Monitora mudanças em páginas web ao longo do tempo"""
hash_anterior = None
contador_mudancas = 0
print(f"🔍 Iniciando monitoramento de {url}")
print(f"⏰ Intervalo: {intervalo} segundos")
while True:
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Remover elementos que mudam frequentemente (timestamps, etc.)
for elemento in soup.find_all(['script', 'style']):
elemento.decompose()
# Calcular hash do conteúdo
conteudo = soup.get_text()
hash_atual = hashlib.md5(conteudo.encode()).hexdigest()
if hash_anterior is None:
print("📝 Hash inicial calculado")
hash_anterior = hash_atual
elif hash_atual != hash_anterior:
contador_mudancas += 1
timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
print(f"🔄 MUDANÇA DETECTADA #{contador_mudancas} em {timestamp}")
print(f" Hash anterior: {hash_anterior[:10]}...")
print(f" Hash atual: {hash_atual[:10]}...")
hash_anterior = hash_atual
else:
print("✅ Nenhuma mudança detectada")
time.sleep(intervalo)
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar site: {e}")
time.sleep(intervalo)
continue
except KeyboardInterrupt:
print("\n⏹️ Monitoramento interrompido pelo usuário")
break
# Exemplo de uso (simulado)
def simular_monitoramento():
"""Simula monitoramento de mudanças"""
print("🔍 Simulando monitoramento de mudanças...")
# Simular diferentes estados da página
estados = [
"Conteúdo original",
"Conteúdo modificado",
"Conteúdo modificado novamente"
]
for i, estado in enumerate(estados):
print(f"📄 Estado {i+1}: {estado}")
time.sleep(1)
simular_monitoramento()Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays e timestamps - Linha 4:
import hashlib- Importa hashlib para calcular hashes - Linha 6:
def monitorar_mudancas(url, intervalo=60):- Define função com URL e intervalo de monitoramento - Linha 7:
"""Monitora mudanças em páginas web ao longo do tempo"""- Docstring explicando função - Linha 8:
hash_anterior = None- Inicializa variável para hash anterior - Linha 9:
contador_mudancas = 0- Inicializa contador de mudanças - Linha 11:
print(f"🔍 Iniciando monitoramento de {url}")- Mostra início do monitoramento - Linha 12:
print(f"⏰ Intervalo: {intervalo} segundos")- Mostra intervalo de monitoramento - Linha 14:
while True:- Loop infinito para monitoramento contínuo - Linha 15:
try:- Inicia bloco try para tratamento de erros - Linha 16:
response = requests.get(url)- Faz requisição HTTP para o site - Linha 17:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 19:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 21:
# Remover elementos que mudam frequentemente (timestamps, etc.)- Comentário explicativo - Linha 22:
for elemento in soup.find_all(['script', 'style']):- Percorre elementos que mudam frequentemente - Linha 23:
elemento.decompose()- Remove elemento da árvore HTML
19. Extrator de APIs JavaScript
from bs4 import BeautifulSoup
import requests
import re
import json
def extrair_apis_javascript(url):
"""Extrai dados de APIs que são carregadas via JavaScript"""
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Procurar por URLs de APIs em scripts
scripts = soup.find_all('script')
apis_encontradas = []
for script in scripts:
if script.string:
# Procurar por padrões de URLs de API
api_patterns = [
r'fetch\(["\']([^"\']+)["\']',
r'axios\.get\(["\']([^"\']+)["\']',
r'\.get\(["\']([^"\']+)["\']',
r'api_url["\']?\s*[:=]\s*["\']([^"\']+)["\']'
]
for pattern in api_patterns:
matches = re.findall(pattern, script.string)
apis_encontradas.extend(matches)
# Procurar por elementos com data-attributes relacionados a APIs
elementos_api = soup.find_all(attrs={'data-api': True})
for elemento in elementos_api:
api_url = elemento.get('data-api')
if api_url:
apis_encontradas.append(api_url)
# Remover duplicatas
apis_unicas = list(set(apis_encontradas))
return apis_unicas
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar site: {e}")
return None
# Exemplo de uso
html_js_api = """
<html>
<body>
<script>
fetch('/api/produtos')
.then(response => response.json())
.then(data => console.log(data));
var api_url = 'https://api.exemplo.com/dados';
axios.get(api_url);
</script>
<div data-api="/api/usuarios">Carregar usuários</div>
</body>
</html>
"""
soup = BeautifulSoup(html_js_api, 'html.parser')
scripts = soup.find_all('script')
print("APIs JavaScript encontradas:")
for script in scripts:
if script.string:
if 'fetch(' in script.string or 'axios' in script.string:
print(f"Script com API: {script.string[:100]}...")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import re- Importa módulo de expressões regulares - Linha 4:
import json- Importa módulo json para trabalhar com dados JSON - Linha 6:
def extrair_apis_javascript(url):- Define função que recebe URL do site - Linha 7:
"""Extrai dados de APIs que são carregadas via JavaScript"""- Docstring explicando função - Linha 8:
try:- Inicia bloco try para tratamento de erros - Linha 9:
response = requests.get(url)- Faz requisição HTTP para o site - Linha 10:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 12:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 14:
# Procurar por URLs de APIs em scripts- Comentário explicativo - Linha 15:
scripts = soup.find_all('script')- Encontra todos os elementos script - Linha 16:
apis_encontradas = []- Inicializa lista para armazenar APIs encontradas - Linha 18:
for script in scripts:- Percorre cada script encontrado - Linha 19:
if script.string:- Verifica se script tem conteúdo - Linha 21:
# Procurar por padrões de URLs de API- Comentário explicativo - Linha 22:
api_patterns = [- Inicia lista de padrões regex para encontrar APIs - Linha 23:
r'fetch\(["\']([^"\']+)["\']',- Padrão para fetch() - Linha 24:
r'axios\.get\(["\']([^"\']+)["\']',- Padrão para axios.get() - Linha 25:
r'\.get\(["\']([^"\']+)["\']',- Padrão genérico para .get() - Linha 26:
r'api_url["\']?\s*[:=]\s*["\']([^"\']+)["\']'- Padrão para variáveis de API
20. Scraper Anti-Bloqueio
from bs4 import BeautifulSoup
import requests
import time
import random
from urllib.parse import urljoin
def scraping_anti_bloqueio(url):
"""Scraper que contorna proteções básicas contra scraping"""
# Headers para simular navegador real
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'pt-BR,pt;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
try:
# Delay aleatório entre 1-3 segundos
time.sleep(random.uniform(1, 3))
# Fazer requisição com headers
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Verificar se página foi bloqueada
if soup.find(text=re.compile(r'blocked|access denied|captcha', re.I)):
print("🚫 Página bloqueada detectada")
return None
# Extrair dados
dados = []
elementos = soup.find_all('div', class_='item')
for elemento in elementos:
try:
titulo = elemento.find('h3').get_text().strip()
preco = elemento.find('span', class_='preco').get_text().strip()
dados.append({
'titulo': titulo,
'preco': preco
})
except AttributeError:
continue
return dados
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar site: {e}")
return None
# Exemplo de uso
def simular_scraping_anti_bloqueio():
"""Simula scraping anti-bloqueio"""
print("🛡️ Simulando scraping anti-bloqueio...")
# Simular headers
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
print(f"📡 Headers configurados: {len(headers)} headers")
print("⏰ Delay aleatório aplicado")
print("🔍 Dados extraídos com sucesso")
simular_scraping_anti_bloqueio()Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays - Linha 4:
import random- Importa random para delays aleatórios - Linha 5:
from urllib.parse import urljoin- Importa urljoin para construir URLs - Linha 7:
def scraping_anti_bloqueio(url):- Define função que recebe URL do site - Linha 8:
"""Scraper que contorna proteções básicas contra scraping"""- Docstring explicando função - Linha 10:
# Headers para simular navegador real- Comentário explicativo - Linha 11:
headers = {- Inicia dicionário com headers de navegador - Linha 12:
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',- User-Agent de navegador real - Linha 13:
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',- Headers de aceitação - Linha 14:
'Accept-Language': 'pt-BR,pt;q=0.9,en;q=0.8',- Idioma preferido - Linha 15:
'Accept-Encoding': 'gzip, deflate, br',- Codificação aceita - Linha 16:
'DNT': '1',- Do Not Track - Linha 17:
'Connection': 'keep-alive',- Conexão persistente - Linha 18:
'Upgrade-Insecure-Requests': '1',- Upgrade para HTTPS - Linha 19:
}- Fecha dicionário de headers - Linha 21:
try:- Inicia bloco try para tratamento de erros - Linha 23:
# Delay aleatório entre 1-3 segundos- Comentário explicativo - Linha 24:
time.sleep(random.uniform(1, 3))- Delay aleatório para evitar detecção - Linha 26:
# Fazer requisição com headers- Comentário explicativo - Linha 27:
response = requests.get(url, headers=headers, timeout=10)- Faz requisição com headers e timeout
14.7.5 MUITO DIFÍCIL (Nível 5)
21. Sistema de Monitoramento
from bs4 import BeautifulSoup
import requests
import time
import json
import smtplib
from email.mime.text import MIMEText
class SistemaMonitoramento:
def __init__(self, produtos_monitorados):
self.produtos = produtos_monitorados
self.historico_precos = {}
def monitorar_precos(self):
"""Monitora preços e envia alertas"""
for produto in self.produtos:
try:
preco_atual = self.extrair_preco(produto['url'])
if preco_atual:
# Verificar se preço mudou
if produto['nome'] in self.historico_precos:
preco_anterior = self.historico_precos[produto['nome']]
if preco_atual < preco_anterior:
self.enviar_alerta(produto, preco_anterior, preco_atual)
self.historico_precos[produto['nome']] = preco_atual
time.sleep(2) # Delay entre requisições
except Exception as e:
print(f"❌ Erro ao monitorar {produto['nome']}: {e}")
def extrair_preco(self, url):
"""Extrai preço de um produto"""
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
preco_element = soup.find('span', class_='preco')
if preco_element:
preco_texto = preco_element.get_text().strip()
# Extrair apenas números do preço
preco_numerico = float(re.sub(r'[^\d,.]', '', preco_texto).replace(',', '.'))
return preco_numerico
return None
except Exception as e:
print(f"❌ Erro ao extrair preço: {e}")
return None
def enviar_alerta(self, produto, preco_anterior, preco_atual):
"""Envia alerta de queda de preço"""
mensagem = f"""
🎉 ALERTA DE PREÇO!
Produto: {produto['nome']}
Preço anterior: R$ {preco_anterior:.2f}
Preço atual: R$ {preco_atual:.2f}
Economia: R$ {preco_anterior - preco_atual:.2f}
Link: {produto['url']}
"""
print(f"📧 Alerta enviado: {produto['nome']} - R$ {preco_atual:.2f}")
# Exemplo de uso
produtos = [
{'nome': 'Notebook Gamer', 'url': 'https://loja.com/notebook'},
{'nome': 'Mouse Óptico', 'url': 'https://loja.com/mouse'}
]
sistema = SistemaMonitoramento(produtos)
print("🔍 Sistema de monitoramento iniciado")
print("📊 Monitorando preços...")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays - Linha 4:
import json- Importa json para trabalhar com dados JSON - Linha 5:
import smtplib- Importa smtplib para envio de emails - Linha 6:
from email.mime.text import MIMEText- Importa MIMEText para emails - Linha 8:
class SistemaMonitoramento:- Define classe para sistema de monitoramento - Linha 9:
def __init__(self, produtos_monitorados):- Construtor da classe - Linha 10:
self.produtos = produtos_monitorados- Armazena produtos para monitorar - Linha 11:
self.historico_precos = {}- Inicializa dicionário para histórico de preços - Linha 13:
def monitorar_precos(self):- Define método para monitorar preços - Linha 14:
"""Monitora preços e envia alertas"""- Docstring explicando método - Linha 15:
for produto in self.produtos:- Percorre cada produto para monitorar - Linha 16:
try:- Inicia bloco try para tratamento de erros - Linha 17:
preco_atual = self.extrair_preco(produto['url'])- Extrai preço atual do produto - Linha 19:
if preco_atual:- Verifica se preço foi extraído com sucesso - Linha 21:
# Verificar se preço mudou- Comentário explicativo - Linha 22:
if produto['nome'] in self.historico_precos:- Verifica se produto já foi monitorado antes - Linha 23:
preco_anterior = self.historico_precos[produto['nome']]- Obtém preço anterior - Linha 25:
if preco_atual < preco_anterior:- Verifica se preço diminuiu - Linha 26:
self.enviar_alerta(produto, preco_anterior, preco_atual)- Envia alerta de queda de preço
22. Scraper com Autenticação
from bs4 import BeautifulSoup
import requests
import time
class ScraperAutenticado:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
self.logado = False
def fazer_login(self, username, password):
"""Faz login no site"""
try:
# Página de login
login_url = f"{self.base_url}/login"
response = self.session.get(login_url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Encontrar token CSRF
csrf_token = soup.find('input', {'name': 'csrf_token'})
if csrf_token:
csrf_value = csrf_token.get('value')
else:
csrf_value = None
# Dados do login
login_data = {
'username': username,
'password': password,
'csrf_token': csrf_value
}
# Fazer login
response = self.session.post(login_url, data=login_data)
response.raise_for_status()
# Verificar se login foi bem-sucedido
if 'dashboard' in response.url or 'welcome' in response.text.lower():
self.logado = True
print("✅ Login realizado com sucesso!")
return True
else:
print("❌ Falha no login")
return False
except Exception as e:
print(f"❌ Erro no login: {e}")
return False
def extrair_dados_protegidos(self, url):
"""Extrai dados de páginas protegidas"""
if not self.logado:
print("❌ É necessário fazer login primeiro")
return None
try:
response = self.session.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Extrair dados da página protegida
dados = []
elementos = soup.find_all('div', class_='dados-protegidos')
for elemento in elementos:
try:
titulo = elemento.find('h3').get_text().strip()
conteudo = elemento.find('p').get_text().strip()
dados.append({
'titulo': titulo,
'conteudo': conteudo
})
except AttributeError:
continue
return dados
except Exception as e:
print(f"❌ Erro ao extrair dados: {e}")
return None
# Exemplo de uso
scraper = ScraperAutenticado('https://site-exemplo.com')
# Simular login
print("🔐 Simulando login...")
print("✅ Login simulado com sucesso!")
# Simular extração de dados
print("🔍 Extraindo dados protegidos...")
dados_simulados = [
{'titulo': 'Dados Pessoais', 'conteudo': 'Informações confidenciais'},
{'titulo': 'Histórico', 'conteudo': 'Dados históricos'}
]
for dados in dados_simulados:
print(f"📄 {dados['titulo']}: {dados['conteudo']}")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays - Linha 5:
class ScraperAutenticado:- Define classe para scraper com autenticação - Linha 6:
def __init__(self, base_url):- Construtor da classe - Linha 7:
self.base_url = base_url- Armazena URL base do site - Linha 8:
self.session = requests.Session()- Cria sessão para manter cookies - Linha 9:
self.logado = False- Inicializa flag de login - Linha 11:
def fazer_login(self, username, password):- Define método para fazer login - Linha 12:
"""Faz login no site"""- Docstring explicando método - Linha 13:
try:- Inicia bloco try para tratamento de erros - Linha 15:
# Página de login- Comentário explicativo - Linha 16:
login_url = f"{self.base_url}/login"- Constrói URL de login - Linha 17:
response = self.session.get(login_url)- Faz requisição para página de login - Linha 18:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 20:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 22:
# Encontrar token CSRF- Comentário explicativo - Linha 23:
csrf_token = soup.find('input', {'name': 'csrf_token'})- Procura token CSRF - Linha 24:
if csrf_token:- Verifica se token foi encontrado - Linha 25:
csrf_value = csrf_token.get('value')- Obtém valor do token - Linha 26:
else:- Se token não foi encontrado - Linha 27:
csrf_value = None- Define token como None
23. Scraper Distribuído
import multiprocessing
from bs4 import BeautifulSoup
import requests
import time
import json
def processar_url(url_data):
"""Processa uma URL em um processo separado"""
url = url_data['url']
processo_id = url_data['processo_id']
try:
print(f"🔄 Processo {processo_id}: Processando {url}")
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Extrair dados
dados = []
elementos = soup.find_all('div', class_='item')
for elemento in elementos:
try:
titulo = elemento.find('h3').get_text().strip()
preco = elemento.find('span', class_='preco').get_text().strip()
dados.append({
'url': url,
'titulo': titulo,
'preco': preco,
'processo': processo_id
})
except AttributeError:
continue
print(f"✅ Processo {processo_id}: {len(dados)} itens extraídos")
return dados
except Exception as e:
print(f"❌ Processo {processo_id}: Erro ao processar {url}: {e}")
return []
class ScraperDistribuido:
def __init__(self, num_processos=4):
self.num_processos = num_processos
def processar_urls(self, urls):
"""Processa múltiplas URLs em paralelo"""
print(f"🚀 Iniciando scraping distribuído com {self.num_processos} processos")
# Preparar dados para cada processo
dados_processos = []
for i, url in enumerate(urls):
dados_processos.append({
'url': url,
'processo_id': i + 1
})
# Executar em paralelo
with multiprocessing.Pool(self.num_processos) as pool:
resultados = pool.map(processar_url, dados_processos)
# Consolidar resultados
todos_dados = []
for resultado in resultados:
todos_dados.extend(resultado)
print(f"📊 Total de dados extraídos: {len(todos_dados)}")
return todos_dados
# Exemplo de uso
urls = [
'https://site1.com/produtos',
'https://site2.com/produtos',
'https://site3.com/produtos',
'https://site4.com/produtos'
]
scraper = ScraperDistribuido(num_processos=2)
# Simular scraping distribuído
print("🔄 Simulando scraping distribuído...")
for i, url in enumerate(urls):
print(f"Processo {i+1}: Processando {url}")
time.sleep(0.5) # Simular processamento
print("✅ Scraping distribuído concluído!")Explicação linha por linha:
- Linha 1:
import multiprocessing- Importa módulo multiprocessing para processamento paralelo - Linha 2:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 3:
import requests- Importa requests para requisições HTTP - Linha 4:
import time- Importa time para delays - Linha 5:
import json- Importa json para trabalhar com dados JSON - Linha 7:
def processar_url(url_data):- Define função para processar uma URL - Linha 8:
"""Processa uma URL em um processo separado"""- Docstring explicando função - Linha 9:
url = url_data['url']- Extrai URL dos dados - Linha 10:
processo_id = url_data['processo_id']- Extrai ID do processo - Linha 12:
try:- Inicia bloco try para tratamento de erros - Linha 13:
print(f"🔄 Processo {processo_id}: Processando {url}")- Mostra progresso do processo - Linha 15:
response = requests.get(url)- Faz requisição HTTP para a URL - Linha 16:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 18:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 20:
# Extrair dados- Comentário explicativo - Linha 21:
dados = []- Inicializa lista para armazenar dados - Linha 22:
elementos = soup.find_all('div', class_='item')- Encontra elementos para extrair - Linha 24:
for elemento in elementos:- Percorre cada elemento encontrado - Linha 25:
try:- Inicia bloco try para tratamento de erros - Linha 26:
titulo = elemento.find('h3').get_text().strip()- Extrai título do elemento - Linha 27:
preco = elemento.find('span', class_='preco').get_text().strip()- Extrai preço do elemento
24. Scraper Anti-CAPTCHA
from bs4 import BeautifulSoup
import requests
import time
import random
from PIL import Image
import pytesseract
class ScraperAntiCaptcha:
def __init__(self):
self.session = requests.Session()
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
def resolver_captcha(self, captcha_url):
"""Resolve CAPTCHA usando OCR"""
try:
# Baixar imagem do CAPTCHA
response = self.session.get(captcha_url)
response.raise_for_status()
# Salvar imagem temporariamente
with open('captcha_temp.png', 'wb') as f:
f.write(response.content)
# Usar OCR para ler CAPTCHA
imagem = Image.open('captcha_temp.png')
texto_captcha = pytesseract.image_to_string(imagem).strip()
print(f"🔍 CAPTCHA resolvido: {texto_captcha}")
return texto_captcha
except Exception as e:
print(f"❌ Erro ao resolver CAPTCHA: {e}")
return None
def contornar_rate_limiting(self, url):
"""Contorna rate limiting com delays inteligentes"""
try:
# Delay aleatório entre 3-8 segundos
delay = random.uniform(3, 8)
print(f"⏰ Aguardando {delay:.1f} segundos...")
time.sleep(delay)
# Fazer requisição
response = self.session.get(url, headers=self.headers)
# Verificar se foi rate limited
if response.status_code == 429:
print("🚫 Rate limited detectado, aguardando mais tempo...")
time.sleep(random.uniform(10, 20))
response = self.session.get(url, headers=self.headers)
response.raise_for_status()
return response
except Exception as e:
print(f"❌ Erro ao contornar rate limiting: {e}")
return None
def extrair_dados_protegidos(self, url):
"""Extrai dados de sites com proteções avançadas"""
try:
# Primeira tentativa
response = self.contornar_rate_limiting(url)
if not response:
return None
soup = BeautifulSoup(response.content, 'html.parser')
# Verificar se há CAPTCHA
captcha_img = soup.find('img', {'alt': re.compile(r'captcha', re.I)})
if captcha_img:
captcha_url = captcha_img.get('src')
if captcha_url:
texto_captcha = self.resolver_captcha(captcha_url)
if texto_captcha:
# Submeter CAPTCHA
form_data = {
'captcha': texto_captcha,
'submit': 'Submit'
}
response = self.session.post(url, data=form_data)
soup = BeautifulSoup(response.content, 'html.parser')
# Extrair dados
dados = []
elementos = soup.find_all('div', class_='dados')
for elemento in elementos:
try:
titulo = elemento.find('h3').get_text().strip()
conteudo = elemento.find('p').get_text().strip()
dados.append({
'titulo': titulo,
'conteudo': conteudo
})
except AttributeError:
continue
return dados
except Exception as e:
print(f"❌ Erro ao extrair dados protegidos: {e}")
return None
# Exemplo de uso
scraper = ScraperAntiCaptcha()
# Simular contorno de proteções
print("🛡️ Simulando contorno de proteções avançadas...")
print("⏰ Aplicando delays inteligentes...")
print("🔍 Resolvendo CAPTCHA...")
print("✅ Dados extraídos com sucesso!")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays - Linha 4:
import random- Importa random para delays aleatórios - Linha 5:
from PIL import Image- Importa PIL para trabalhar com imagens - Linha 6:
import pytesseract- Importa pytesseract para OCR - Linha 8:
class ScraperAntiCaptcha:- Define classe para scraper anti-CAPTCHA - Linha 9:
def __init__(self):- Construtor da classe - Linha 10:
self.session = requests.Session()- Cria sessão para manter cookies - Linha 11:
self.headers = {- Define headers para simular navegador - Linha 12:
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'- User-Agent de navegador - Linha 13:
}- Fecha dicionário de headers - Linha 15:
def resolver_captcha(self, captcha_url):- Define método para resolver CAPTCHA - Linha 16:
"""Resolve CAPTCHA usando OCR"""- Docstring explicando método - Linha 17:
try:- Inicia bloco try para tratamento de erros - Linha 19:
# Baixar imagem do CAPTCHA- Comentário explicativo - Linha 20:
response = self.session.get(captcha_url)- Faz requisição para imagem do CAPTCHA - Linha 21:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 23:
# Salvar imagem temporariamente- Comentário explicativo - Linha 24:
with open('captcha_temp.png', 'wb') as f:- Abre arquivo para salvar imagem - Linha 25:
f.write(response.content)- Salva conteúdo da imagem no arquivo
25. Scraper Adaptativo
from bs4 import BeautifulSoup
import requests
import time
import re
from urllib.parse import urljoin
class ScraperAdaptativo:
def __init__(self):
self.session = requests.Session()
self.estrategias = {
'produtos': self.extrair_produtos,
'noticias': self.extrair_noticias,
'contatos': self.extrair_contatos
}
def detectar_tipo_site(self, url):
"""Detecta automaticamente o tipo de site"""
try:
response = self.session.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Analisar conteúdo para detectar tipo
texto = soup.get_text().lower()
if any(palavra in texto for palavra in ['produto', 'preço', 'comprar', 'loja']):
return 'produtos'
elif any(palavra in texto for palavra in ['notícia', 'artigo', 'manchete']):
return 'noticias'
elif any(palavra in texto for palavra in ['contato', 'email', 'telefone']):
return 'contatos'
else:
return 'generico'
except Exception as e:
print(f"❌ Erro ao detectar tipo do site: {e}")
return 'generico'
def extrair_produtos(self, soup):
"""Estratégia para extrair produtos"""
dados = []
# Tentar diferentes seletores comuns
seletores_produto = [
'div.produto',
'div.item',
'div.product',
'article',
'.product-item'
]
for seletor in seletores_produto:
elementos = soup.select(seletor)
if elementos:
print(f"✅ Encontrados {len(elementos)} produtos com seletor: {seletor}")
for elemento in elementos:
try:
titulo = elemento.find(['h1', 'h2', 'h3', 'h4']).get_text().strip()
preco = elemento.find(text=re.compile(r'R\$\s*\d+'))
if titulo and preco:
dados.append({
'titulo': titulo,
'preco': preco.strip()
})
except AttributeError:
continue
break
return dados
def extrair_noticias(self, soup):
"""Estratégia para extrair notícias"""
dados = []
# Tentar diferentes seletores comuns
seletores_noticia = [
'div.noticia',
'div.news',
'article',
'.news-item',
'div.article'
]
for seletor in seletores_noticia:
elementos = soup.select(seletor)
if elementos:
print(f"✅ Encontradas {len(elementos)} notícias com seletor: {seletor}")
for elemento in elementos:
try:
titulo = elemento.find(['h1', 'h2', 'h3', 'h4']).get_text().strip()
resumo = elemento.find('p').get_text().strip()
if titulo:
dados.append({
'titulo': titulo,
'resumo': resumo[:100] + '...' if len(resumo) > 100 else resumo
})
except AttributeError:
continue
break
return dados
def extrair_contatos(self, soup):
"""Estratégia para extrair contatos"""
dados = {}
# Procurar por emails
emails = re.findall(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', soup.get_text())
if emails:
dados['emails'] = list(set(emails))
# Procurar por telefones
telefones = re.findall(r'\(?\d{2}\)?[-.\s]?\d{4,5}[-.\s]?\d{4}', soup.get_text())
if telefones:
dados['telefones'] = list(set(telefones))
return dados
def extrair_dados_adaptativo(self, url):
"""Extrai dados adaptando-se automaticamente ao site"""
try:
print(f"🔍 Analisando site: {url}")
# Detectar tipo do site
tipo_site = self.detectar_tipo_site(url)
print(f"📊 Tipo detectado: {tipo_site}")
# Fazer requisição
response = self.session.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
# Aplicar estratégia apropriada
if tipo_site in self.estrategias:
dados = self.estrategias[tipo_site](soup)
print(f"📄 Dados extraídos: {len(dados) if isinstance(dados, list) else 'contatos'}")
return dados
else:
print("❓ Tipo de site não reconhecido, usando estratégia genérica")
return {'tipo': 'generico', 'conteudo': soup.get_text()[:500]}
except Exception as e:
print(f"❌ Erro ao extrair dados: {e}")
return None
# Exemplo de uso
scraper = ScraperAdaptativo()
# Simular extração adaptativa
print("🤖 Simulando scraper adaptativo...")
print("🔍 Analisando site...")
print("📊 Tipo detectado: produtos")
print("✅ Estratégia de produtos aplicada")
print("📄 15 produtos extraídos com sucesso!")Explicação linha por linha:
- Linha 1:
from bs4 import BeautifulSoup- Importa BeautifulSoup - Linha 2:
import requests- Importa requests para requisições HTTP - Linha 3:
import time- Importa time para delays - Linha 4:
import re- Importa módulo de expressões regulares - Linha 5:
from urllib.parse import urljoin- Importa urljoin para construir URLs - Linha 7:
class ScraperAdaptativo:- Define classe para scraper adaptativo - Linha 8:
def __init__(self):- Construtor da classe - Linha 9:
self.session = requests.Session()- Cria sessão para manter cookies - Linha 10:
self.estrategias = {- Define dicionário com estratégias de extração - Linha 11:
'produtos': self.extrair_produtos,- Mapeia tipo ‘produtos’ para método - Linha 12:
'noticias': self.extrair_noticias,- Mapeia tipo ‘noticias’ para método - Linha 13:
'contatos': self.extrair_contatos- Mapeia tipo ‘contatos’ para método - Linha 14:
}- Fecha dicionário de estratégias - Linha 16:
def detectar_tipo_site(self, url):- Define método para detectar tipo do site - Linha 17:
"""Detecta automaticamente o tipo de site"""- Docstring explicando método - Linha 18:
try:- Inicia bloco try para tratamento de erros - Linha 19:
response = self.session.get(url)- Faz requisição HTTP para o site - Linha 20:
response.raise_for_status()- Verifica se requisição foi bem-sucedida - Linha 22:
soup = BeautifulSoup(response.content, 'html.parser')- Cria objeto BeautifulSoup - Linha 24:
# Analisar conteúdo para detectar tipo- Comentário explicativo - Linha 25:
texto = soup.get_text().lower()- Obtém todo o texto da página em minúsculas - Linha 27:
if any(palavra in texto for palavra in ['produto', 'preço', 'comprar', 'loja']):- Verifica se é site de produtos - Linha 28:
return 'produtos'- Retorna tipo ‘produtos’ - Linha 29:
elif any(palavra in texto for palavra in ['notícia', 'artigo', 'manchete']):- Verifica se é site de notícias - Linha 30:
return 'noticias'- Retorna tipo ‘noticias’ - Linha 31:
elif any(palavra in texto for palavra in ['contato', 'email', 'telefone']):- Verifica se é site de contatos - Linha 32:
return 'contatos'- Retorna tipo ‘contatos’ - Linha 33:
else:- Se não é nenhum tipo específico - Linha 34:
return 'generico'- Retorna tipo ‘generico’
Solução: Extrair títulos H1
from bs4 import BeautifulSoup
html = '''
<html>
<head><title>Minha Página</title></head>
<body>
<h1>Título Principal</h1>
<h1>Outro Título</h1>
<p>Parágrafo normal</p>
</body>
</html>
'''
soup = BeautifulSoup(html, 'html.parser')
titulos = soup.find_all('h1')
for titulo in titulos:
print(titulo.text)Conceitos-chave: BeautifulSoup, find_all, extração de texto
14.8 Próximos Passos: Continue Aprendendo!
Parabéns! Você agora domina web scraping com BeautifulSoup! 🎉
14.8.1 O que você aprendeu:
- ✅ Conceito de Web Scraping: Como extrair dados de páginas web
- ✅ HTML básico: Estrutura de páginas web e tags essenciais
- ✅ BeautifulSoup: Como usar a biblioteca para parsing de HTML
- ✅ Seletores: Como encontrar elementos específicos na página
- ✅ requests + BeautifulSoup: Combinando requisições HTTP com parsing
- ✅ Scraping responsável: Boas práticas e ética no scraping
- ✅ Salvando dados: Como organizar dados coletados em arquivos
- ✅ Projetos práticos: Sistemas de coleta de dados da web
14.8.2 Desafios para Continuar:
- Explore sites diferentes: Teste scraping em diversos tipos de sites
- Crie sistemas de monitoramento: Desenvolva scrapers que rodam periodicamente
- Automatize tarefas: Use scraping para automatizar coleta de dados
- Contribua com projetos: Encontre projetos open source que precisam de dados
14.8.3 Próximo Capítulo:
No Capítulo 15, vamos aprender sobre Banco de Dados SQL com Python! Você vai descobrir como:
- Trabalhar com bancos de dados SQLite
- Executar comandos SQL básicos
- Criar sistemas de persistência de dados
- Implementar operações CRUD completas
- Conectar Python com bancos de dados
🎯 batel.tech: Quer praticar mais? Acesse batel.tech e encontre projetos práticos para aplicar seus conhecimentos de web scraping! Lá você pode colaborar com outros desenvolvedores e construir sistemas incríveis de coleta de dados!
14.9 Referências Bibliográficas
- BeautifulSoup Documentation: Beautiful Soup Documentation
- Requests Documentation: Python HTTP Library
- Web Scraping Guide: Web Scraping Best Practices
- HTML Tutorial: W3Schools HTML Tutorial
- Scraping Ethics: Web Scraping Ethics and Legal Considerations
Capítulo 14 concluído! 🎉 Agora você está pronto para extrair dados da web e criar sistemas de coleta de informações. No próximo capítulo, vamos aprender a organizar esses dados em bancos de dados!