Crawl4AI: Web Scraping com IA em Python
Aprenda a usar Crawl4AI para web scraping inteligente com LLMs em Python. Extração estruturada, crawling assíncrono e exemplos.
Web scraping tradicional exige que você escreva seletores CSS, XPath ou expressões regulares para cada site. Quando a estrutura da página muda, tudo quebra. O Crawl4AI propõe uma abordagem diferente: usar modelos de linguagem (LLMs) para entender o conteúdo da página e extrair dados de forma inteligente, sem depender da estrutura HTML.
Com mais de 30 mil estrelas no GitHub, o Crawl4AI se tornou a principal biblioteca open-source de web scraping com IA em Python. Neste artigo, vamos ver como instalar, configurar e usar o Crawl4AI para extrair dados estruturados de qualquer página web.
O que é o Crawl4AI?
O Crawl4AI é uma biblioteca Python que combina crawling assíncrono com extração baseada em LLMs. Ele usa um navegador headless (Playwright) para renderizar páginas — incluindo conteúdo JavaScript — e depois processa o HTML com estratégias de extração que podem ser baseadas em CSS tradicional ou em modelos de IA.
As principais funcionalidades incluem:
- Crawling assíncrono com suporte a múltiplas páginas simultâneas
- Extração com LLM usando modelos locais ou APIs como OpenAI e Claude
- Estratégias de extração configuráveis (CSS, cosine similarity, LLM)
- Conversão automática para Markdown otimizado para LLMs
- Suporte a JavaScript via Playwright
- Cache inteligente para evitar requisições desnecessárias
- Chunking de conteúdo longo para processamento eficiente
Instalação
A instalação é simples com pip ou UV:
# Com pip
pip install crawl4ai
crawl4ai-setup # Instala o Playwright e navegadores
# Com UV (mais rápido)
uv add crawl4ai
uv run crawl4ai-setup
O comando crawl4ai-setup baixa o Chromium e configura o Playwright automaticamente.
Crawling Básico
O uso mais simples do Crawl4AI é extrair o conteúdo de uma página como Markdown:
import asyncio
from crawl4ai import AsyncWebCrawler
async def main():
async with AsyncWebCrawler() as crawler:
resultado = await crawler.arun(url="https://python.org")
print(resultado.markdown[:500])
print(f"\nLinks encontrados: {len(resultado.links['internal'])}")
print(f"Imagens: {len(resultado.media['images'])}")
asyncio.run(main())
O Crawl4AI retorna um objeto CrawlResult com várias representações do conteúdo:
resultado.html— HTML originalresultado.markdown— conteúdo convertido para Markdownresultado.cleaned_html— HTML limpo sem scripts e estilosresultado.links— links internos e externosresultado.media— imagens, vídeos e áudios encontrados
Extração Estruturada com LLM
O diferencial do Crawl4AI é usar LLMs para extrair dados estruturados. Em vez de escrever seletores CSS, você define um schema Pydantic e deixa o modelo extrair as informações:
import asyncio
from pydantic import BaseModel
from crawl4ai import AsyncWebCrawler
from crawl4ai.extraction_strategy import LLMExtractionStrategy
class Produto(BaseModel):
nome: str
preco: float
descricao: str
disponivel: bool
async def extrair_produtos(url: str) -> list[Produto]:
estrategia = LLMExtractionStrategy(
provider="openai/gpt-4o-mini",
schema=Produto.model_json_schema(),
instruction="Extraia todos os produtos da página com nome, preço, descrição e disponibilidade.",
)
async with AsyncWebCrawler() as crawler:
resultado = await crawler.arun(
url=url,
extraction_strategy=estrategia,
)
return [Produto(**item) for item in resultado.extracted_content]
produtos = asyncio.run(extrair_produtos("https://exemplo.com/produtos"))
for p in produtos:
print(f"{p.nome}: R$ {p.preco:.2f}")
Esse padrão funciona para qualquer tipo de dado: artigos de blog, ofertas de emprego, reviews, catálogos e mais. O LLM entende o contexto da página e extrai os campos mesmo quando a estrutura HTML varia.
Extração sem LLM: CSS e Cosine Strategy
Nem tudo precisa de IA. O Crawl4AI oferece estratégias de extração que não dependem de LLMs:
CSS Extraction Strategy
Para sites com estrutura conhecida, a extração por CSS é mais rápida e barata:
import asyncio
from crawl4ai import AsyncWebCrawler
from crawl4ai.extraction_strategy import JsonCssExtractionStrategy
schema = {
"name": "Artigos",
"baseSelector": "article.post",
"fields": [
{"name": "titulo", "selector": "h2 a", "type": "text"},
{"name": "link", "selector": "h2 a", "type": "attribute", "attribute": "href"},
{"name": "resumo", "selector": ".excerpt", "type": "text"},
{"name": "data", "selector": "time", "type": "attribute", "attribute": "datetime"},
],
}
async def main():
estrategia = JsonCssExtractionStrategy(schema)
async with AsyncWebCrawler() as crawler:
resultado = await crawler.arun(
url="https://blog.exemplo.com",
extraction_strategy=estrategia,
)
for artigo in resultado.extracted_content:
print(f"- {artigo['titulo']}")
asyncio.run(main())
Cosine Strategy
A estratégia de similaridade por cosseno agrupa conteúdo semanticamente relacionado sem precisar de seletores:
from crawl4ai.extraction_strategy import CosineStrategy
estrategia = CosineStrategy(
semantic_filter="vagas de emprego python",
word_count_threshold=50,
sim_threshold=0.3,
)
Crawling de Múltiplas Páginas
Para projetos que precisam raspar várias páginas, o Crawl4AI oferece crawling assíncrono eficiente:
import asyncio
from crawl4ai import AsyncWebCrawler
async def crawl_multiplas(urls: list[str]):
async with AsyncWebCrawler() as crawler:
resultados = await crawler.arun_many(
urls=urls,
max_concurrent=5, # Máximo de páginas simultâneas
)
for resultado in resultados:
if resultado.success:
print(f"✓ {resultado.url}: {len(resultado.markdown)} chars")
else:
print(f"✗ {resultado.url}: {resultado.error_message}")
urls = [
"https://python.org",
"https://pypi.org",
"https://docs.python.org/3/",
]
asyncio.run(crawl_multiplas(urls))
Configurações Avançadas
Executar JavaScript antes da extração
Páginas com conteúdo dinâmico podem precisar de interações antes da extração:
async with AsyncWebCrawler() as crawler:
resultado = await crawler.arun(
url="https://exemplo.com/infinite-scroll",
js_code=[
"window.scrollTo(0, document.body.scrollHeight);",
"await new Promise(r => setTimeout(r, 2000));",
],
wait_for="css:.item:nth-child(20)", # Esperar 20 itens carregarem
)
Headers e cookies personalizados
async with AsyncWebCrawler(
headers={"Accept-Language": "pt-BR,pt;q=0.9"},
cookies=[{"name": "session", "value": "abc123", "domain": "exemplo.com"}],
) as crawler:
resultado = await crawler.arun(url="https://exemplo.com")
Cache para desenvolvimento
Durante o desenvolvimento, o cache evita requisições repetidas:
async with AsyncWebCrawler() as crawler:
# Primeira chamada: faz a requisição
resultado = await crawler.arun(url="https://exemplo.com", cache_mode="enabled")
# Segunda chamada: usa o cache
resultado = await crawler.arun(url="https://exemplo.com", cache_mode="enabled")
Crawl4AI vs BeautifulSoup vs Scrapy
| Recurso | BeautifulSoup | Scrapy | Crawl4AI |
|---|---|---|---|
| Extração com LLM | Não | Não | Sim |
| JavaScript rendering | Não | Com plugin | Sim (Playwright) |
| Assíncrono nativo | Não | Sim | Sim |
| Conversão para Markdown | Não | Não | Sim |
| Curva de aprendizado | Baixa | Média | Baixa |
| Ideal para | Parsing simples | Crawling em escala | Extração inteligente |
Para projetos que precisam apenas de parsing HTML simples, BeautifulSoup com requests continua sendo uma boa escolha. Para scraping em larga escala com pipelines complexos, Scrapy é maduro e robusto. O Crawl4AI brilha quando você precisa extrair dados estruturados de páginas variadas sem escrever seletores específicos para cada uma.
Exemplo Completo: Monitorando Vagas de Python
Vamos juntar tudo em um exemplo prático que monitora vagas de emprego:
import asyncio
import json
from datetime import datetime
from pydantic import BaseModel
from crawl4ai import AsyncWebCrawler
from crawl4ai.extraction_strategy import LLMExtractionStrategy
class Vaga(BaseModel):
titulo: str
empresa: str
localizacao: str
senioridade: str
salario: str | None = None
tecnologias: list[str]
async def monitorar_vagas():
estrategia = LLMExtractionStrategy(
provider="openai/gpt-4o-mini",
schema=Vaga.model_json_schema(),
instruction=(
"Extraia todas as vagas de emprego relacionadas a Python. "
"Identifique título, empresa, localização, nível de senioridade, "
"salário (se disponível) e tecnologias mencionadas."
),
)
urls = [
"https://exemplo.com/vagas/python",
"https://exemplo.com/vagas/backend",
]
async with AsyncWebCrawler() as crawler:
resultados = await crawler.arun_many(
urls=urls,
extraction_strategy=estrategia,
max_concurrent=3,
)
todas_vagas = []
for resultado in resultados:
if resultado.success and resultado.extracted_content:
vagas = [Vaga(**v) for v in resultado.extracted_content]
todas_vagas.extend(vagas)
# Salvar resultados
with open("vagas.json", "w", encoding="utf-8") as f:
json.dump(
[v.model_dump() for v in todas_vagas],
f,
ensure_ascii=False,
indent=2,
)
print(f"Encontradas {len(todas_vagas)} vagas em {datetime.now():%Y-%m-%d %H:%M}")
for vaga in todas_vagas[:5]:
print(f" - {vaga.titulo} @ {vaga.empresa} ({vaga.senioridade})")
asyncio.run(monitorar_vagas())
Boas Práticas
Ao usar o Crawl4AI em projetos reais, considere estas práticas:
- Respeite o
robots.txt: verifique se o site permite scraping antes de começar. - Use rate limiting: configure intervalos entre requisições para não sobrecarregar servidores.
- Prefira extração CSS quando possível: é mais rápida e não consome tokens de LLM.
- Cache durante desenvolvimento: evite requisições desnecessárias enquanto ajusta o código.
- Trate erros: páginas podem falhar, retornar 403 ou ter estrutura inesperada.
- Monitore custos de LLM: cada extração com LLM consome tokens. Use modelos menores para tarefas simples.
Se você trabalha com logging e tratamento de erros, esses conhecimentos são essenciais para robustez em projetos de scraping.
Conclusão
O Crawl4AI traz o web scraping para uma nova era. Em vez de batalhar com seletores frágeis que quebram a cada mudança no HTML, você descreve o que quer extrair e deixa o LLM fazer o trabalho pesado de entender a estrutura da página.
Para projetos que precisam extrair dados de sites variados, lidar com conteúdo dinâmico e produzir resultados estruturados, o Crawl4AI é a ferramenta mais produtiva disponível em Python hoje. E para quem já domina scraping tradicional com BeautifulSoup e requests, a migração é natural — os conceitos são os mesmos, só a estratégia de extração muda.
Se você quer explorar mais ferramentas modernas do ecossistema Python, confira nossos artigos sobre Polars, Pydantic e automação com Python.
Para scraping em larga escala com performance máxima, Go com Colly oferece crawling concorrente extremamente eficiente com goroutines — ideal para quando você precisa raspar milhões de páginas e o gargalo é a velocidade de rede, não a extração de dados.
Equipe python.dev.br
Contribuidor do Python Brasil — Aprenda Python em Português