Trawls — www.trawls.dev
Moteur de crawling, d'extraction et de navigation web, construit from scratch. Un chalut (trawl) ratisse le fond et remonte tout : Trawls cartographie et extrait n'importe quel site et renvoie du Markdown propre, LLM-ready.
- Ne crashe jamais : une page qui échoue produit un
PageResultstatus=failedavec une erreur typée. Le crawl continue. - Escalade automatique : HTTP pur (curl_cffi, empreinte TLS Chrome) → navigateur (Playwright, pool de contexts) → stealth (patches JS, identité cohérente). Le mode résolu est mémorisé par host.
- Sortie LLM-ready : pipeline HTML → Markdown maison (nettoyage, suppression du boilerplate, scoring du contenu principal, tables avec rowspan/colspan, citations), métadonnées fusionnées (head, OpenGraph, JSON-LD), chunks par titres ou par tokens.
- PDF : texte avec ordre de lecture, titres inférés, tables, détection de scan (OCR optionnel).
- Extraction structurée : CSS typé (déterministe) ou LLM (JSON Schema, validation, corrections) avec fusion multi-pages.
- Self-host first : SQLite, worker embarqué, aucun service externe requis. LLM local via Ollama par défaut.
- Observable : structlog JSON,
/healthz,/readyz,/metricsPrometheus, trace d'escalade par page.
Démarrage
uv venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"
playwright install chromium
trawls serve # http://localhost:8180 (UI + API + worker)trawls scrape https://fr.wikipedia.org/wiki/Chalut
trawls map https://docs.python.org --search "asyncio"
trawls crawl https://exemple.com --max-pages 50 -o pages.jsonlDocker : make up (api + web sur http://localhost:8180).
API (/v1, OpenAPI sur /docs)
| Méthode | Route | Rôle |
|---|---|---|
| POST | /scrape |
une page, synchrone → PageResult |
| POST | /crawl → GET /crawl/{id} · /crawl/{id}/stream (SSE) · DELETE |
crawl asynchrone, pages streamées |
| POST | /map |
liste d'URLs (sitemaps + crawl shallow), tri BM25 si search |
| POST | /extract |
CSS ou LLM sur urls[] / pattern ; sync ≤ 5 URLs |
| POST | /batch/scrape |
N URLs en job |
| GET | /jobs, /jobs/{id}, /jobs/{id}/stream, /jobs/{id}/export?format=zip|jsonl|md |
jobs génériques |
| GET | /usage · /keys (admin) |
crédits, clés API (argon2, affichées une fois) |
Erreurs : { "error": { "code", "message", "retryable", "details?" } }. Idempotence : header Idempotency-Key. Webhooks signés X-Trawls-Signature (HMAC-SHA256).
curl -s https://www.trawls.dev/v1/scrape -H 'Content-Type: application/json' \
-d '{"url":"https://example.com","formats":["markdown","links"]}' | jq .markdown Configuration (préfixe TRAWLS_)
PORT (8180), PUBLIC_URL, DATA_DIR, REQUIRE_AUTH, ADMIN_KEY, BROWSER_POOL_SIZE, MAX_CONCURRENCY_PER_HOST, MAX_SIZE_MB, PROXY_URLS, LLM_PROVIDER (openai|anthropic|none), LLM_BASE_URL (Ollama par défaut), LLM_API_KEY, LLM_MODEL, RESULT_TTL_DAYS, RATE_LIMIT_PER_MINUTE, ALLOW_PRIVATE_TARGETS (jamais en prod). Voir .env.example.
Architecture
trawls/
config.py settings pydantic
models/ contrat Pydantic v2 (ScrapeOptions, PageResult, ErrorInfo…)
core/fetcher/ http_fast (curl_cffi), browser (pool Playwright), strategy (escalade)
core/antibot/ detect, identity, stealth, blocklist
core/scheduler/ dedup (normalisation + simhash), robots, politeness
core/resilience/ retry, breaker, budget
core/security.py garde SSRF (DNS résolu avant, re-vérifié après redirection)
core/scrape.py pipeline d'une page — ne lève jamais
processors/ html_to_md (clean, readability, convert, tables, citations), pdf, structured, chunker, links
extract/ css, llm, merge
map/ sitemaps + crawl shallow + BM25
llm/ client unique (Anthropic, OpenAI-compatible)
worker/ store SQLite, moteur de jobs (crawl/batch/extract), SSE
api/ FastAPI /v1, auth, UI
web/static/ UI (playground, crawls, map, extract, keys)
cli.pyTests
pytest -q # unitaires (html_to_md, dedup, ssrf, detect, chunker, css)
ruff check . && ruff format --check .Déploiement MacLustr
Déployée via mld (manifeste trawls.json) : PM2 trawls-api + trawls-ngrok → https://www.trawls.dev. Voir deploy/trawls.manifest.json.
Feuille de route
Phases 1–6 livrées (fetch + escalade, Markdown, API/jobs/SSE/CLI, map + PDF, extract + chunker, UI). Phase 7 (agent) et 8 (SDK, benchmarks) à venir — voir CLAUDE.md.