Web Scraping / RAG

Framework de web scraping para aplicações de IA

PythonOpen Source

Extração limpa de conteúdo web com crawling inteligente, conversão para markdown e pipeline completo de embeddings para aplicações RAG.

O que é este projeto

O Eget Crawler é um framework de web scraping construído especificamente para alimentar aplicações de IA e pipelines RAG (Retrieval-Augmented Generation). Diferente de scrapers genéricos, cada decisão de design foi tomada pensando em como o conteúdo será consumido por modelos de linguagem.

O framework cuida de todo o ciclo: descoberta de URLs, extração de conteúdo, limpeza de HTML, conversão para markdown, geração de embeddings e armazenamento em vector stores. Tudo assíncrono, respeitando limites e pronto para escalar.

Scraping ético é inegociável. O Eget Crawler respeita robots.txt, implementa rate limiting configurável, identifica-se via User-Agent e permite configurar delays entre requisições. Se o site não quer ser crawleado, o crawler não crawleia.

Crawling inteligente

O módulo de crawling vai além de seguir links. Ele entende a estrutura do site antes de começar a extrair conteúdo:

  • Respeito ao robots.txt — parse automático de regras de exclusão antes de qualquer requisição
  • Rate limiting adaptativo — ajusta a velocidade baseado em respostas 429 e headers Retry-After
  • Deduplicação de URLs — normalização de URLs com remoção de parâmetros de tracking e fragmentos
  • Parsing de sitemap — leitura de sitemap.xml e sitemap index para descoberta eficiente de páginas
  • Filtros por profundidade — controle de profundidade máxima de crawling e padrões de URL

Exemplo: Configuração do crawler

# Configuração básica do Eget Crawler from eget import Crawler, CrawlConfig config = CrawlConfig( seed_urls=['https://docs.exemplo.com.br'], max_depth=3, rate_limit=2.0, # requisições por segundo respect_robots=True, user_agent='EgetCrawler/1.0 (+https://sakaguchi.ia.br)', url_filters=[ r'/docs/.*', # apenas /docs/ r'!/.*\.(pdf|zip)' # excluir binários ] ) crawler = Crawler(config) async for page in crawler.crawl(): print(f'Extraído: {page.url} ({page.word_count} palavras)')

Conversão para Markdown

HTML bruto não serve para RAG. O pipeline de conversão transforma páginas complexas em markdown limpo e estruturado, preservando a hierarquia semântica do conteúdo:

  • Extração de conteúdo principal — algoritmo que identifica o bloco de conteúdo principal versus navegação, footer, sidebar e ads
  • Remoção de boilerplate — scripts, estilos, cookies banners, pop-ups e elementos decorativos são descartados
  • Preservação de estrutura — headings, listas, tabelas, blocos de código e links são convertidos fielmente
  • Metadados extraídos — título, descrição, autor, data de publicação e tags são capturados separadamente
  • Chunking inteligente — o markdown resultante é dividido em chunks semânticos respeitando limites de seção

Processamento assíncrono

Crawlear milhares de páginas de forma sequencial não escala. O Eget Crawler usa asyncio com um pool de workers configurável e gerenciamento de fila para maximizar throughput sem sobrecarregar o servidor alvo:

  • Worker pool com asyncio — número configurável de workers concorrentes com semáforo
  • Fila persistente — URLs pendentes são salvas em disco para retomada após interrupções
  • Backpressure — o sistema desacelera automaticamente quando a fila de processamento cresce demais
  • Retry com exponential backoff — requisições falhas são recolocadas na fila com delay crescente

Exemplo: Arquitetura assíncrona

