Um crawler robusto e profissional para baixar documentações de sites e convertê-las em um único arquivo Markdown com sumário automático (TOC).
🚨 Novo na v2.0.2: Detecção automática de SPAs! O crawler agora identifica sites com JavaScript e aborta gracefully em vez de travar.
✨ v2.0.1: Validação adaptativa, detecção automática de linguagem em code blocks, flag
--debuge TOC inteligente!
- 🔗 Resolução robusta de links (relativos/absolutos) com suporte a múltiplos padrões de documentação
- 🌐 Crawling baseado em domínio (crawleia todo o domínio base)
- 📂 Conversão para Markdown com TOC automático e metadados
- 🤖 Respeita robots.txt por padrão
- 💾 Cache local inteligente para re-execuções rápidas
- ⚡ Threads paralelas para downloads acelerados
- 🎨 Barra de progresso com
tqdm
- ✅ Validação automática de output (detecta problemas de extração)
- 🔄 Retry inteligente com exponential backoff
- ⏱️ Rate limiting automático para evitar bans
- 🔐 Autenticação HTTP (Basic Auth)
- 📋 Headers HTTP customizados
- 📊 Metadados em JSON salvos automaticamente
- 🛑 Tratamento robusto de interrupções (Ctrl+C salva progresso)
- 📝 Logging detalhado para debug
- 🧹 Fallback inteligente para sites com SSR/JavaScript
- 🎯 Filtro conservador (remove apenas páginas realmente inúteis)
- 📊 Estatísticas detalhadas (cache hits, retries, links duplicados, etc.)
- Python 3.7+ (use
python3no Linux/Mac) pip3oupip
git clone git@github.com:bychrisr/crawler.git
cd crawlerpython3 -m venv venv
# Ativa o ambiente virtual
# Linux/Mac:
source venv/bin/activate
# Windows:
venv\Scripts\activatepip install -r requirements.txt
# ou
pip3 install -r requirements.txtpython3 crawler.py --base-url <URL_DA_DOCUMENTACAO>python3 crawler.py \
--base-url https://docs.minimals.cc/introduction/ \
--output minimals-docs.md \
--max-pages 100python3 crawler.py \
--base-url https://vuejs.org/guide/ \
--output vue-docs.md \
--max-pages 1000 \
--workers 5python3 crawler.py \
--base-url https://docs-privadas.com/ \
--auth-user meu-usuario \
--auth-pass minha-senha \
--output docs-privadas.mdpython3 crawler.py \
--base-url https://api-docs.com/ \
--header "Authorization: Bearer TOKEN123" \
--header "X-Custom-Header: value" \
--output api-docs.mdpython3 crawler.py \
--base-url https://site.com/ \
--no-robots \
--output site-docs.md| Argumento | Descrição | Padrão |
|---|---|---|
--base-url |
(Obrigatório) URL base da documentação | - |
--output |
Arquivo de saída Markdown | output.md |
--workers |
Número de threads paralelas | 2 |
--max-pages |
Número máximo de páginas a crawlear | 500 |
--cache-dir |
Diretório para cache local | .cache |
--min-content-length |
Tamanho mínimo de conteúdo (chars) | 100 |
| Flag | Descrição |
|---|---|
--clear-cache |
Limpa o cache antes de iniciar |
--no-robots |
Ignora robots.txt ( |
--debug |
Mostra extração de conteúdo em tempo real (útil para debug) |
--version |
Mostra a versão do crawler |
| Argumento | Descrição |
|---|---|
--auth-user |
Usuário para autenticação HTTP básica |
--auth-pass |
Senha para autenticação HTTP básica |
--header |
Header HTTP customizado (pode usar múltiplas vezes) |
Após a execução, você terá:
.
├── output.md # Documentação em Markdown
├── output.metadata.json # Metadados da execução
├── crawler.log # Log detalhado
└── .cache/ # Cache de páginas HTML
├── abc123def.html
└── ...
Exemplo de output.metadata.json:
{
"version": "2.0.0",
"base_url": "https://docs.exemplo.com/",
"started_at": "2026-01-05T23:00:00",
"finished_at": "2026-01-05T23:05:32",
"config": {
"max_workers": 3,
"max_pages": 100,
"min_content_length": 100,
"respect_robots": true
},
"stats": {
"fetched": 87,
"failed": 2,
"cache_hits": 12,
"links_found": 95,
"retries_performed": 4,
...
}
}======================================================================
📊 RESUMO DO CRAWLING
======================================================================
✅ Páginas Crawleadas: 87
❌ Páginas Falhas: 2
🗑️ Páginas Filtradas (junk): 3
📏 Páginas Muito Pequenas: 1
🤖 Bloqueadas por robots.txt: 0
🔗 Links Encontrados: 95
🌐 Links Externos (ignorados): 234
♻️ Links Duplicados (ignorados): 1,523
💾 Cache Hits: 12
🔄 Retries Realizados: 4
📝 Total de Caracteres: 3,245,892
📖 Total de Palavras: 456,234
💾 Tamanho do Arquivo: 245,892 bytes (240.13 KB)
⏱️ Tempo Total: 00:05:32
======================================================================
🔍 VALIDAÇÃO DE QUALIDADE
======================================================================
✅ Output validado com sucesso! Nenhum problema detectado.
======================================================================
📄 Logs detalhados salvos em: crawler.log
📊 Metadados salvos em: output.metadata.json
======================================================================
O crawler agora detecta automaticamente sites que usam JavaScript puro (SPAs) e aborta gracefully em vez de travar!
Problema que resolve:
# Antes (v2.0.1):
python3 crawler.py --base-url https://spa-site.com/
# → Trava em loop infinito ou deadlock 🔒
# Agora (v2.0.2):
python3 crawler.py --base-url https://spa-site.com/
# → Detecta e aborta com mensagem clara ✅Output quando SPA é detectada:
======================================================================
⚠️ SPA DETECTADA!
======================================================================
O site https://minimals.cc/components/ parece ser uma SPA pura
(Single Page Application - React/Vue/Angular).
SPAs renderizam conteúdo via JavaScript, que este
crawler não executa. O HTML retornado está quase vazio.
📊 Análise:
- Tamanho HTML: 494 bytes
- Links encontrados: 0
- Conteúdo textual: 15 chars
💡 Soluções:
1. Use a versão de documentação (docs.exemplo.com)
2. Use Selenium/Puppeteer para SPAs
3. Verifique se existe versão SSR do site
======================================================================
❌ Crawling abortado: SPA detectada
Proteção contra crawlers travados:
Se sem progresso por 30s:
⚠️ Timeout: Sem progresso por 30s
Páginas crawleadas: 5
Possíveis causas:
- Site é uma SPA (JavaScript puro)
- Problemas de rede
- Site bloqueia crawlers
💾 Salvando progresso parcial...
Sites que NÃO funcionam (SPAs):
- Create React App sem SSR
- Vue CLI sem SSR
- Angular sem Universal
- Sites com
<div id="root"></div>vazio
Sites que funcionam:
- Next.js (SSR/SSG)
- Nuxt (SSR/SSG)
- Gatsby (SSG)
- Sites estáticos (HTML puro)
- Docusaurus, VuePress, MkDocs
Teste rápido:
# View Source no navegador
# Se vê conteúdo → ✅ Funciona
# Se só vê <div id="root"> → ❌ SPAA v2.0.1 resolve o principal problema da v2.0.0: avisos falsos-positivos sobre "baixa conversão".
Antes (v2.0.0):
⚠️ Baixa conversão de HTML para Markdown: 0.9% (esperado: >30%)
❌ Aparecia em 100% dos sites modernos, mesmo funcionando corretamente!
Agora (v2.0.1):
✅ Output validado com sucesso! Nenhum problema detectado.
✅ Threshold se adapta automaticamente ao tipo de site:
- Sites de docs técnicas (muito código): 1%
- Sites pequenos: 3%
- Sites modernos padrão: 1.5%
Code blocks agora têm syntax highlighting correto!
Antes:
```text
import React from 'react';
const App = () => <div>Hello</div>;
```Agora:
```javascript
import React from 'react';
const App = () => <div>Hello</div>;
```Linguagens detectadas: JavaScript, TypeScript, JSX, TSX, Python, Bash, JSON, CSS, HTML, Markdown
Novo modo para debugar extração:
python3 crawler.py --base-url https://docs.exemplo.com/ --debug
# Output:
[DEBUG] Extraído de https://docs.exemplo.com/intro:
- 8 headers
- 15 parágrafos
- 12 items de lista
- 5 code blocksPáginas vazias (root sem título) não aparecem mais no Table of Contents.
-
Validação Automática
- Detecta automaticamente problemas de extração
- Avisa se arquivo está muito pequeno para o número de páginas
- Identifica baixa conversão HTML → Markdown
- Alerta sobre alta taxa de falhas
-
Retry Inteligente
- Exponential backoff automático (2^n segundos)
- Configurable retries (padrão: 3 tentativas)
- Estatísticas de retries no resumo final
-
Rate Limiting
- Intervalo mínimo de 0.5s entre requests
- Evita bans e respeita servidores
-
Autenticação e Headers
- Suporte a HTTP Basic Auth
- Headers HTTP customizados
- Útil para APIs e docs privadas
-
Metadados e Observabilidade
- Arquivo JSON com metadados completos
- Timestamps de início/fim
- Configuração usada
- Todas as estatísticas
-
Tratamento de Interrupções
- Ctrl+C agora salva progresso parcial
- Não perde trabalho em interrupções
-
Robots.txt
- Respeita robots.txt por padrão
- Flag
--no-robotspara ignorar (use com responsabilidade)
- Extração robusta para sites com SSR/JavaScript
- Fallback inteligente quando
<main>está vazio - Logs mais detalhados para debug
- Código refatorado com type hints
- Configurações centralizadas em
CrawlerConfig
Solução:
pip3 install -r requirements.txtDiagnóstico:
- Verifique
crawler.log:grep "Links encontrados" crawler.log - Verifique se robots.txt está bloqueando:
grep "Bloqueado por robots.txt" crawler.log - Teste manualmente se os links funcionam no navegador
Soluções:
- Use
--no-robotsse appropriate - Aumente
--max-pagesse atingiu o limite - Verifique se o site usa JavaScript (SPAs não são suportados)
Causas comuns:
- Site usa JavaScript para renderizar (React/Vue SPA)
- Bloqueio por robots.txt
- Problemas na extração de conteúdo
Soluções:
- Verifique os avisos de validação no resumo
- Analise
crawler.logpara detalhes - Para SPAs, considere usar Selenium/Puppeteer (não suportado atualmente)
Causas:
- Timeouts de rede
- Rate limiting do servidor
- Bloqueio por firewall/WAF
Soluções:
- Reduza
--workerspara 1-2 - Use headers customizados se necessário
- Verifique conectividade de rede
Não suportado: Sites que renderizam 100% do conteúdo via JavaScript.
A partir da v2.0.2, o crawler detecta automaticamente SPAs e aborta com mensagem clara.
| Framework | SSR? | Funciona? | Exemplo |
|---|---|---|---|
| Create React App | ❌ Não | ❌ Não | minimals.cc/components |
| Next.js | ✅ Sim | ✅ Sim | docs.minimals.cc |
| Vue CLI | ❌ Não | ❌ Não | Sites Vue sem Nuxt |
| Nuxt | ✅ Sim | ✅ Sim | Sites Nuxt com SSR |
| Angular | ❌ Não* | ❌ Não* | *Sem Universal |
| Gatsby | ✅ SSG | ✅ Sim | Sites estáticos |
| Docusaurus | ✅ SSG | ✅ Sim | Documentações |
| VuePress | ✅ SSG | ✅ Sim | Documentações |
| MkDocs | ✅ SSG | ✅ Sim | Documentações |
Como identificar uma SPA:
- Abra "View Source" (Ctrl+U) no navegador
- Se vê apenas
<div id="root"></div>vazio → SPA ❌ - Se vê conteúdo HTML completo → SSR/SSG ✅
Soluções para SPAs:
- Procure versão de documentação (geralmente usa SSG)
- Use Selenium/Puppeteer (não incluído)
- Verifique se o site tem versão SSR
- Autenticação complexa: Apenas HTTP Basic Auth é suportada. OAuth e outros métodos requerem modificação no código.
- Rate Limiting agressivo: Alguns sites podem bloquear mesmo com rate limiting. Ajuste
--workersse necessário. - JavaScript Interativo: Sites que requerem cliques/interações não são suportados.
Pull requests são bem-vindos! Para mudanças maiores:
- Abra uma issue primeiro para discutir
- Fork o projeto
- Crie uma branch (
git checkout -b feature/MinhaFeature) - Commit suas mudanças (
git commit -m 'Add: MinhaFeature') - Push para a branch (
git push origin feature/MinhaFeature) - Abra um Pull Request
Veja CHANGELOG.md para histórico de versões.
Este projeto é open source sob a licença MIT. Veja LICENSE para detalhes.
- BeautifulSoup4 - HTML parsing
- requests - HTTP requests
- tqdm - Progress bars
Desenvolvido com ❤️ para a comunidade open source
Para bugs, sugestões ou dúvidas, abra uma issue!