- flaresolverr.py: refactor stateless (create_session/destroy_session/get)
L'ancienne approche warmup→cookies→requests était bloquée par Cloudflare
(JA3 TLS fingerprinting). Toutes les requêtes passent maintenant via une
session Chrome persistante FlareSolverr.
- ma_http.py: MASession utilise les sessions FS persistantes. Ajout de
_extract_json (html.unescape + extraction <pre>) et _build_url.
Gestion du refresh sur 403/429 avec recréation de session.
- db.py: ajout du champ data JSONB dans upsert_bands INSERT+ON CONFLICT.
Avant ce fix, l'URL n'était jamais stockée → get_bands_to_enrich retournait
toujours 0 résultats → enrichissement mort.
- scraper_band.py: schéma band_page aligné sur l'historique DB (lineup
structuré avec URLs artistes, discography_url, lyrical_themes, location,
info_raw). Ajout de "Themes" dans _pick pour couvrir les deux variantes
de clé HTML (MA utilise parfois "Themes", parfois "Lyrical themes").
- 005_fix_checkpoints_and_data.sql: renomme last_additions_check →
last_created_check (clé morte vs clé utilisée par le code). Backfill
enriched=true + colonnes top-level (formed_year, themes, status,
location_text) depuis band_page JSONB pour les 85k bands de l'ancien scraper.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- apps/crawler/ : service Python complet, remplace les scripts locaux
- FlareSolverr pour bypasser Cloudflare (cookies CF → session requests)
- Crawl incrémental : /archives/band-list/by/created et /by/modified
- Crawl complet Europe : pagination AJAX /browse/ajax-country/
- Enrichissement : pages individuelles de bands (themes, membres, label, hash)
- Écriture directe en DB (upserts bulk, idempotents)
- Scheduler intégré (schedule library) : incrémental 4h, enrich 2h, full le 1er du mois
- Tracking via crawl_run et crawl_checkpoint (migration 004)
- docker-compose.dev.yml : flaresolverr + crawler ajoutés
Full crawl désactivé en dev (CRAWLER_SCHED_FULL_DAY=0)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>