# Worker pool assíncrono com controle de concorrência import asyncio from eget import Crawler, CrawlConfig, MarkdownPipeline async def process_site(seed_url: str): config = CrawlConfig( seed_urls=[seed_url], max_workers=10, queue_backend='sqlite', # persistência em disco retry_max=3, backoff_factor=1.5 ) pipeline = MarkdownPipeline( remove_boilerplate=True, chunk_size=512, chunk_overlap=64 ) crawler = Crawler(config, pipeline=pipeline) results = await crawler.run() print(f'Páginas: {results.pages_crawled}') print(f'Chunks: {results.chunks_generated}') print(f'Tempo: {results.elapsed:.1f}s') asyncio.run(process_site('https://docs.exemplo.com.br'))

Conteúdo dinâmico

Muitos sites modernos renderizam conteúdo via JavaScript. O Eget Crawler integra com Playwright para lidar com SPAs, páginas com lazy loading e conteúdo gerado dinamicamente:

  • Playwright headless — Chromium controlado programaticamente para renderizar JavaScript completo
  • Detecção automática — identifica quando uma página precisa de browser versus requisição HTTP simples
  • Wait strategies — espera por seletores CSS, network idle ou timeout antes de extrair
  • Interceptação de rede — bloqueia imagens, fonts e analytics para acelerar a renderização
  • Pool de browsers — reutilização de instâncias Playwright para reduzir overhead de inicialização

Pipeline RAG

O conteúdo extraído e convertido em markdown precisa virar embeddings armazenados em um vector store para ser útil em aplicações RAG. O Eget Crawler oferece integração nativa com os principais vector databases:

# Pipeline completo: crawl → extract → embed → store from eget import Crawler, CrawlConfig, MarkdownPipeline from eget.embeddings import OpenAIEmbedder from eget.stores import ChromaStore # 1. Configurar crawler + pipeline config = CrawlConfig( seed_urls=['https://docs.exemplo.com.br'], max_depth=3, rate_limit=2.0 ) pipeline = MarkdownPipeline(chunk_size=512) # 2. Configurar embeddings + vector store embedder = OpenAIEmbedder(model='text-embedding-3-small') store = ChromaStore( collection='documentacao', persist_dir='./chroma_data' ) # 3. Executar pipeline completo crawler = Crawler(config, pipeline=pipeline) async for chunk in crawler.stream_chunks(): embedding = await embedder.embed(chunk.text) store.upsert( id=chunk.id, embedding=embedding, metadata={ 'url': chunk.source_url, 'title': chunk.title, 'section': chunk.heading }, document=chunk.text )
  • ChromaDB — armazenamento local, ideal para desenvolvimento e prototipação rápida
  • Pinecone — vector store gerenciado para produção com escala horizontal
  • Weaviate — suporte a busca híbrida (vetorial + keyword) com filtros por metadados
Crawl URLs + HTML Extract HTML → Markdown Embed Chunks → Vetores Store Vector Database async chunk upsert ChromaDB Pinecone Weaviate

Pipeline completo: Crawl → Extract → Embed → Store

Monitoramento

Crawling em escala sem observabilidade é voar às cegas. O Eget Crawler expõe métricas Prometheus nativas que podem ser visualizadas em dashboards Grafana:

  • pages_per_second — throughput real de páginas crawleadas por segundo
  • error_rate — percentual de requisições com erro (4xx, 5xx, timeout)
  • queue_depth — quantidade de URLs pendentes na fila de processamento
  • embedding_latency_ms — latência P50/P95/P99 da geração de embeddings
  • chunks_stored_total — contador de chunks inseridos no vector store
  • active_workers — workers ativos versus configurados para identificar gargalos

As métricas são expostas no endpoint /metrics (porta 9090) e são compatíveis com qualquer stack de monitoramento baseada em Prometheus. Incluímos um dashboard Grafana pré-configurado no repositório.

O dashboard Grafana incluso no repositório mostra em tempo real: throughput, taxa de erros, profundidade da fila e latência de embeddings. Basta importar o JSON no seu Grafana e apontar para o Prometheus.

Quer implementar algo parecido?

Entendemos o seu contexto antes de apresentar qualquer solução.

Fale conosco