SPB Git forge

spb/trawls

Public
3commits 1branches 0releases
456.0 KBsize
maindefault branch
19 days agolast push
Python 76.2% JavaScript 11.3% CSS 6.3% HTML 5.9%
4.6 KB · 89 lines markdown
Rendered Raw Blame History
1# Trawls — www.trawls.dev23Moteur 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**.45- **Ne crashe jamais** : une page qui échoue produit un `PageResult` `status=failed` avec une erreur typée. Le crawl continue.6- **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.7- **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.8- **PDF** : texte avec ordre de lecture, titres inférés, tables, détection de scan (OCR optionnel).9- **Extraction structurée** : CSS typé (déterministe) ou LLM (JSON Schema, validation, corrections) avec fusion multi-pages.10- **Self-host first** : SQLite, worker embarqué, aucun service externe requis. LLM local via Ollama par défaut.11- **Observable** : structlog JSON, `/healthz`, `/readyz`, `/metrics` Prometheus, trace d'escalade par page.1213## Démarrage1415```bash16uv venv --python 3.12 && source .venv/bin/activate17uv pip install -e ".[dev]"18playwright install chromium19trawls serve            # http://localhost:8180 (UI + API + worker)20```2122```bash23trawls scrape https://fr.wikipedia.org/wiki/Chalut24trawls map https://docs.python.org --search "asyncio"25trawls crawl https://exemple.com --max-pages 50 -o pages.jsonl26```2728Docker : `make up` (api + web sur http://localhost:8180).2930## API (`/v1`, OpenAPI sur `/docs`)3132| Méthode | Route | Rôle |33|---|---|---|34| POST | `/scrape` | une page, synchrone → `PageResult` |35| POST | `/crawl` → GET `/crawl/{id}` · `/crawl/{id}/stream` (SSE) · DELETE | crawl asynchrone, pages streamées |36| POST | `/map` | liste d'URLs (sitemaps + crawl shallow), tri BM25 si `search` |37| POST | `/extract` | CSS ou LLM sur `urls[]` / `pattern` ; sync ≤ 5 URLs |38| POST | `/batch/scrape` | N URLs en job |39| GET | `/jobs`, `/jobs/{id}`, `/jobs/{id}/stream`, `/jobs/{id}/export?format=zip\|jsonl\|md` | jobs génériques |40| GET | `/usage` · `/keys` (admin) | crédits, clés API (argon2, affichées une fois) |4142Erreurs : `{ "error": { "code", "message", "retryable", "details?" } }`. Idempotence : header `Idempotency-Key`. Webhooks signés `X-Trawls-Signature` (HMAC-SHA256).4344```bash45curl -s https://www.trawls.dev/v1/scrape -H 'Content-Type: application/json' \46  -d '{"url":"https://example.com","formats":["markdown","links"]}' | jq .markdown47```4849## Configuration (préfixe `TRAWLS_`)5051`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`.5253## Architecture5455```56trawls/57  config.py            settings pydantic58  models/              contrat Pydantic v2 (ScrapeOptions, PageResult, ErrorInfo…)59  core/fetcher/        http_fast (curl_cffi), browser (pool Playwright), strategy (escalade)60  core/antibot/        detect, identity, stealth, blocklist61  core/scheduler/      dedup (normalisation + simhash), robots, politeness62  core/resilience/     retry, breaker, budget63  core/security.py     garde SSRF (DNS résolu avant, re-vérifié après redirection)64  core/scrape.py       pipeline d'une page — ne lève jamais65  processors/          html_to_md (clean, readability, convert, tables, citations), pdf, structured, chunker, links66  extract/             css, llm, merge67  map/                 sitemaps + crawl shallow + BM2568  llm/                 client unique (Anthropic, OpenAI-compatible)69  worker/              store SQLite, moteur de jobs (crawl/batch/extract), SSE70  api/                 FastAPI /v1, auth, UI71  web/static/          UI (playground, crawls, map, extract, keys)72  cli.py73```7475## Tests7677```bash78pytest -q                 # unitaires (html_to_md, dedup, ssrf, detect, chunker, css)79ruff check . && ruff format --check .80```8182## Déploiement MacLustr8384Déployée via `mld` (manifeste `trawls.json`) : PM2 `trawls-api` + `trawls-ngrok` → https://www.trawls.dev. Voir `deploy/trawls.manifest.json`.8586## Feuille de route8788Phases 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`.89