Introdução à Coleta de Dados Automatizada
A extração automatizada de informações da web, frequentemente chamada de web scraping, é essencial para análise de dados e monitoramento. A linguagem Python se destaca nesse cenário devido à sua sintaxe acessível e ao vasto ecossistema de bibliotecas especializadas. Este guia aborda os fundamentos e técnicas avançadas para construir robôs de coleta eficientes, utilizando exemplos reais para ilustrar cada conceito.
Preparação do Ambiente
Para iniciar, é necessário instalar as dependências principais. Focaremos nas bibliotecas requests, para gerenciamento de requisições HTTP, e BeautifulSoup, para análise estrutural de documentos HTML.
import requests
from bs4 import BeautifulSoup
Implementação Inicial de Coleta
Considerando o site oficial da Python Foundation como alvo, podemos estruturar um script básico para recuperar o conteúdo da página. O objetivo é estabelecer a conexão e transformar o texto bruto em um objeto navegável.
endereco_alvo = "https://www.python.org/"
resposta_http = requests.get(endereco_alvo)
analise_html = BeautifulSoup(resposta_http.text, 'html.parser')
print(analise_html.prettify()[:500])
O método get executa a solicitação GET, enquanto o parser da BeautifulSoup interpreta a estrutura do documento. A saída exibe os primeiros caracteres do código fonte processado.
Seleção de Elementos via CSS
Para isolar dados específicos, como links de navegação, utilizamos seletores CSS. Isso permite filtrar apenas as tags relevantes dentro da árvore DOM.
seletor_navegacao = 'div.top-bar > ul > li > a'
elementos_encontrados = analise_html.select(seletor_navegacao)
for item in elementos_encontrados:
link = item.get('href')
texto = item.text
print(link, texto)
O seletor identifica ancoras (a) aninhadas dantro de listas não ordenadas na barra superior. O loop itera sobre os resultados extraindo o href e o texto visível.
Parseamento com XPath
Alternativamente, a linguagem XPath oferece um poder de consulta robusto, especialmente útil para documentos XML ou HTML complexos. A biblioteca lxml facilita essa abordagem.
from lxml import etree
codigo_html = '<div><a href="/a">A</a><a href="/b">B</a></div>'
arvore_dom = etree.HTML(codigo_html)
caminhos = arvore_dom.xpath('//a/@href')
print(caminhos)
Aqui, convertimos uma string HTML em uma árvore estruturada e aplicamos uma expressão XPath para extrair todos os atributos de href das tags de ancoras.
Normalização de URLs
Muitos links extraídos são relativos. Para torná-los utilizáveis, é necessário combiná-los com o domínio base usando utilitários padrão da linguagem.
from urllib.parse import urljoin
for item in elementos_encontrados:
href_relativo = item.get('href')
url_completa = urljoin(endereco_alvo, href_relativo)
print(url_completa, item.text)
A função urljoin resolve automaticamente as paths relativas, garantindo que cada link apontado seja absoluto e acessível.
Manipulação de Conteúdo Dinâmico
Sites modernos frequentemente carregam dados via JavaScript após o carregamento inicial. Nesses casos, ferramentas de automação de navegador como o Selenium são necessárias.
from selenium import webdriver
from selenium.webdriver.common.by import By
navegador = webdriver.Firefox()
navegador.get('https://www.python.org/')
elemento_alvo = navegador.find_element(By.CSS_SELECTOR, 'div.top-bar > ul > li > a')
print(elemento_alvo.text)
O Selenium instancia um navegador real, permitindo a execução de scripts client-side. A busca pelo elemento utiliza a estratégia de seleção CSS atualizada.
Gerenciamento de Proxies
Para evitar bloqueios por excesso de requisições, o tráfego pode ser roteado através de servidores intermediários, ocultando o IP original do script.
configuracao_proxy = {
"http": "http://192.168.1.5:8080",
"https": "http://192.168.1.5:8080",
}
resposta_segura = requests.get("https://www.python.org/", proxies=configuracao_proxy)
O dicionário de proxies é passado diretamente para a método de requisição, desviando a conexão através do servidor especificado.
Otimização com Assincronia
Em operações de larga escala, o bloqueio I/O pode reduzir drasticamente a performance. O uso de asyncio juntamente com aiohttp permite concorrência eficiente.
import asyncio
import aiohttp
async def requisitar(sessao, endereco):
async with sessao.get(endereco) as resp:
return await resp.text()
async def executar_principal():
async with aiohttp.ClientSession() as sessao:
conteudo = await requisitar(sessao, 'http://python.org')
print(conteudo[:500])
asyncio.run(executar_principal())
Definimos corrotinas para gerenciar as sessões HTTP. O loop de eventos executa as tarefas sem bloquear a thread principal durante a espera de respostas de rede.
Frameworks Especializados: Scrapy
Para projetos de grande porte, o framework Scrapy oferece arquitetura pronta para escalabilidade, incluindo gerenciamento de pipelines e middlewares.
import scrapy
class RastreadorPersonalizado(scrapy.Spider):
name = 'rastreador_python'
start_urls = ['http://python.org']
def processar(self, response):
self.log('Acesso realizado em %s' % response.url)
yield {
'endereco': response.url,
'titulo_pagina': response.css('title::text').get(),
}
A classe herda do spider base, definindo URLs iniciais e o método de parse. O framework gerencia a fila de requisições automaticamente.
Agendamento de Tarefas
A execução periódica de scripts pode ser gerenciada por bibliotecas de agendamento, permitindo atualizações regulares de dados sem intervenção manual.
import schedule
import time
def tarefa_coleta():
print("Executando coleta de dados...")
schedule.every(10).seconds.do(tarefa_coleta)
while True:
schedule.run_pending()
time.sleep(1)
O loop infinito verifica constantemente se há tarefas pendentes no agendador, executando a função definida no intervalo estipulado.
Ética e Conformidade: Robots.txt
É crucial respeitar as regras de exclusão definidas pelos proprietários dos sites. O arquivo robots.txt especifica quais áreas são permitidas para bots.
from urllib.robotparser import RobotFileParser
verificador = RobotFileParser()
verificador.set_url('http://www.python.org/robots.txt')
verificador.read()
permisso = verificador.can_fetch('*', 'http://www.python.org/')
print(permisso)
O parser verifica as diretrizes antes da coleta. Além de seguir essas regras, é recomendável limitar a frequência das requisições para não sobrecarregar os servidores alvo.