Vague 4 — expansion massive : twitch-decouverte + kick-decouverte (Scrapfly), YT 1361 requêtes (bloc EN, 13 thèmes×56 villes, +100 passe-temps), iTunes 146 requêtes, +5 catégories Wikipédia, enrichisseur region-bio (ville déclarée en bio → région §7)
+3 596 créateurs (5 841 → 9 437), +3 684 comptes (10 512). Twitch 292, Kick 122 comptes. region-bio : 1 391 fiches localisées. Avatars 96,5 %. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
28 changed files +1,053 −169
modified
creaka/connectors/balados_itunes.py
+19 −0
@@ -65,6 +65,25 @@ QUERIES = [ | ||
| 65 | 65 | "balado papa québec", "balado éducation québec", "balado science québec", |
| 66 | 66 | "balado littérature québec", "balado poésie québec", "balado bd québec", |
| 67 | 67 | "balado jeux de société québec", "balado vin québec", "balado bière québec", |
| 68 | + # vague 4 : villes restantes + créneaux supplémentaires | |
| 69 | + "mascouche", "blainville balado", "brossard", "mirabel", "boucherville", | |
| 70 | + "chambly", "varennes balado", "sainte-julie", "beloeil", "mont-tremblant", | |
| 71 | + "sainte-adèle", "thetford mines", "la tuque", "gaspé", "roberval", | |
| 72 | + "dolbeau", "amqui", "montmagny", "saint-georges beauce", "cowansville", | |
| 73 | + "lachute", "salaberry-de-valleyfield", "sainte-thérèse", "l'assomption", | |
| 74 | + "rawdon", "baie-saint-paul", "la malbaie", "chibougamau", | |
| 75 | + "balado ia québec", "balado crypto québec", "balado marketing québec", | |
| 76 | + "balado droit québec", "balado médecine québec", "balado psycho québec", | |
| 77 | + "balado philosophie québec", "balado environnement québec", | |
| 78 | + "balado autochtone", "balado voyage québec", "balado spiritualité québec", | |
| 79 | + "balado true crime québec", "balado paranormal québec", | |
| 80 | + "balado nostalgie québec", "balado télé québec", "balado wrestling québec", | |
| 81 | + "balado lutte québec", "balado course québec", "balado vélo québec", | |
| 82 | + "balado golf québec", "balado pêche à la mouche québec", | |
| 83 | + "balado gestion québec", "balado rh québec", "balado photo québec", | |
| 84 | + "balado musique émergente québec", "balado métal québec", | |
| 85 | + "balado country québec", "balado horreur québec", "balado cinéma d'horreur", | |
| 86 | + "balado animation québec", "balado improvisation québec", | |
| 68 | 87 | ] |
| 69 | 88 | |
| 70 | 89 | _GENRE_NICHE = { |
added
creaka/connectors/kick_decouverte.py
+147 −0
@@ -0,0 +1,147 @@ | ||
| 1 | +# ============================================================================== | |
| 2 | +# Author: Simon-Pierre Boucher <contact@spboucher.ai> | |
| 3 | +# File: creaka/connectors/kick_decouverte.py | |
| 4 | +# Desc: Connecteur DÉCOUVERTE — streamers Kick québécois via l'API publique | |
| 5 | +# de recherche du site (kick.com/api/search) + fiche v2 par chaîne | |
| 6 | +# (liens sociaux AUTO-DÉCLARÉS par le créateur → cross_link 0.90). | |
| 7 | +# Mode d'accès : Scrapfly ASP sans render_js (Cloudflare bloque les | |
| 8 | +# requêtes directes — 403). Palier 4 (§9/§10). | |
| 9 | +# ============================================================================== | |
| 10 | +"""Découverte des streamers Kick québécois. | |
| 11 | + | |
| 12 | +``kick.com/api/search?searched_word=…`` retourne pour chaque chaîne : slug, | |
| 13 | +abonnés, bio, photo de profil. ``kick.com/api/v2/channels/{slug}`` ajoute le | |
| 14 | +badge vérifié et surtout les LIENS SOCIAUX que le créateur a lui-même remplis | |
| 15 | +dans son profil (instagram/twitter/youtube/tiktok/facebook/discord) → signal | |
| 16 | +cross_link (0.90), la meilleure matière première du rattachement (§12.1). | |
| 17 | + | |
| 18 | +Filtre conservateur : marqueur québécois OBLIGATOIRE dans le pseudo, le slug | |
| 19 | +ou la bio (§7/§15). La fiche v2 n'est demandée QUE pour les chaînes retenues | |
| 20 | +(économie Scrapfly, §10 — chaque requête passe par l'ASP anti-bot). | |
| 21 | +""" | |
| 22 | +from __future__ import annotations | |
| 23 | + | |
| 24 | +import json | |
| 25 | +import sys | |
| 26 | + | |
| 27 | +from ..identity import account | |
| 28 | +from ..normalize import platform_from_url, slugify | |
| 29 | +from ..schema import Creator | |
| 30 | +from .base import BaseConnector | |
| 31 | +from .youtube_recherche import is_quebec | |
| 32 | + | |
| 33 | +SEARCH_URL = "https://kick.com/api/search?searched_word={term}" | |
| 34 | +CHANNEL_URL = "https://kick.com/api/v2/channels/{slug}" | |
| 35 | + | |
| 36 | +SEARCH_TERMS = [ | |
| 37 | + "quebec", "quebecois", "quebecoise", "queb", "montreal", "mtl", | |
| 38 | + "saguenay", "gaspesie", "mauricie", "estrie", "outaouais", "abitibi", | |
| 39 | + "gatineau", "sherbrooke", "levis", "longueuil", "rimouski", "chicoutimi", | |
| 40 | + "trois-rivieres", "drummondville", "lanaudiere", "laurentides", | |
| 41 | + "monteregie", "beauce", "charlevoix", "riv-nord", "rive-sud", | |
| 42 | +] | |
| 43 | + | |
| 44 | +# clés du profil v2 → plateformes §6.2 (liens auto-déclarés par le créateur) | |
| 45 | +_SOCIAL_KEYS = ("instagram", "twitter", "youtube", "tiktok", "facebook", | |
| 46 | + "discord") | |
| 47 | + | |
| 48 | + | |
| 49 | +class KickDecouverteConnector(BaseConnector): | |
| 50 | + source_id = "kick-decouverte" | |
| 51 | + kind = "discovery" | |
| 52 | + request_delay = 1.5 | |
| 53 | + max_details = 120 # fiches v2 par passage (budget Scrapfly, §10) | |
| 54 | + | |
| 55 | + def __init__(self) -> None: | |
| 56 | + super().__init__() | |
| 57 | + self.errors = 0 | |
| 58 | + | |
| 59 | + def _json(self, url: str) -> dict | list | None: | |
| 60 | + """GET via Scrapfly ASP (sans render_js — l'API répond en JSON).""" | |
| 61 | + result = self.scrapfly(url, render_js=False, asp=True) | |
| 62 | + if (result.get("status_code") or 0) != 200: | |
| 63 | + return None | |
| 64 | + try: | |
| 65 | + return json.loads(result.get("content") or "") | |
| 66 | + except Exception: | |
| 67 | + return None | |
| 68 | + | |
| 69 | + def _socials(self, user: dict) -> list: | |
| 70 | + """Liens sociaux auto-déclarés du profil v2 → comptes cross_link.""" | |
| 71 | + accounts = [] | |
| 72 | + for key in _SOCIAL_KEYS: | |
| 73 | + raw = (user.get(key) or "").strip() | |
| 74 | + if not raw: | |
| 75 | + continue | |
| 76 | + # le champ contient tantôt une URL, tantôt un simple handle | |
| 77 | + if "://" in raw or "." in raw.split("/")[0]: | |
| 78 | + parsed = platform_from_url(raw) | |
| 79 | + if parsed: | |
| 80 | + accounts.append(account(parsed[0], parsed[1], "cross_link")) | |
| 81 | + else: | |
| 82 | + platform = "x" if key == "twitter" else key | |
| 83 | + accounts.append(account(platform, raw, "cross_link")) | |
| 84 | + return accounts | |
| 85 | + | |
| 86 | + def fetch(self) -> list[Creator]: | |
| 87 | + # 1) recherche par termes QC → candidats (slug, bio, abonnés, avatar) | |
| 88 | + candidates: dict[str, dict] = {} | |
| 89 | + for term in SEARCH_TERMS: | |
| 90 | + try: | |
| 91 | + data = self._json(SEARCH_URL.format(term=term)) | |
| 92 | + except Exception: | |
| 93 | + self.errors += 1 | |
| 94 | + continue | |
| 95 | + for ch in (data or {}).get("channels") or []: | |
| 96 | + slug = (ch.get("slug") or "").strip().lower() | |
| 97 | + user = ch.get("user") or {} | |
| 98 | + name = (user.get("username") or slug).strip() | |
| 99 | + bio = (user.get("bio") or "").strip() | |
| 100 | + if not slug or slug in candidates or ch.get("is_banned"): | |
| 101 | + continue | |
| 102 | + # filtre conservateur : marqueur QC requis (pseudo/slug/bio) | |
| 103 | + if not is_quebec(f"{name} {slug} {bio}"): | |
| 104 | + continue | |
| 105 | + candidates[slug] = { | |
| 106 | + "name": name, "bio": bio, | |
| 107 | + "followers": ch.get("followers_count"), | |
| 108 | + "avatar": user.get("profilePic") or user.get("profile_pic"), | |
| 109 | + } | |
| 110 | + # 2) fiche v2 pour les retenus → badge + liens sociaux auto-déclarés | |
| 111 | + creators: list[Creator] = [] | |
| 112 | + for slug, cand in list(candidates.items())[:self.max_details]: | |
| 113 | + verified, socials = None, [] | |
| 114 | + try: | |
| 115 | + detail = self._json(CHANNEL_URL.format(slug=slug)) | |
| 116 | + except Exception: | |
| 117 | + self.errors += 1 | |
| 118 | + detail = None | |
| 119 | + if isinstance(detail, dict): | |
| 120 | + verified = bool(detail.get("verified")) or None | |
| 121 | + user = detail.get("user") or {} | |
| 122 | + socials = self._socials(user) | |
| 123 | + cand["bio"] = (user.get("bio") or cand["bio"] or "").strip() | |
| 124 | + cand["avatar"] = user.get("profile_pic") or cand["avatar"] | |
| 125 | + if detail.get("followers_count") is not None: | |
| 126 | + cand["followers"] = detail["followers_count"] | |
| 127 | + acc = account("kick", slug, "profil_source", | |
| 128 | + followers=cand["followers"], verified=verified) | |
| 129 | + avatar = cand.get("avatar") or "" | |
| 130 | + creators.append(Creator( | |
| 131 | + source=self.source_id, | |
| 132 | + external_id=slugify(cand["name"]), | |
| 133 | + display_name=cand["name"], | |
| 134 | + bio=(cand["bio"] or "")[:1200], | |
| 135 | + niches=["gaming"], | |
| 136 | + creator_type="streamer", | |
| 137 | + primary_platform="kick", | |
| 138 | + avatar_url=avatar if avatar.startswith("http") else None, | |
| 139 | + platforms=[acc, *socials], | |
| 140 | + source_ids=[f"{self.source_id}:{slug}"], | |
| 141 | + )) | |
| 142 | + dropped = len(candidates) - min(len(candidates), self.max_details) | |
| 143 | + if dropped > 0: | |
| 144 | + print(f"[crea-ka] kick-decouverte : {dropped} candidat(s) au-delà " | |
| 145 | + f"du budget v2 ({self.max_details}) — repris au prochain " | |
| 146 | + f"passage", file=sys.stderr) | |
| 147 | + return creators | |
added
creaka/connectors/region_bio.py
+166 −0
@@ -0,0 +1,166 @@ | ||
| 1 | +# ============================================================================== | |
| 2 | +# Author: Simon-Pierre Boucher <contact@spboucher.ai> | |
| 3 | +# File: creaka/connectors/region_bio.py | |
| 4 | +# Desc: Connecteur ENRICHISSEMENT — région/ville depuis la localisation | |
| 5 | +# DÉCLARÉE dans la bio publique du créateur (« humoriste de | |
| 6 | +# Sherbrooke », « based in Montreal », « vlogueuse montréalaise »). | |
| 7 | +# Mode d'accès : AUCUNE requête (relit les bios déjà en base, comme | |
| 8 | +# bio-liens). Palier 1 (§9). Vague 4. | |
| 9 | +# ============================================================================== | |
| 10 | +"""Région/ville depuis la bio publique — prudence maximale (§7/§15). | |
| 11 | + | |
| 12 | +On n'infère JAMAIS : on ne retient une ville que si le créateur la déclare | |
| 13 | +lui-même dans sa bio avec une tournure locative sans ambiguïté (« de X », | |
| 14 | +« basé à X », « from X », gentilé comme « montréalais »). Villes au nom | |
| 15 | +piégeux exclues (Alma, Waterloo, Varennes… : prénoms, homonymes hors Québec, | |
| 16 | +particules de noms de famille). Si la bio mentionne des villes de RÉGIONS | |
| 17 | +différentes, on s'abstient (ambigu). Ne remplit que les champs VIDES. | |
| 18 | +""" | |
| 19 | +from __future__ import annotations | |
| 20 | + | |
| 21 | +import re | |
| 22 | + | |
| 23 | +from ..normalize import strip_accents | |
| 24 | +from ..schema import Creator | |
| 25 | +from .base import BaseConnector | |
| 26 | + | |
| 27 | +# villes SÛRES (clé sans accent) → (ville affichée, région §7). | |
| 28 | +# ⚠ liste volontairement restrictive : pas d'Alma (prénom), pas de Waterloo | |
| 29 | +# (Ontario), pas de Varennes (particule de nom), pas d'Anjou (France/quartier). | |
| 30 | +_SAFE_CITIES: dict[str, tuple[str, str]] = { | |
| 31 | + "montreal": ("Montréal", "Montréal"), | |
| 32 | + "verdun": ("Verdun", "Montréal"), | |
| 33 | + "lachine": ("Lachine", "Montréal"), | |
| 34 | + "outremont": ("Outremont", "Montréal"), | |
| 35 | + "westmount": ("Westmount", "Montréal"), | |
| 36 | + "ville de quebec": ("Québec", "Capitale-Nationale"), | |
| 37 | + "quebec city": ("Québec", "Capitale-Nationale"), | |
| 38 | + "baie-saint-paul": ("Baie-Saint-Paul", "Capitale-Nationale"), | |
| 39 | + "la malbaie": ("La Malbaie", "Capitale-Nationale"), | |
| 40 | + "laval": ("Laval", "Laval"), | |
| 41 | + "gatineau": ("Gatineau", "Outaouais"), | |
| 42 | + "sherbrooke": ("Sherbrooke", "Estrie"), | |
| 43 | + "magog": ("Magog", "Estrie"), | |
| 44 | + "granby": ("Granby", "Estrie"), | |
| 45 | + "trois-rivieres": ("Trois-Rivières", "Mauricie"), | |
| 46 | + "shawinigan": ("Shawinigan", "Mauricie"), | |
| 47 | + "la tuque": ("La Tuque", "Mauricie"), | |
| 48 | + "saguenay": ("Saguenay", "Saguenay–Lac-Saint-Jean"), | |
| 49 | + "chicoutimi": ("Chicoutimi", "Saguenay–Lac-Saint-Jean"), | |
| 50 | + "jonquiere": ("Jonquière", "Saguenay–Lac-Saint-Jean"), | |
| 51 | + "roberval": ("Roberval", "Saguenay–Lac-Saint-Jean"), | |
| 52 | + "dolbeau-mistassini": ("Dolbeau-Mistassini", "Saguenay–Lac-Saint-Jean"), | |
| 53 | + "rimouski": ("Rimouski", "Bas-Saint-Laurent"), | |
| 54 | + "riviere-du-loup": ("Rivière-du-Loup", "Bas-Saint-Laurent"), | |
| 55 | + "matane": ("Matane", "Bas-Saint-Laurent"), | |
| 56 | + "amqui": ("Amqui", "Bas-Saint-Laurent"), | |
| 57 | + "gaspe": ("Gaspé", "Gaspésie–Îles-de-la-Madeleine"), | |
| 58 | + "chandler": ("Chandler", "Gaspésie–Îles-de-la-Madeleine"), | |
| 59 | + "iles-de-la-madeleine": ("Îles-de-la-Madeleine", | |
| 60 | + "Gaspésie–Îles-de-la-Madeleine"), | |
| 61 | + "rouyn-noranda": ("Rouyn-Noranda", "Abitibi-Témiscamingue"), | |
| 62 | + "val-d'or": ("Val-d'Or", "Abitibi-Témiscamingue"), | |
| 63 | + "amos": ("Amos", "Abitibi-Témiscamingue"), | |
| 64 | + "la sarre": ("La Sarre", "Abitibi-Témiscamingue"), | |
| 65 | + "sept-iles": ("Sept-Îles", "Côte-Nord"), | |
| 66 | + "baie-comeau": ("Baie-Comeau", "Côte-Nord"), | |
| 67 | + "havre-saint-pierre": ("Havre-Saint-Pierre", "Côte-Nord"), | |
| 68 | + "chibougamau": ("Chibougamau", "Nord-du-Québec"), | |
| 69 | + "levis": ("Lévis", "Chaudière-Appalaches"), | |
| 70 | + "thetford mines": ("Thetford Mines", "Chaudière-Appalaches"), | |
| 71 | + "montmagny": ("Montmagny", "Chaudière-Appalaches"), | |
| 72 | + "saint-georges": ("Saint-Georges", "Chaudière-Appalaches"), | |
| 73 | + "drummondville": ("Drummondville", "Centre-du-Québec"), | |
| 74 | + "victoriaville": ("Victoriaville", "Centre-du-Québec"), | |
| 75 | + "longueuil": ("Longueuil", "Montérégie"), | |
| 76 | + "brossard": ("Brossard", "Montérégie"), | |
| 77 | + "boucherville": ("Boucherville", "Montérégie"), | |
| 78 | + "chambly": ("Chambly", "Montérégie"), | |
| 79 | + "beloeil": ("Belœil", "Montérégie"), | |
| 80 | + "sainte-julie": ("Sainte-Julie", "Montérégie"), | |
| 81 | + "saint-hyacinthe": ("Saint-Hyacinthe", "Montérégie"), | |
| 82 | + "sorel-tracy": ("Sorel-Tracy", "Montérégie"), | |
| 83 | + "chateauguay": ("Châteauguay", "Montérégie"), | |
| 84 | + "saint-jean-sur-richelieu": ("Saint-Jean-sur-Richelieu", "Montérégie"), | |
| 85 | + "salaberry-de-valleyfield": ("Salaberry-de-Valleyfield", "Montérégie"), | |
| 86 | + "vaudreuil-dorion": ("Vaudreuil-Dorion", "Montérégie"), | |
| 87 | + "cowansville": ("Cowansville", "Montérégie"), | |
| 88 | + "terrebonne": ("Terrebonne", "Lanaudière"), | |
| 89 | + "repentigny": ("Repentigny", "Lanaudière"), | |
| 90 | + "mascouche": ("Mascouche", "Lanaudière"), | |
| 91 | + "joliette": ("Joliette", "Lanaudière"), | |
| 92 | + "rawdon": ("Rawdon", "Lanaudière"), | |
| 93 | + "blainville": ("Blainville", "Laurentides"), | |
| 94 | + "boisbriand": ("Boisbriand", "Laurentides"), | |
| 95 | + "mirabel": ("Mirabel", "Laurentides"), | |
| 96 | + "saint-jerome": ("Saint-Jérôme", "Laurentides"), | |
| 97 | + "sainte-therese": ("Sainte-Thérèse", "Laurentides"), | |
| 98 | + "sainte-adele": ("Sainte-Adèle", "Laurentides"), | |
| 99 | + "sainte-agathe-des-monts": ("Sainte-Agathe-des-Monts", "Laurentides"), | |
| 100 | + "mont-laurier": ("Mont-Laurier", "Laurentides"), | |
| 101 | + "mont-tremblant": ("Mont-Tremblant", "Laurentides"), | |
| 102 | + "lachute": ("Lachute", "Laurentides"), | |
| 103 | +} | |
| 104 | + | |
| 105 | +# gentilés sans ambiguïté → ville (déclaration d'appartenance dans la bio) | |
| 106 | +_DEMONYMS: dict[str, str] = { | |
| 107 | + "montrealais": "montreal", "montrealaise": "montreal", | |
| 108 | + "trifluvien": "trois-rivieres", "trifluvienne": "trois-rivieres", | |
| 109 | + "sherbrookois": "sherbrooke", "sherbrookoise": "sherbrooke", | |
| 110 | + "gatinois": "gatineau", "gatinoise": "gatineau", | |
| 111 | + "lavallois": "laval", "lavalloise": "laval", | |
| 112 | + "longueuillois": "longueuil", "longueuilloise": "longueuil", | |
| 113 | + "rimouskois": "rimouski", "rimouskoise": "rimouski", | |
| 114 | + "gaspesien": "gaspe", "gaspesienne": "gaspe", | |
| 115 | +} | |
| 116 | + | |
| 117 | +# tournure locative OBLIGATOIRE devant le nom de ville : c'est elle qui fait | |
| 118 | +# de la mention une DÉCLARATION (« de Sherbrooke ») et non une anecdote | |
| 119 | +# (« j'ai visité Sherbrooke ») | |
| 120 | +_LOCATIVE = (r"(?:de|d'|du|a|au|from|in|based in|base(?:e)? a|situe(?:e)? a|" | |
| 121 | + r"originaire de|native de|natif de|vit a|vis a|habite a|" | |
| 122 | + r"direct(?:ement)? de|region de|coin de|ici a)") | |
| 123 | + | |
| 124 | +_CITY_RE = re.compile( | |
| 125 | + r"(?<![\w-])" + _LOCATIVE + r"\s+(?:la\s+|le\s+|l')?(" + | |
| 126 | + "|".join(sorted(map(re.escape, _SAFE_CITIES), key=len, reverse=True)) + | |
| 127 | + r")(?![\w-])") | |
| 128 | +_DEMONYM_RE = re.compile( | |
| 129 | + r"(?<![\w-])(" + "|".join(sorted(_DEMONYMS, key=len, reverse=True)) + | |
| 130 | + r")(?![\w-])") | |
| 131 | + | |
| 132 | + | |
| 133 | +def declared_cities(text: str) -> set[str]: | |
| 134 | + """Bio publique → clés de villes DÉCLARÉES (tournure locative ou gentilé).""" | |
| 135 | + blob = strip_accents(text or "").lower() | |
| 136 | + keys = set(_CITY_RE.findall(blob)) | |
| 137 | + keys |= {_DEMONYMS[d] for d in _DEMONYM_RE.findall(blob)} | |
| 138 | + return keys | |
| 139 | + | |
| 140 | + | |
| 141 | +class RegionBioConnector(BaseConnector): | |
| 142 | + source_id = "region-bio" | |
| 143 | + kind = "enrichment" | |
| 144 | + request_delay = 0.0 # aucune requête réseau | |
| 145 | + | |
| 146 | + def enrich(self, creators: list[Creator]) -> list[Creator]: | |
| 147 | + enriched: list[Creator] = [] | |
| 148 | + for cr in creators: | |
| 149 | + if cr.region and cr.city: | |
| 150 | + continue | |
| 151 | + keys = declared_cities(cr.bio) | |
| 152 | + if not keys: | |
| 153 | + continue | |
| 154 | + regions = {_SAFE_CITIES[k][1] for k in keys} | |
| 155 | + if len(regions) != 1: | |
| 156 | + continue # villes de régions différentes → ambigu, abstention | |
| 157 | + changed = False | |
| 158 | + if not cr.region: | |
| 159 | + cr.region = next(iter(regions)) | |
| 160 | + changed = True | |
| 161 | + if not cr.city and len(keys) == 1: | |
| 162 | + cr.city = _SAFE_CITIES[next(iter(keys))][0] | |
| 163 | + changed = True | |
| 164 | + if changed: | |
| 165 | + enriched.append(cr) | |
| 166 | + return enriched | |
added
creaka/connectors/twitch_decouverte.py
+206 −0
@@ -0,0 +1,206 @@ | ||
| 1 | +# ============================================================================== | |
| 2 | +# Author: Simon-Pierre Boucher <contact@spboucher.ai> | |
| 3 | +# File: creaka/connectors/twitch_decouverte.py | |
| 4 | +# Desc: Connecteur DÉCOUVERTE — streamers Twitch québécois via l'API GQL | |
| 5 | +# publique du site officiel (Client-ID public, sans clé) : recherche | |
| 6 | +# de chaînes par termes QC + répertoire des diffusions en français. | |
| 7 | +# Palier 3 (§9). Filtre conservateur : marqueur québécois OBLIGATOIRE | |
| 8 | +# dans le nom, la bio ou le titre du stream. | |
| 9 | +# ============================================================================== | |
| 10 | +"""Découverte des streamers Twitch québécois — sans clé. | |
| 11 | + | |
| 12 | +Deux voies, mêmes conventions que l'enrichisseur `twitch` (vague 3) : | |
| 13 | + | |
| 14 | +1. ``searchFor`` (la recherche du site officiel) sur une liste de termes | |
| 15 | + québécois (province, régions, villes) → chaînes dont le profil PUBLIC | |
| 16 | + mentionne le Québec, avec abonnés, bio, avatar, statut partenaire ; | |
| 17 | +2. le répertoire des diffusions EN DIRECT en français (``streams``, | |
| 18 | + languages: [FR]) → longue traîne de streamers QC actifs, paginé ; la | |
| 19 | + couverture s'accumule à chaque passage (qui est en direct change chaque | |
| 20 | + jour, comme youtube-recherche). | |
| 21 | + | |
| 22 | +On ne crée une fiche QUE si un marqueur québécois figure dans le nom, la | |
| 23 | +description du profil ou le titre du stream (jamais d'inférence, §7/§15). | |
| 24 | +Le compte Twitch est le compte SOURCE de la fiche → signal profil_source | |
| 25 | +(0.98) ; l'enrichissement rattache ensuite ses autres plateformes. | |
| 26 | +""" | |
| 27 | +from __future__ import annotations | |
| 28 | + | |
| 29 | +import json | |
| 30 | +import subprocess | |
| 31 | +import sys | |
| 32 | +import time | |
| 33 | + | |
| 34 | +from ..identity import account | |
| 35 | +from ..normalize import slugify | |
| 36 | +from ..schema import Creator | |
| 37 | +from .base import USER_AGENT, BaseConnector | |
| 38 | +from .twitch import GQL_URL, WEB_CLIENT_ID | |
| 39 | +from .youtube_recherche import is_quebec | |
| 40 | + | |
| 41 | +# champs publics du profil (§15) — mêmes que l'enrichisseur twitch | |
| 42 | +_USER_FIELDS = ("login displayName description createdAt " | |
| 43 | + "followers { totalCount } profileImageURL(width: 300) " | |
| 44 | + "roles { isPartner isAffiliate } " | |
| 45 | + "lastBroadcast { startedAt game { displayName } }") | |
| 46 | + | |
| 47 | +# termes de recherche québécois (province, régions, villes, scène locale) | |
| 48 | +SEARCH_TERMS = [ | |
| 49 | + "québec", "québécois", "québécoise", "queb", "montréal", "mtl", | |
| 50 | + "ville de québec", "rive-sud", "rive-nord", "saguenay", "gaspésie", | |
| 51 | + "mauricie", "estrie", "outaouais", "abitibi", "témiscamingue", | |
| 52 | + "lanaudière", "laurentides", "montérégie", "charlevoix", "beauce", | |
| 53 | + "côte-nord", "bas-saint-laurent", "gatineau", "sherbrooke", "laval", | |
| 54 | + "longueuil", "lévis", "trois-rivières", "chicoutimi", "rimouski", | |
| 55 | + "drummondville", "granby", "victoriaville", "joliette", "terrebonne", | |
| 56 | + "repentigny", "brossard", "shawinigan", "rouyn-noranda", "alma", | |
| 57 | + "streamer québécois", "gamer québécois", "twitch québec", | |
| 58 | +] | |
| 59 | + | |
| 60 | +# jeu du stream → niche §6.1 (défaut : gaming — c'est Twitch) | |
| 61 | +_GAME_NICHE = { | |
| 62 | + "Just Chatting": "lifestyle", "Music": "musique", "Art": "arts", | |
| 63 | + "Food & Drink": "cuisine", "Sports": "sport-fitness", | |
| 64 | + "ASMR": "lifestyle", "Talk Shows & Podcasts": "actualite-opinion", | |
| 65 | + "Software and Game Development": "tech", "Science & Technology": "tech", | |
| 66 | + "Fitness & Health": "sport-fitness", "Travel & Outdoors": "plein-air", | |
| 67 | + "Makers & Crafting": "arts", "Beauty & Body Art": "beaute", | |
| 68 | + "Politics": "actualite-opinion", "DJs": "musique", | |
| 69 | +} | |
| 70 | + | |
| 71 | + | |
| 72 | +class TwitchDecouverteConnector(BaseConnector): | |
| 73 | + source_id = "twitch-decouverte" | |
| 74 | + kind = "discovery" | |
| 75 | + request_delay = 1.0 | |
| 76 | + search_limit = 25 # chaînes par page de recherche | |
| 77 | + search_pages = 4 # pages par terme (cursor searchFor) | |
| 78 | + stream_pages = 20 # pages du répertoire FR (30 streams/page) | |
| 79 | + | |
| 80 | + def __init__(self) -> None: | |
| 81 | + super().__init__() | |
| 82 | + self.errors = 0 | |
| 83 | + | |
| 84 | + # -- transport GQL (repli curl-binaire, même pattern que twitch.py) -------- | |
| 85 | + def _gql(self, query: str) -> dict: | |
| 86 | + payload = {"query": query} | |
| 87 | + try: | |
| 88 | + resp = self.post(GQL_URL, json=payload, | |
| 89 | + headers={"Client-Id": WEB_CLIENT_ID}) | |
| 90 | + return resp.json() | |
| 91 | + except Exception: | |
| 92 | + pass # 4xx/blocage TLS → repli curl | |
| 93 | + self._throttle() | |
| 94 | + try: | |
| 95 | + proc = subprocess.run( | |
| 96 | + ["curl", "-sS", "--fail", "--max-time", str(self.timeout), | |
| 97 | + "-A", USER_AGENT, "-H", f"Client-Id: {WEB_CLIENT_ID}", | |
| 98 | + "-H", "Content-Type: application/json", | |
| 99 | + "-d", json.dumps(payload), GQL_URL], | |
| 100 | + capture_output=True, text=True, timeout=self.timeout + 5) | |
| 101 | + finally: | |
| 102 | + self._last_request = time.time() | |
| 103 | + if proc.returncode != 0: | |
| 104 | + raise RuntimeError(f"curl {proc.returncode}: gql.twitch.tv") | |
| 105 | + return json.loads(proc.stdout) | |
| 106 | + | |
| 107 | + # -- fabrication d'une fiche ------------------------------------------------- | |
| 108 | + def _collect(self, user: dict, context: str, seen: set[str], | |
| 109 | + creators: list[Creator], niche: str = "gaming") -> None: | |
| 110 | + login = (user.get("login") or "").strip().lower() | |
| 111 | + name = (user.get("displayName") or login).strip() | |
| 112 | + bio = (user.get("description") or "").strip() | |
| 113 | + if not login or login in seen: | |
| 114 | + return | |
| 115 | + # filtre conservateur : marqueur QC dans nom + bio + titre du stream | |
| 116 | + if not is_quebec(f"{name} {bio} {context}"): | |
| 117 | + return | |
| 118 | + seen.add(login) | |
| 119 | + last = user.get("lastBroadcast") or {} | |
| 120 | + roles = user.get("roles") or {} | |
| 121 | + game = (last.get("game") or {}).get("displayName") | |
| 122 | + acc = account("twitch", login, "profil_source", | |
| 123 | + followers=(user.get("followers") or {}).get("totalCount"), | |
| 124 | + verified=bool(roles.get("isPartner")) or None) | |
| 125 | + acc.metrics = {k: v for k, v in { | |
| 126 | + "affiliate": bool(roles.get("isAffiliate")) or None, | |
| 127 | + "last_stream": last.get("startedAt"), | |
| 128 | + "game": game, | |
| 129 | + }.items() if v} | |
| 130 | + avatar = user.get("profileImageURL") or "" | |
| 131 | + creators.append(Creator( | |
| 132 | + source=self.source_id, | |
| 133 | + external_id=slugify(name), | |
| 134 | + display_name=name, | |
| 135 | + bio=bio[:1200], | |
| 136 | + niches=[_GAME_NICHE.get(game or "", niche)], | |
| 137 | + creator_type="streamer", | |
| 138 | + primary_platform="twitch", | |
| 139 | + avatar_url=avatar if avatar.startswith("http") else None, | |
| 140 | + platforms=[acc], | |
| 141 | + source_ids=[f"{self.source_id}:{login}"], | |
| 142 | + )) | |
| 143 | + | |
| 144 | + # -- voie 1 : recherche de chaînes par termes QC ----------------------------- | |
| 145 | + def _search(self, seen: set[str], creators: list[Creator]) -> None: | |
| 146 | + for term in SEARCH_TERMS: | |
| 147 | + cursor = "" | |
| 148 | + for _page in range(self.search_pages): | |
| 149 | + cur = f', cursor: {json.dumps(cursor)}' if cursor else "" | |
| 150 | + q = ("query { searchFor(userQuery: %s, platform: \"web\", " | |
| 151 | + "target: {index: CHANNEL, limit: %d%s}) " | |
| 152 | + "{ channels { cursor edges { item { ... on User { %s } } } } } }" | |
| 153 | + % (json.dumps(term), self.search_limit, cur, _USER_FIELDS)) | |
| 154 | + try: | |
| 155 | + data = self._gql(q) | |
| 156 | + channels = ((data.get("data") or {}).get("searchFor") | |
| 157 | + or {}).get("channels") or {} | |
| 158 | + except Exception: | |
| 159 | + self.errors += 1 | |
| 160 | + break | |
| 161 | + edges = channels.get("edges") or [] | |
| 162 | + for edge in edges: | |
| 163 | + user = edge.get("item") or {} | |
| 164 | + if user.get("login"): | |
| 165 | + self._collect(user, "", seen, creators) | |
| 166 | + cursor = channels.get("cursor") or "" | |
| 167 | + if not cursor or not edges: | |
| 168 | + break | |
| 169 | + | |
| 170 | + # -- voie 2 : répertoire des diffusions en français (longue traîne) ---------- | |
| 171 | + def _directory(self, seen: set[str], creators: list[Creator]) -> None: | |
| 172 | + after = "" | |
| 173 | + for _page in range(self.stream_pages): | |
| 174 | + aft = f', after: {json.dumps(after)}' if after else "" | |
| 175 | + q = ("query { streams(first: 30%s, options: {languages: [FR]}) " | |
| 176 | + "{ edges { cursor node { title broadcaster { %s } } } " | |
| 177 | + "pageInfo { hasNextPage } } }" % (aft, _USER_FIELDS)) | |
| 178 | + try: | |
| 179 | + data = self._gql(q) | |
| 180 | + streams = (data.get("data") or {}).get("streams") or {} | |
| 181 | + except Exception: | |
| 182 | + self.errors += 1 | |
| 183 | + return | |
| 184 | + edges = streams.get("edges") or [] | |
| 185 | + for edge in edges: | |
| 186 | + node = edge.get("node") or {} | |
| 187 | + user = node.get("broadcaster") or {} | |
| 188 | + if user.get("login"): | |
| 189 | + self._collect(user, node.get("title") or "", seen, creators) | |
| 190 | + if not edges or not (streams.get("pageInfo") or {}).get("hasNextPage"): | |
| 191 | + return | |
| 192 | + after = edges[-1].get("cursor") or "" | |
| 193 | + if not after: | |
| 194 | + return | |
| 195 | + | |
| 196 | + def fetch(self) -> list[Creator]: | |
| 197 | + creators: list[Creator] = [] | |
| 198 | + seen: set[str] = set() | |
| 199 | + self._search(seen, creators) | |
| 200 | + try: | |
| 201 | + self._directory(seen, creators) | |
| 202 | + except Exception as exc: # la voie 2 ne bloque jamais la voie 1 | |
| 203 | + self.errors += 1 | |
| 204 | + print(f"[crea-ka] ⚠ twitch-decouverte : répertoire FR en échec : " | |
| 205 | + f"{exc}", file=sys.stderr) | |
| 206 | + return creators | |
modified
creaka/connectors/wikipedia_qc.py
+9 −0
@@ -52,6 +52,15 @@ CATEGORIES: list[tuple[str, str, bool, str, str]] = [ | ||
| 52 | 52 | ("en", "Category:Canadian Twitch (service) streamers", True, "gaming", |
| 53 | 53 | "streamer"), |
| 54 | 54 | ("en", "Category:Canadian TikTokers", True, "lifestyle", "createur-tiktok"), |
| 55 | + # vague 4 — catégories supplémentaires vérifiées (2026-08-18) | |
| 56 | + ("fr", "Catégorie:Blogueuse québécoise", False, "actualite-opinion", | |
| 57 | + "createur-ecrit"), | |
| 58 | + ("en", "Category:Canadian Internet celebrities", True, "lifestyle", | |
| 59 | + "influenceur"), | |
| 60 | + ("en", "Category:Canadian women podcasters", True, "actualite-opinion", | |
| 61 | + "podcasteur"), | |
| 62 | + ("en", "Category:Canadian video bloggers", True, "lifestyle", "youtubeur"), | |
| 63 | + ("en", "Category:Canadian gaming YouTubers", True, "gaming", "youtubeur"), | |
| 55 | 64 | ] |
| 56 | 65 | |
| 57 | 66 | # propriétés Wikidata → plateformes §6.2 (handles curés par la communauté) |
modified
creaka/connectors/youtube_recherche.py
+101 −2
@@ -116,6 +116,34 @@ QUERIES: list[tuple[str, str]] = [ | ||
| 116 | 116 | ("urbex québec", "autre"), ("faits divers québec", "actualite-opinion"), |
| 117 | 117 | ("politique québécoise", "actualite-opinion"), |
| 118 | 118 | ("nouvelles québec", "actualite-opinion"), |
| 119 | + # créateurs anglophones/bilingues (les marqueurs montreal/mtl/quebec | |
| 120 | + # figurent dans _QC_MARKERS — même filtre conservateur) | |
| 121 | + ("montreal vlog", "lifestyle"), ("montreal vlogger", "lifestyle"), | |
| 122 | + ("montreal youtuber", "lifestyle"), ("living in montreal", "lifestyle"), | |
| 123 | + ("montreal food", "bouffe-resto"), ("montreal foodie", "bouffe-resto"), | |
| 124 | + ("montreal restaurants", "bouffe-resto"), ("montreal cooking", "cuisine"), | |
| 125 | + ("montreal gaming", "gaming"), ("montreal streamer", "gaming"), | |
| 126 | + ("montreal comedy", "humour"), ("montreal standup", "humour"), | |
| 127 | + ("montreal music", "musique"), ("montreal rap", "musique"), | |
| 128 | + ("mtl rap", "musique"), ("montreal producer", "musique"), | |
| 129 | + ("montreal fitness", "sport-fitness"), ("montreal gym", "sport-fitness"), | |
| 130 | + ("montreal makeup", "beaute"), ("montreal beauty", "beaute"), | |
| 131 | + ("montreal fashion", "mode"), ("montreal streetwear", "mode"), | |
| 132 | + ("montreal thrift", "mode"), ("montreal barber", "beaute"), | |
| 133 | + ("montreal tech", "tech"), ("montreal developer", "tech"), | |
| 134 | + ("montreal photography", "arts"), ("montreal artist", "arts"), | |
| 135 | + ("montreal dance", "danse"), ("montreal travel", "voyage"), | |
| 136 | + ("montreal real estate", "finance-affaires"), | |
| 137 | + ("montreal finance", "finance-affaires"), | |
| 138 | + ("montreal podcast", "actualite-opinion"), | |
| 139 | + ("montreal family vlog", "famille-parentalite"), | |
| 140 | + ("quebec city vlog", "lifestyle"), ("quebec city food", "bouffe-resto"), | |
| 141 | + ("quebec gaming", "gaming"), ("quebec outdoors", "plein-air"), | |
| 142 | + ("quebec fishing", "plein-air"), ("quebec hunting", "plein-air"), | |
| 143 | + ("quebec snowboard", "plein-air"), ("quebec skiing", "plein-air"), | |
| 144 | + ("quebec history", "education"), ("learn french quebec", "education"), | |
| 145 | + ("quebec french lessons", "education"), ("anglo montreal", "lifestyle"), | |
| 146 | + ("laval vlogger", "lifestyle"), ("gatineau ottawa vlog", "lifestyle"), | |
| 119 | 147 | ] |
| 120 | 148 | |
| 121 | 149 | # --- longue traîne : villes/MRC × créneaux (nano/micro créateurs locaux) -------- |
@@ -137,7 +165,13 @@ _TOWNS = [ | ||
| 137 | 165 | ] |
| 138 | 166 | _TOWN_THEMES = [("vlog", "lifestyle"), ("youtubeur", "lifestyle"), |
| 139 | 167 | ("gaming", "gaming"), ("chasse pêche", "plein-air"), |
| 140 | − ("humour", "humour")] | |
| 168 | + ("humour", "humour"), | |
| 169 | + # vague 4 : la longue traîne locale couvre aussi la bouffe, la | |
| 170 | + # forme, la beauté, la musique, la famille et les balados | |
| 171 | + ("cuisine", "cuisine"), ("resto", "bouffe-resto"), | |
| 172 | + ("fitness", "sport-fitness"), ("beauté", "beaute"), | |
| 173 | + ("musique", "musique"), ("famille", "famille-parentalite"), | |
| 174 | + ("balado", "actualite-opinion"), ("plein air", "plein-air")] | |
| 141 | 175 | for _t in _TOWNS: |
| 142 | 176 | for _th, _n in _TOWN_THEMES: |
| 143 | 177 | QUERIES.append((f"{_th} {_t}", _n)) |
@@ -189,6 +223,71 @@ _HOBBIES = [ | ||
| 189 | 223 | ("frugal", "finance-affaires"), ("bourse dividendes", "finance-affaires"), |
| 190 | 224 | ("intelligence artificielle", "tech"), ("cybersécurité", "tech"), |
| 191 | 225 | ("impression 3d", "tech"), ("domotique", "tech"), ("drones", "tech"), |
| 226 | + # vague 4 : encore plus de passe-temps, sports, métiers et scènes | |
| 227 | + ("escalade", "sport-fitness"), ("trail", "sport-fitness"), | |
| 228 | + ("triathlon", "sport-fitness"), ("powerlifting", "sport-fitness"), | |
| 229 | + ("arts martiaux", "sport-fitness"), ("jiu-jitsu", "sport-fitness"), | |
| 230 | + ("karaté", "sport-fitness"), ("boxe thaï", "sport-fitness"), | |
| 231 | + ("patinage", "sport-fitness"), ("ringuette", "sport-fitness"), | |
| 232 | + ("curling", "sport-fitness"), ("cheerleading", "sport-fitness"), | |
| 233 | + ("gymnastique", "sport-fitness"), ("natation", "sport-fitness"), | |
| 234 | + ("plongée", "plein-air"), ("voile", "plein-air"), | |
| 235 | + ("kayak de mer", "plein-air"), ("canot", "plein-air"), | |
| 236 | + ("raquette", "plein-air"), ("ski de fond", "plein-air"), | |
| 237 | + ("ski hors-piste", "plein-air"), ("escapade", "voyage"), | |
| 238 | + ("roadtrip", "voyage"), ("croisière", "voyage"), | |
| 239 | + ("aquariophilie", "autre"), ("reptiles", "autre"), | |
| 240 | + ("chiens", "autre"), ("chats", "autre"), ("chevaux", "plein-air"), | |
| 241 | + ("équitation", "plein-air"), ("fermette", "plein-air"), | |
| 242 | + ("poules", "plein-air"), ("potager", "plein-air"), | |
| 243 | + ("champignons", "plein-air"), ("mycologie", "plein-air"), | |
| 244 | + ("herboristerie", "sante-mieux-etre"), ("zéro déchet", "lifestyle"), | |
| 245 | + ("autosuffisance", "plein-air"), ("survivalisme", "plein-air"), | |
| 246 | + ("vinyle", "musique"), ("audiophile", "tech"), | |
| 247 | + ("home studio", "musique"), ("beatmaking", "musique"), | |
| 248 | + ("production musicale", "musique"), ("ukulélé", "musique"), | |
| 249 | + ("saxophone", "musique"), ("harmonica", "musique"), | |
| 250 | + ("accordéon", "musique"), ("chant", "musique"), | |
| 251 | + ("billard", "autre"), ("poker", "autre"), ("fléchettes", "autre"), | |
| 252 | + ("airsoft", "autre"), ("paintball", "autre"), | |
| 253 | + ("modélisme", "arts"), ("figurines", "arts"), ("bijoux", "arts"), | |
| 254 | + ("savonnerie", "arts"), ("chandelles", "arts"), | |
| 255 | + ("macramé", "arts"), ("scrapbooking", "arts"), | |
| 256 | + ("philatélie", "education"), ("numismatique", "education"), | |
| 257 | + ("antiquités", "autre"), ("brocante", "autre"), | |
| 258 | + ("horlogerie", "arts"), ("restauration meubles", "arts"), | |
| 259 | + ("ébénisterie", "arts"), ("charpenterie", "autre"), | |
| 260 | + ("maçonnerie", "autre"), ("toiture", "autre"), | |
| 261 | + ("mécanique diesel", "autre"), ("carrosserie", "autre"), | |
| 262 | + ("détailing", "autre"), ("camion lourd", "autre"), | |
| 263 | + ("agriculture laitière", "plein-air"), ("grandes cultures", "plein-air"), | |
| 264 | + ("boucherie", "cuisine"), ("charcuterie", "cuisine"), | |
| 265 | + ("fermentation", "cuisine"), ("kombucha", "cuisine"), | |
| 266 | + ("cidre", "bouffe-resto"), ("hydromel", "bouffe-resto"), | |
| 267 | + ("distillerie", "bouffe-resto"), ("torréfaction", "bouffe-resto"), | |
| 268 | + ("sommelier", "bouffe-resto"), ("cocktails", "bouffe-resto"), | |
| 269 | + ("orthopédagogie", "education"), ("orthophonie", "education"), | |
| 270 | + ("tdah", "sante-mieux-etre"), ("autisme", "sante-mieux-etre"), | |
| 271 | + ("kinésiologie", "sante-mieux-etre"), ("chiropratique", "sante-mieux-etre"), | |
| 272 | + ("dermatologie", "beaute"), ("nutritionniste", "sante-mieux-etre"), | |
| 273 | + ("sage-femme", "famille-parentalite"), ("doula", "famille-parentalite"), | |
| 274 | + ("homeschooling", "famille-parentalite"), ("école à la maison", "famille-parentalite"), | |
| 275 | + ("astuces ménage", "lifestyle"), ("décoration", "lifestyle"), | |
| 276 | + ("design intérieur", "lifestyle"), ("aménagement paysager", "autre"), | |
| 277 | + ("piscine", "autre"), ("spa", "autre"), | |
| 278 | + ("courtier hypothécaire", "finance-affaires"), | |
| 279 | + ("planificateur financier", "finance-affaires"), | |
| 280 | + ("assurance", "finance-affaires"), ("fiscalité", "finance-affaires"), | |
| 281 | + ("dropshipping", "finance-affaires"), ("commerce en ligne", "finance-affaires"), | |
| 282 | + ("marketing numérique", "finance-affaires"), ("freelance", "finance-affaires"), | |
| 283 | + ("linguistique", "education"), ("vulgarisation", "education"), | |
| 284 | + ("archéologie", "education"), ("géographie", "education"), | |
| 285 | + ("météo", "education"), ("aviation", "tech"), | |
| 286 | + ("simulateur de vol", "gaming"), ("trains", "autre"), | |
| 287 | + ("camping-car", "voyage"), ("vr roulotte", "voyage"), | |
| 288 | + ("pêche blanche", "plein-air"), ("trappage", "plein-air"), | |
| 289 | + ("taxidermie", "autre"), ("coutellerie", "arts"), | |
| 290 | + ("armes à feu", "plein-air"), ("tir à l'arc", "plein-air"), | |
| 192 | 291 | ] |
| 193 | 292 | for _h, _n in _HOBBIES: |
| 194 | 293 | QUERIES.append((f"{_h} québec", _n)) |
@@ -275,7 +374,7 @@ class YouTubeRechercheConnector(BaseConnector): | ||
| 275 | 374 | source_id = "youtube-recherche" |
| 276 | 375 | kind = "discovery" |
| 277 | 376 | request_delay = 1.0 |
| 278 | − max_queries = 800 | |
| 377 | + max_queries = 2500 | |
| 279 | 378 | max_pages_per_query = 4 # PROFONDEUR : pages de continuation (~20 chaînes/page) |
| 280 | 379 | |
| 281 | 380 | def _collect(self, channels: list[dict], niche: str, seen: set[str], |
modified
creaka/ingest.py
+1 −1
@@ -32,7 +32,7 @@ from .dedup import dedupe | ||
| 32 | 32 | # tout dernier (il relit les bios enrichies, sans aucune requête) |
| 33 | 33 | ENRICH_ORDER = ["instagram-profil", "tiktok-profil", "youtube", "twitch", |
| 34 | 34 | "x-profil", "balados-rss", "podcastindex", |
| 35 | − "link-in-bio", "bio-liens"] | |
| 35 | + "link-in-bio", "bio-liens", "region-bio"] | |
| 36 | 36 | |
| 37 | 37 | |
| 38 | 38 | def _finalize_batch(creators: list) -> tuple[list, int]: |
modified
data/sources.json
+28 −1
@@ -148,6 +148,33 @@ | ||
| 148 | 148 | "signal_identite": "cross_link (0.90) — le créateur pointe lui-même vers son autre compte", |
| 149 | 149 | "cadence": "quotidienne (watch), en dernier du pipeline", |
| 150 | 150 | "notes": "passe conservatrice §12 : patrons sûrs seulement, cap 5 nouveaux comptes par fiche" |
| 151 | + }, | |
| 152 | + { | |
| 153 | + "id": "twitch-decouverte", | |
| 154 | + "famille": "decouverte", | |
| 155 | + "palier": 3, | |
| 156 | + "acces": "API GQL publique du site officiel de Twitch (Client-ID public web, sans clé) : recherche searchFor par ~43 termes QC paginée + répertoire des diffusions EN DIRECT en français (streams languages:[FR], 20 pages)", | |
| 157 | + "signal_identite": "profil_source (0.98) — la chaîne est le compte d'origine de la fiche", | |
| 158 | + "cadence": "quotidienne (watch) — qui est en direct change chaque jour, la couverture s'accumule", | |
| 159 | + "notes": "vague 4 — marqueur québécois OBLIGATOIRE dans nom/bio/titre du stream ; abonnés, avatar, partenaire/affilié, dernier direct et jeu captés à la source ; niche déduite du jeu (Just Chatting → lifestyle, Music → musique…)" | |
| 160 | + }, | |
| 161 | + { | |
| 162 | + "id": "kick-decouverte", | |
| 163 | + "famille": "decouverte", | |
| 164 | + "palier": 4, | |
| 165 | + "acces": "Scrapfly ASP sans render_js (Cloudflare bloque le direct) : kick.com/api/search par ~27 termes QC + fiche v2 par chaîne retenue (cap 120/passage — budget Scrapfly)", | |
| 166 | + "signal_identite": "profil_source (0.98) pour la chaîne Kick ; cross_link (0.90) pour les liens sociaux AUTO-DÉCLARÉS du profil v2 (instagram/x/youtube/tiktok/facebook/discord)", | |
| 167 | + "cadence": "quotidienne (watch)", | |
| 168 | + "notes": "vague 4 — marqueur québécois requis dans pseudo/slug/bio ; la fiche v2 expose les liens sociaux remplis par le créateur lui-même : meilleure matière première du rattachement §12.1" | |
| 169 | + }, | |
| 170 | + { | |
| 171 | + "id": "region-bio", | |
| 172 | + "famille": "enrichissement", | |
| 173 | + "palier": 1, | |
| 174 | + "acces": "AUCUNE requête — relit les bios publiques déjà en base : ville DÉCLARÉE avec tournure locative (« de Sherbrooke », « based in Montreal ») ou gentilé (« montréalaise ») → région §7 + ville", | |
| 175 | + "signal_identite": "n/a (ne touche pas aux comptes)", | |
| 176 | + "cadence": "quotidienne (watch), tout dernier du pipeline", | |
| 177 | + "notes": "vague 4 — liste de ~70 villes SÛRES seulement (pas d'Alma/Waterloo/Varennes : prénoms, homonymes hors QC, particules) ; abstention si villes de régions différentes ; ne remplit que les champs vides" | |
| 151 | 178 | } |
| 152 | 179 | ] |
| 153 | −} | |
| 180 | +} | |
| \ No newline at end of file | ||
modified
docs/connecteurs/INDEX.md
+21 −18
@@ -1,24 +1,27 @@ | ||
| 1 | 1 | # Créa-Ka — Index des connecteurs |
| 2 | 2 | |
| 3 | −_Généré automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Généré automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | −**16 sources au registre** · **5740 créateurs** et **6714 comptes** en BD. | |
| 5 | +**19 sources au registre** · **9437 créateurs** et **10512 comptes** en BD. | |
| 6 | 6 | |
| 7 | 7 | | Source | Famille | Palier | Type d'accès | Backend | Découverts | Comptes (plateforme) | État | Dernier passage | |
| 8 | 8 | |---|---|---|---|---|---|---|---|---| |
| 9 | −| [`listes-medias`](listes-medias.md) | decouverte | P3 | dataset local compilé (data/seed) | direct | 310 | — | actif | 2026-08-18T06:23… | | |
| 10 | −| [`wikidata-qc`](wikidata-qc.md) | decouverte | P3 | API SPARQL publique (Wikidata) | direct | 73 | — | actif | 2026-08-18T06:27… | | |
| 11 | −| [`onlyqueb`](onlyqueb.md) | decouverte | P3 | sitemap XML + JSON-LD des pages profil (S… | direct | 253 | 248 (onlyfans) | actif | 2026-08-18T06:27… | | |
| 12 | −| [`youtube-recherche`](youtube-recherche.md) | decouverte | P3 | API JSON | direct | 4595 | 4784 (youtube) | actif | 2026-08-18T07:22… | | |
| 13 | −| [`wikipedia-qc`](wikipedia-qc.md) | decouverte | P3 | API SPARQL publique (Wikidata) | direct | 76 | — | actif | 2026-08-18T10:07… | | |
| 14 | −| [`palmares-apple`](palmares-apple.md) | decouverte | P2 | API iTunes Search/Lookup (publique) | direct | 0 | 435 (podcast) | actif | 2026-08-18T09:58… | | |
| 15 | −| [`balados-itunes`](balados-itunes.md) | decouverte | P2 | API iTunes Search/Lookup (publique) | direct | 433 | 435 (podcast) | actif | 2026-08-18T06:23… | | |
| 16 | −| [`instagram-profil`](instagram-profil.md) | enrichissement | P4 | pages HTML publiques | Scrapfly | 0 | 476 (instagram) | actif | 2026-08-18T07:51… | | |
| 17 | −| [`tiktok-profil`](tiktok-profil.md) | enrichissement | P4 | pages HTML publiques | Scrapfly | 0 | 199 (tiktok) | actif | 2026-08-18T09:16… | | |
| 18 | −| [`youtube`](youtube.md) | enrichissement | P2 | API JSON | direct | 0 | 4784 (youtube) | actif | 2026-08-18T10:24… | | |
| 19 | −| [`twitch`](twitch.md) | enrichissement | P2 | API JSON | direct | 0 | 28 (twitch) | actif | 2026-08-18T09:50… | | |
| 20 | −| [`link-in-bio`](link-in-bio.md) | enrichissement | P1 | pages HTML publiques | Firecrawl | 0 | — | actif | 2026-08-18T09:57… | | |
| 21 | −| [`balados-rss`](balados-rss.md) | enrichissement | P1 | flux RSS publics | direct | 0 | 435 (podcast) | actif | 2026-08-18T09:55… | | |
| 22 | −| [`podcastindex`](podcastindex.md) | enrichissement | P2 | API JSON | direct | 0 | 435 (podcast) | prêt | — | | |
| 23 | −| [`x-profil`](x-profil.md) | enrichissement | P3 | pages HTML publiques | direct | 0 | 209 (x) | actif | 2026-08-18T09:55… | | |
| 24 | −| [`bio-liens`](bio-liens.md) | enrichissement | P1 | pages HTML publiques | direct | 0 | — | actif | 2026-08-18T09:57… | | |
| 9 | +| [`listes-medias`](listes-medias.md) | decouverte | P3 | dataset local compilé (data/seed) | direct | 310 | — | actif | 2026-08-18T10:27… | | |
| 10 | +| [`wikidata-qc`](wikidata-qc.md) | decouverte | P3 | API SPARQL publique (Wikidata) | direct | 73 | — | actif | 2026-08-18T10:36… | | |
| 11 | +| [`onlyqueb`](onlyqueb.md) | decouverte | P3 | sitemap XML + JSON-LD des pages profil (S… | direct | 253 | 248 (onlyfans) | actif | 2026-08-18T10:32… | | |
| 12 | +| [`youtube-recherche`](youtube-recherche.md) | decouverte | P3 | API JSON | direct | 7876 | 8084 (youtube) | actif | 2026-08-18T17:05… | | |
| 13 | +| [`wikipedia-qc`](wikipedia-qc.md) | decouverte | P3 | API SPARQL publique (Wikidata) | direct | 84 | — | actif | 2026-08-18T14:44… | | |
| 14 | +| [`palmares-apple`](palmares-apple.md) | decouverte | P2 | API iTunes Search/Lookup (publique) | direct | 0 | 462 (podcast) | actif | 2026-08-18T10:35… | | |
| 15 | +| [`balados-itunes`](balados-itunes.md) | decouverte | P2 | API iTunes Search/Lookup (publique) | direct | 460 | 462 (podcast) | actif | 2026-08-18T14:48… | | |
| 16 | +| [`instagram-profil`](instagram-profil.md) | enrichissement | P4 | pages HTML publiques | Scrapfly | 0 | 495 (instagram) | actif | 2026-08-18T12:04… | | |
| 17 | +| [`tiktok-profil`](tiktok-profil.md) | enrichissement | P4 | pages HTML publiques | Scrapfly | 0 | 224 (tiktok) | actif | 2026-08-18T13:25… | | |
| 18 | +| [`youtube`](youtube.md) | enrichissement | P2 | API JSON | direct | 0 | 8084 (youtube) | actif | 2026-08-18T17:21… | | |
| 19 | +| [`twitch`](twitch.md) | enrichissement | P2 | API JSON | direct | 0 | 292 (twitch) | actif | 2026-08-18T17:05… | | |
| 20 | +| [`link-in-bio`](link-in-bio.md) | enrichissement | P1 | pages HTML publiques | Firecrawl | 0 | — | actif | 2026-08-18T17:29… | | |
| 21 | +| [`balados-rss`](balados-rss.md) | enrichissement | P1 | flux RSS publics | direct | 0 | 462 (podcast) | actif | 2026-08-18T13:48… | | |
| 22 | +| [`podcastindex`](podcastindex.md) | enrichissement | P2 | API JSON | direct | 0 | 462 (podcast) | prêt | — | | |
| 23 | +| [`x-profil`](x-profil.md) | enrichissement | P3 | pages HTML publiques | direct | 0 | 228 (x) | actif | 2026-08-18T17:27… | | |
| 24 | +| [`bio-liens`](bio-liens.md) | enrichissement | P1 | pages HTML publiques | direct | 0 | — | actif | 2026-08-18T17:29… | | |
| 25 | +| [`twitch-decouverte`](twitch-decouverte.md) | decouverte | P3 | pages HTML publiques | direct | 262 | — | actif | 2026-08-18T14:33… | | |
| 26 | +| [`kick-decouverte`](kick-decouverte.md) | decouverte | P4 | pages HTML publiques | Scrapfly | 119 | — | actif | 2026-08-18T14:42… | | |
| 27 | +| [`region-bio`](region-bio.md) | enrichissement | P1 | pages HTML publiques | direct | 0 | — | actif | 2026-08-18T17:29… | | |
modified
docs/connecteurs/balados-itunes.md
+12 −12
@@ -1,8 +1,8 @@ | ||
| 1 | 1 | # `balados-itunes` — connecteur decouverte (palier 2) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | −**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 433 · touchés : 433 | |
| 5 | +**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 460 · touchés : 460 | |
| 6 | 6 | |
| 7 | 7 | ## Description de la source |
| 8 | 8 | |
@@ -25,14 +25,14 @@ Connecteur DÉCOUVERTE — balados québécois via l'API de recherche iTunes/App | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 433 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 28 | +Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 460 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 29 | 29 | |
| 30 | 30 | | Champ du doc créateur | Contenu | Renseigné | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `display_name` | Nom public | 100 % | Québec Nostalgie : le podcast | |
| 33 | 33 | | `bio` | Bio | 97 % | Fidèle à la page Instagram du même nom, Québec Nostalgie : le podcast est un véritable vo… | |
| 34 | −| `region` | Région | 0 % | — | | |
| 35 | −| `city` | Ville | 0 % | — | | |
| 34 | +| `region` | Région | 8 % | — | | |
| 35 | +| `city` | Ville | 8 % | — | | |
| 36 | 36 | | `niches` | Niches (liste) | 100 % | actualite-opinion | |
| 37 | 37 | | `languages` | Langues (liste) | 100 % | fr | |
| 38 | 38 | | `creator_type` | Type de créateur | 100 % | podcasteur | |
@@ -42,7 +42,7 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 42 | 42 | | `total_reach` | Portée totale (abonnés cumulés) | 0 % | 109744 | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 0 % | https://linktr.ee/QuebecNostalgie | |
| 44 | 44 | |
| 45 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (435 comptes en BD, confiance moyenne 0.98). | |
| 45 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (462 comptes en BD, confiance moyenne 0.98). | |
| 46 | 46 | |
| 47 | 47 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 48 | 48 | |---|---|---|---| |
@@ -58,16 +58,16 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 58 | 58 | ## Fréquence & budget |
| 59 | 59 | |
| 60 | 60 | - **Cadence déclarée (registre)** : quotidienne (watch) |
| 61 | −- **Cadence observée** (médiane sync_log) : ≈ 24 min | |
| 62 | −- **Dernier passage** : 2026-08-18T06:23:00Z — 433 créateurs, 433 comptes, +0 / ~433, 0 erreur(s), 131 s | |
| 61 | +- **Cadence observée** (médiane sync_log) : ≈ 40 min | |
| 62 | +- **Dernier passage** : 2026-08-18T14:48:10Z — 460 créateurs, 460 comptes, +27 / ~433, 0 erreur(s), 241 s | |
| 63 | 63 | - **Throttling** : 1.5 s entre requêtes (`request_delay`) |
| 64 | 64 | |
| 65 | 65 | ## Volumétrie & complétude |
| 66 | 66 | |
| 67 | −- **Créateurs découverts par la source** (`doc.source`) : 433 · **fiches touchées** (`source_ids`) : 433 | |
| 68 | −- **Complétude clé (découverts)** : niches 100 % · avatar 100 % · portée 0 % · région 0 % | |
| 69 | −- **Comptes `podcast` en BD** : 435 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T09:56:23Z | |
| 70 | −- **Runs journalisés (60 derniers)** : 7, dont 0 avec erreurs | |
| 67 | +- **Créateurs découverts par la source** (`doc.source`) : 460 · **fiches touchées** (`source_ids`) : 460 | |
| 68 | +- **Complétude clé (découverts)** : niches 100 % · avatar 100 % · portée 0 % · région 8 % | |
| 69 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T17:28:28Z | |
| 70 | +- **Runs journalisés (60 derniers)** : 9, dont 0 avec erreurs | |
| 71 | 71 | |
| 72 | 72 | ## Erreurs connues & dépannage |
| 73 | 73 | |
modified
docs/connecteurs/balados-rss.md
+7 −6
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `balados-rss` — connecteur enrichissement (palier 1) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,7 +25,7 @@ Connecteur ENRICHISSEMENT « balados-rss » — lecture directe des flux RSS aut | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (435 comptes en BD, confiance moyenne 0.98). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (462 comptes en BD, confiance moyenne 0.98). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
@@ -41,20 +41,21 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
| 43 | 43 | - **Cadence déclarée (registre)** : quotidienne (watch) — rotation complète des 433 balados en ~3 jours, puis hebdomadaire |
| 44 | −- **Cadence observée** (médiane sync_log) : ≈ 2.0 h | |
| 45 | −- **Dernier passage** : 2026-08-18T09:55:43Z — 8 créateurs, 36 comptes, +0 / ~8, 5 erreur(s), 12 s | |
| 44 | +- **Cadence observée** (médiane sync_log) : ≈ 3.6 h | |
| 45 | +- **Dernier passage** : 2026-08-18T13:48:02Z — 8 créateurs, 36 comptes, +0 / ~8, 5 erreur(s), 12 s | |
| 46 | 46 | - **Throttling** : 0.2 s entre requêtes (`request_delay`) |
| 47 | 47 | |
| 48 | 48 | ## Volumétrie & complétude |
| 49 | 49 | |
| 50 | 50 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 51 | −- **Comptes `podcast` en BD** : 435 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T09:56:23Z | |
| 52 | −- **Runs journalisés (60 derniers)** : 5, dont 4 avec erreurs | |
| 51 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T17:28:28Z | |
| 52 | +- **Runs journalisés (60 derniers)** : 6, dont 5 avec erreurs | |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
| 55 | 55 | |
| 56 | 56 | | Passage | Erreurs | Alerte (sync_log) | |
| 57 | 57 | |---|---|---| |
| 58 | +| 2026-08-18T13:48:02Z | 5 | — | | |
| 58 | 59 | | 2026-08-18T09:55:43Z | 5 | — | |
| 59 | 60 | | 2026-08-18T06:17:19Z | 5 | — | |
| 60 | 61 | | 2026-08-18T06:17:07Z | 5 | — | |
modified
docs/connecteurs/bio-liens.md
+7 −5
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `bio-liens` — connecteur enrichissement (palier 1) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -29,19 +29,21 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 29 | 29 | ## Fréquence & budget |
| 30 | 30 | |
| 31 | 31 | - **Cadence déclarée (registre)** : quotidienne (watch), en dernier du pipeline |
| 32 | −- **Cadence observée** (médiane sync_log) : — | |
| 33 | −- **Dernier passage** : 2026-08-18T09:57:40Z — 1 créateurs, 2 comptes, +0 / ~1, 0 erreur(s), 0 s | |
| 32 | +- **Cadence observée** (médiane sync_log) : ≈ 3.7 h | |
| 33 | +- **Dernier passage** : 2026-08-18T17:29:45Z — 14 créateurs, 30 comptes, +0 / ~14, 0 erreur(s), 0 s | |
| 34 | 34 | - **Caps / budgets du module** : `MAX_NEW_PER_CREATOR` = 5 |
| 35 | 35 | - **Throttling** : 0.0 s entre requêtes (`request_delay`) |
| 36 | 36 | |
| 37 | 37 | ## Volumétrie & complétude |
| 38 | 38 | |
| 39 | 39 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 40 | −- **Runs journalisés (60 derniers)** : 2, dont 0 avec erreurs | |
| 40 | +- **Runs journalisés (60 derniers)** : 4, dont 0 avec erreurs | |
| 41 | 41 | |
| 42 | 42 | ## Erreurs connues & dépannage |
| 43 | 43 | |
| 44 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 44 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 45 | +|---|---|---| | |
| 46 | +| 2026-08-18T13:50:07Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 45 | 47 | |
| 46 | 48 | Rejouer la source seule : `python3 run.py sync bio-liens` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='bio-liens' ORDER BY ts DESC LIMIT 5;`). |
| 47 | 49 | |
modified
docs/connecteurs/instagram-profil.md
+8 −8
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `instagram-profil` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : Scrapfly · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,31 +25,31 @@ Connecteur ENRICHISSEMENT Instagram — profil public par créateur : abonnés, | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `instagram` (476 comptes en BD, confiance moyenne 0.88). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `instagram` (495 comptes en BD, confiance moyenne 0.88). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `handle` | Handle | 100 % | catherinepaiz | |
| 33 | 33 | | `url` | URL du profil | 100 % | https://www.instagram.com/catherinepaiz/ | |
| 34 | −| `followers` | Abonnés | 70 % | 7023547 | | |
| 34 | +| `followers` | Abonnés | 70 % | 7023251 | | |
| 35 | 35 | | `verified` | Badge vérifié | 58 % | 1 | |
| 36 | 36 | | `confidence` | Confiance d'identité | 100 % | 0.85 | |
| 37 | 37 | | `signal` | Signal d'identité | 100 % | base_publique | |
| 38 | 38 | | `metrics` | Métriques détaillées (JSON) | 58 % | {"following": 248, "posts": 667, "is_business": false} | |
| 39 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T07:23:10Z | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T11:35:29Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
| 43 | 43 | - **Cadence déclarée (registre)** : hebdomadaire (gros créateurs) / mensuelle |
| 44 | −- **Cadence observée** (médiane sync_log) : ≈ 2.1 h | |
| 45 | −- **Dernier passage** : 2026-08-18T07:51:39Z — 274 créateurs, 698 comptes, +0 / ~274, 0 erreur(s), 1724 s | |
| 44 | +- **Cadence observée** (médiane sync_log) : ≈ 3.2 h | |
| 45 | +- **Dernier passage** : 2026-08-18T12:04:24Z — 288 créateurs, 789 comptes, +0 / ~288, 0 erreur(s), 1756 s | |
| 46 | 46 | - **Throttling** : 1.5 s entre requêtes (`request_delay`) |
| 47 | 47 | |
| 48 | 48 | ## Volumétrie & complétude |
| 49 | 49 | |
| 50 | 50 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 51 | −- **Comptes `instagram` en BD** : 476 — abonnés 70 % · métriques 58 % · dernière vérification 2026-08-18T10:07:33Z | |
| 52 | −- **Runs journalisés (60 derniers)** : 4, dont 0 avec erreurs | |
| 51 | +- **Comptes `instagram` en BD** : 495 — abonnés 70 % · métriques 58 % · dernière vérification 2026-08-18T17:29:45Z | |
| 52 | +- **Runs journalisés (60 derniers)** : 5, dont 0 avec erreurs | |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
| 55 | 55 | |
added
docs/connecteurs/kick-decouverte.md
+73 −0
@@ -0,0 +1,73 @@ | ||
| 1 | +# `kick-decouverte` — connecteur decouverte (palier 4) | |
| 2 | + | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | + | |
| 5 | +**État : actif** · Famille : decouverte (discovery) · Backend : Scrapfly · Créateurs découverts : 119 · touchés : 119 | |
| 6 | + | |
| 7 | +## Description de la source | |
| 8 | + | |
| 9 | +Connecteur DÉCOUVERTE — streamers Kick québécois via l'API publique de recherche du site (kick.com/api/search) + fiche v2 par chaîne (liens sociaux AUTO-DÉCLARÉS par le créateur → cross_link 0.90). Mode d'accès : Scrapfly ASP sans render_js (Cloudflare bloque les requêtes directes — 403). Palier 4 (§9/§10). | |
| 10 | + | |
| 11 | +- **Notes (registre)** : vague 4 — marqueur québécois requis dans pseudo/slug/bio ; la fiche v2 expose les liens sociaux remplis par le créateur lui-même : meilleure matière première du rattachement §12.1 | |
| 12 | +- **Signal d'identité** : profil_source (0.98) pour la chaîne Kick ; cross_link (0.90) pour les liens sociaux AUTO-DÉCLARÉS du profil v2 (instagram/x/youtube/tiktok/facebook/discord) (colonne `accounts.signal` / `confidence`) | |
| 13 | +- **Module** : `creaka/connectors/kick_decouverte.py` — classe `KickDecouverteConnector` (`kind = "discovery"`) | |
| 14 | + | |
| 15 | +## Accès | |
| 16 | + | |
| 17 | +- **Accès (registre)** : Scrapfly ASP sans render_js (Cloudflare bloque le direct) : kick.com/api/search par ~27 termes QC + fiche v2 par chaîne retenue (cap 120/passage — budget Scrapfly) | |
| 18 | +- **Type d'accès (code)** : pages HTML publiques | |
| 19 | +- **Endpoint de base** : https://kick.com/api/search?searched_word={term} | |
| 20 | +- **URLs du module** : https://kick.com/api/search?searched_word={term} · https://kick.com/api/v2/channels/{slug} | |
| 21 | +- **Pagination** : réponse unique (pas de pagination) | |
| 22 | +- **Backend anti-bot / rendu** : Scrapfly (asp + render_js — contournement anti-bot) | |
| 23 | +- **Politesse** : 1.5 s entre requêtes, timeout 30 s, UA `CreaKaBot/1.0 (+https://www.crea-ka.com/bot)` | |
| 24 | +- **Authentification** : aucune — contenu public / API anonyme | |
| 25 | + | |
| 26 | +## Champs récupérés → schéma cible | |
| 27 | + | |
| 28 | +Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 119 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 29 | + | |
| 30 | +| Champ du doc créateur | Contenu | Renseigné | Exemple réel | | |
| 31 | +|---|---|---|---| | |
| 32 | +| `display_name` | Nom public | 100 % | valquebrada | | |
| 33 | +| `bio` | Bio | 25 % | Meu nome é Valmir Lima, tenho 32 anos de idade, curto jogar GTA RP. Vou mostrar um pouco … | | |
| 34 | +| `region` | Région | 0 % | — | | |
| 35 | +| `city` | Ville | 0 % | — | | |
| 36 | +| `niches` | Niches (liste) | 100 % | gaming | | |
| 37 | +| `languages` | Langues (liste) | 100 % | fr | | |
| 38 | +| `creator_type` | Type de créateur | 100 % | streamer | | |
| 39 | +| `primary_platform` | Plateforme principale | 100 % | twitch | | |
| 40 | +| `platforms` | Comptes sociaux (liste) | 100 % | twitch:@valquebrada, kick:@valquebrada, instagram:@val_quebrada | | |
| 41 | +| `avatar_url` | Avatar | 40 % | https://files.kick.com/images/user/15480678/profile_image/conversion/f1cf1446-e43a-478d-8… | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 56 % | 2772 | | |
| 43 | +| `link_in_bio_url` | Lien-en-bio | 0 % | — | | |
| 44 | + | |
| 45 | +## Fréquence & budget | |
| 46 | + | |
| 47 | +- **Cadence déclarée (registre)** : quotidienne (watch) | |
| 48 | +- **Cadence observée** (médiane sync_log) : — | |
| 49 | +- **Dernier passage** : 2026-08-18T14:42:46Z — 120 créateurs, 188 comptes, +119 / ~1, 0 erreur(s), 573 s | |
| 50 | +- **Throttling** : 1.5 s entre requêtes (`request_delay`) | |
| 51 | + | |
| 52 | +## Volumétrie & complétude | |
| 53 | + | |
| 54 | +- **Créateurs découverts par la source** (`doc.source`) : 119 · **fiches touchées** (`source_ids`) : 119 | |
| 55 | +- **Complétude clé (découverts)** : niches 100 % · avatar 40 % · portée 56 % · région 0 % | |
| 56 | +- **Runs journalisés (60 derniers)** : 1, dont 0 avec erreurs | |
| 57 | + | |
| 58 | +## Erreurs connues & dépannage | |
| 59 | + | |
| 60 | +Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 61 | + | |
| 62 | +Rejouer la source seule : `python3 run.py sync kick-decouverte` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='kick-decouverte' ORDER BY ts DESC LIMIT 5;`). | |
| 63 | + | |
| 64 | +## Licence, attribution & conditions | |
| 65 | + | |
| 66 | +- **Cadre d'accès (registre)** : Scrapfly ASP sans render_js (Cloudflare bloque le direct) : kick.com/api/search par ~27 termes QC + fiche v2 par chaîne retenue (cap 120/passage — budget Scrapfly) | |
| 67 | +- **Profils publics uniquement** : UA identifiable `CreaKaBot/1.0 (+https://www.crea-ka.com/bot; contact@spboucher.ai)`, throttling poli, respect des opt-out (`data/optout.json`) et du volet éthique (`creaka/ethics.py` — mineurs exclus via `is_minor`). | |
| 68 | +- Retrait sur demande : contact@spboucher.ai (opt-out honoré à la prochaine ingestion). | |
| 69 | + | |
| 70 | +## Historique | |
| 71 | + | |
| 72 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 73 | +- 2026-08-18 — vague d'enrichissement : standardisation de la documentation des connecteurs (fiche générée par `scripts/gen_connector_docs.py`). | |
modified
docs/connecteurs/link-in-bio.md
+4 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `link-in-bio` — connecteur enrichissement (palier 1) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : Firecrawl · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -29,14 +29,14 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 29 | 29 | ## Fréquence & budget |
| 30 | 30 | |
| 31 | 31 | - **Cadence déclarée (registre)** : mensuelle |
| 32 | −- **Cadence observée** (médiane sync_log) : ≈ 4.4 h | |
| 33 | −- **Dernier passage** : 2026-08-18T09:57:40Z — 78 créateurs, 302 comptes, +0 / ~78, 0 erreur(s), 116 s | |
| 32 | +- **Cadence observée** (médiane sync_log) : ≈ 3.8 h | |
| 33 | +- **Dernier passage** : 2026-08-18T17:29:45Z — 83 créateurs, 333 comptes, +0 / ~83, 0 erreur(s), 126 s | |
| 34 | 34 | - **Throttling** : 1.2 s entre requêtes (`request_delay`) |
| 35 | 35 | |
| 36 | 36 | ## Volumétrie & complétude |
| 37 | 37 | |
| 38 | 38 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 39 | −- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 39 | +- **Runs journalisés (60 derniers)** : 5, dont 0 avec erreurs | |
| 40 | 40 | |
| 41 | 41 | ## Erreurs connues & dépannage |
| 42 | 42 | |
modified
docs/connecteurs/listes-medias.md
+10 −10
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `listes-medias` — connecteur decouverte (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 310 · touchés : 310 |
| 6 | 6 | |
@@ -29,30 +29,30 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 29 | 29 | | Champ du doc créateur | Contenu | Renseigné | Exemple réel | |
| 30 | 30 | |---|---|---|---| |
| 31 | 31 | | `display_name` | Nom public | 100 % | Enola Bédard | |
| 32 | −| `bio` | Bio | 72 % | Énola Bédard (born September 14, 2000) is a Canadian dancer, singer, and social media per… | | |
| 33 | −| `region` | Région | 49 % | — | | |
| 34 | −| `city` | Ville | 49 % | — | | |
| 32 | +| `bio` | Bio | 73 % | Énola Bédard (born September 14, 2000) is a Canadian dancer, singer, and social media per… | | |
| 33 | +| `region` | Région | 51 % | Capitale-Nationale | | |
| 34 | +| `city` | Ville | 51 % | Québec | | |
| 35 | 35 | | `niches` | Niches (liste) | 100 % | danse, lifestyle | |
| 36 | 36 | | `languages` | Langues (liste) | 100 % | en, fr | |
| 37 | 37 | | `creator_type` | Type de créateur | 100 % | createur-tiktok | |
| 38 | 38 | | `primary_platform` | Plateforme principale | 100 % | tiktok | |
| 39 | 39 | | `platforms` | Comptes sociaux (liste) | 100 % | tiktok:@enola.bedard, youtube:@enola.bedard, instagram:@enola.bedard | |
| 40 | −| `avatar_url` | Avatar | 74 % | https://scontent-lga3-2.cdninstagram.com/v/t51.82787-19/515154150_18510310135012441_32506… | | |
| 41 | −| `total_reach` | Portée totale (abonnés cumulés) | 90 % | 25307536 | | |
| 40 | +| `avatar_url` | Avatar | 75 % | https://scontent-lga3-2.cdninstagram.com/v/t51.82787-19/515154150_18510310135012441_32506… | | |
| 41 | +| `total_reach` | Portée totale (abonnés cumulés) | 90 % | 24917522 | | |
| 42 | 42 | | `link_in_bio_url` | Lien-en-bio | 24 % | — | |
| 43 | 43 | |
| 44 | 44 | ## Fréquence & budget |
| 45 | 45 | |
| 46 | 46 | - **Cadence déclarée (registre)** : mensuelle (recompilation du dataset) |
| 47 | −- **Cadence observée** (médiane sync_log) : ≈ 22 min | |
| 48 | −- **Dernier passage** : 2026-08-18T06:23:00Z — 310 créateurs, 448 comptes, +0 / ~310, 0 erreur(s), 0 s | |
| 47 | +- **Cadence observée** (médiane sync_log) : ≈ 28 min | |
| 48 | +- **Dernier passage** : 2026-08-18T10:27:45Z — 310 créateurs, 448 comptes, +0 / ~310, 0 erreur(s), 0 s | |
| 49 | 49 | - **Throttling** : 0.8 s entre requêtes (`request_delay`) |
| 50 | 50 | |
| 51 | 51 | ## Volumétrie & complétude |
| 52 | 52 | |
| 53 | 53 | - **Créateurs découverts par la source** (`doc.source`) : 310 · **fiches touchées** (`source_ids`) : 310 |
| 54 | −- **Complétude clé (découverts)** : niches 100 % · avatar 74 % · portée 90 % · région 49 % | |
| 55 | −- **Runs journalisés (60 derniers)** : 11, dont 0 avec erreurs | |
| 54 | +- **Complétude clé (découverts)** : niches 100 % · avatar 75 % · portée 90 % · région 51 % | |
| 55 | +- **Runs journalisés (60 derniers)** : 12, dont 0 avec erreurs | |
| 56 | 56 | |
| 57 | 57 | ## Erreurs connues & dépannage |
| 58 | 58 | |
modified
docs/connecteurs/onlyqueb.md
+9 −9
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `onlyqueb` — connecteur decouverte (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 253 · touchés : 253 |
| 6 | 6 | |
@@ -31,15 +31,15 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `display_name` | Nom public | 100 % | Jade Lavoie | |
| 33 | 33 | | `bio` | Bio | 98 % | Deviens mon prochain acteur! 🔥 Je fais littéralement TOUT. Demande ce que tu veux et trou… | |
| 34 | −| `region` | Région | 0 % | — | | |
| 35 | −| `city` | Ville | 0 % | — | | |
| 34 | +| `region` | Région | 2 % | — | | |
| 35 | +| `city` | Ville | 2 % | — | | |
| 36 | 36 | | `niches` | Niches (liste) | 100 % | autre | |
| 37 | 37 | | `languages` | Langues (liste) | 100 % | fr | |
| 38 | 38 | | `creator_type` | Type de créateur | 100 % | influenceur | |
| 39 | 39 | | `primary_platform` | Plateforme principale | 100 % | instagram | |
| 40 | 40 | | `platforms` | Comptes sociaux (liste) | 100 % | instagram:@jadelavoie, x:@missjadelavoie, onlyfans:@misslavoie | |
| 41 | 41 | | `avatar_url` | Avatar | 100 % | https://storage.googleapis.com/onlyqueb/MQZBiXsbMQa31zxj9P_mabNxNITFBxa6 | |
| 42 | −| `total_reach` | Portée totale (abonnés cumulés) | 18 % | 1571106 | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 20 % | 1571053 | | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 2 % | — | |
| 44 | 44 | |
| 45 | 45 | Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `onlyfans` (248 comptes en BD, confiance moyenne 0.90). |
@@ -58,16 +58,16 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 58 | 58 | ## Fréquence & budget |
| 59 | 59 | |
| 60 | 60 | - **Cadence déclarée (registre)** : hebdomadaire |
| 61 | −- **Cadence observée** (médiane sync_log) : ≈ 24 min | |
| 62 | −- **Dernier passage** : 2026-08-18T06:27:32Z — 253 créateurs, 611 comptes, +0 / ~253, 0 erreur(s), 272 s | |
| 61 | +- **Cadence observée** (médiane sync_log) : ≈ 32 min | |
| 62 | +- **Dernier passage** : 2026-08-18T10:32:17Z — 253 créateurs, 611 comptes, +0 / ~253, 0 erreur(s), 272 s | |
| 63 | 63 | - **Throttling** : 1.0 s entre requêtes (`request_delay`) |
| 64 | 64 | |
| 65 | 65 | ## Volumétrie & complétude |
| 66 | 66 | |
| 67 | 67 | - **Créateurs découverts par la source** (`doc.source`) : 253 · **fiches touchées** (`source_ids`) : 253 |
| 68 | −- **Complétude clé (découverts)** : niches 100 % · avatar 100 % · portée 18 % · région 0 % | |
| 69 | −- **Comptes `onlyfans` en BD** : 248 — abonnés 0 % · métriques 0 % · dernière vérification 2026-08-18T09:57:40Z | |
| 70 | −- **Runs journalisés (60 derniers)** : 7, dont 0 avec erreurs | |
| 68 | +- **Complétude clé (découverts)** : niches 100 % · avatar 100 % · portée 20 % · région 2 % | |
| 69 | +- **Comptes `onlyfans` en BD** : 248 — abonnés 0 % · métriques 0 % · dernière vérification 2026-08-18T17:29:45Z | |
| 70 | +- **Runs journalisés (60 derniers)** : 8, dont 0 avec erreurs | |
| 71 | 71 | |
| 72 | 72 | ## Erreurs connues & dépannage |
| 73 | 73 | |
modified
docs/connecteurs/palmares-apple.md
+7 −6
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `palmares-apple` — connecteur decouverte (palier 2) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,7 +25,7 @@ Connecteur DÉCOUVERTE — balados québécois dans le TOP 100 canadien d'Apple | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (435 comptes en BD, confiance moyenne 0.98). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (462 comptes en BD, confiance moyenne 0.98). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
@@ -41,20 +41,21 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
| 43 | 43 | - **Cadence déclarée (registre)** : quotidienne (watch) — le palmarès bouge chaque jour |
| 44 | −- **Cadence observée** (médiane sync_log) : — | |
| 45 | −- **Dernier passage** : 2026-08-18T09:58:54Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 211 s | |
| 44 | +- **Cadence observée** (médiane sync_log) : ≈ 21 min | |
| 45 | +- **Dernier passage** : 2026-08-18T10:35:47Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 209 s | |
| 46 | 46 | - **Throttling** : 1.0 s entre requêtes (`request_delay`) |
| 47 | 47 | |
| 48 | 48 | ## Volumétrie & complétude |
| 49 | 49 | |
| 50 | 50 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 51 | −- **Comptes `podcast` en BD** : 435 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T09:56:23Z | |
| 52 | −- **Runs journalisés (60 derniers)** : 2, dont 0 avec erreurs | |
| 51 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T17:28:28Z | |
| 52 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
| 55 | 55 | |
| 56 | 56 | | Passage | Erreurs | Alerte (sync_log) | |
| 57 | 57 | |---|---|---| |
| 58 | +| 2026-08-18T10:35:47Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 58 | 59 | | 2026-08-18T09:58:54Z | 0 | 0 créateur retourné — source possiblement bloquée | |
| 59 | 60 | |
| 60 | 61 | Rejouer la source seule : `python3 run.py sync palmares-apple` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='palmares-apple' ORDER BY ts DESC LIMIT 5;`). |
modified
docs/connecteurs/podcastindex.md
+3 −3
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `podcastindex` — connecteur enrichissement (palier 2) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : prêt — clés requises** · Famille : enrichissement (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,7 +25,7 @@ Connecteur ENRICHISSEMENT « podcastindex » — API Podcast Index (OFFICIELLE, | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (435 comptes en BD, confiance moyenne 0.98). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (462 comptes en BD, confiance moyenne 0.98). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
@@ -47,7 +47,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 47 | 47 | ## Volumétrie & complétude |
| 48 | 48 | |
| 49 | 49 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 50 | −- **Comptes `podcast` en BD** : 435 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T09:56:23Z | |
| 50 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T17:28:28Z | |
| 51 | 51 | - **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs |
| 52 | 52 | |
| 53 | 53 | ## Erreurs connues & dépannage |
added
docs/connecteurs/region-bio.md
+56 −0
@@ -0,0 +1,56 @@ | ||
| 1 | +# `region-bio` — connecteur enrichissement (palier 1) | |
| 2 | + | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | + | |
| 5 | +**État : actif** · Famille : enrichissement (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 | |
| 6 | + | |
| 7 | +## Description de la source | |
| 8 | + | |
| 9 | +Connecteur ENRICHISSEMENT — région/ville depuis la localisation DÉCLARÉE dans la bio publique du créateur (« humoriste de Sherbrooke », « based in Montreal », « vlogueuse montréalaise »). Mode d'accès : AUCUNE requête (relit les bios déjà en base, comme bio-liens). Palier 1 (§9). Vague 4. | |
| 10 | + | |
| 11 | +- **Notes (registre)** : vague 4 — liste de ~70 villes SÛRES seulement (pas d'Alma/Waterloo/Varennes : prénoms, homonymes hors QC, particules) ; abstention si villes de régions différentes ; ne remplit que les champs vides | |
| 12 | +- **Signal d'identité** : n/a (ne touche pas aux comptes) (colonne `accounts.signal` / `confidence`) | |
| 13 | +- **Module** : `creaka/connectors/region_bio.py` — classe `RegionBioConnector` (`kind = "enrichment"`) | |
| 14 | + | |
| 15 | +## Accès | |
| 16 | + | |
| 17 | +- **Accès (registre)** : AUCUNE requête — relit les bios publiques déjà en base : ville DÉCLARÉE avec tournure locative (« de Sherbrooke », « based in Montreal ») ou gentilé (« montréalaise ») → région §7 + ville | |
| 18 | +- **Type d'accès (code)** : pages HTML publiques | |
| 19 | +- **Endpoint de base** : — | |
| 20 | +- **Pagination** : réponse unique (pas de pagination) | |
| 21 | +- **Backend anti-bot / rendu** : requests direct | |
| 22 | +- **Politesse** : 0.0 s entre requêtes, timeout 30 s, UA `CreaKaBot/1.0 (+https://www.crea-ka.com/bot)` | |
| 23 | +- **Authentification** : aucune — contenu public / API anonyme | |
| 24 | + | |
| 25 | +## Champs récupérés → schéma cible | |
| 26 | + | |
| 27 | +Aucune donnée attribuable à cette source en BD pour l'instant (clés manquantes ou source en attente) — schéma cible : `creators` + `accounts`. | |
| 28 | + | |
| 29 | +## Fréquence & budget | |
| 30 | + | |
| 31 | +- **Cadence déclarée (registre)** : quotidienne (watch), tout dernier du pipeline | |
| 32 | +- **Cadence observée** (médiane sync_log) : — | |
| 33 | +- **Dernier passage** : 2026-08-18T17:29:46Z — 1391 créateurs, 1507 comptes, +0 / ~1391, 0 erreur(s), 0 s | |
| 34 | +- **Throttling** : 0.0 s entre requêtes (`request_delay`) | |
| 35 | + | |
| 36 | +## Volumétrie & complétude | |
| 37 | + | |
| 38 | +- **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 | |
| 39 | +- **Runs journalisés (60 derniers)** : 1, dont 0 avec erreurs | |
| 40 | + | |
| 41 | +## Erreurs connues & dépannage | |
| 42 | + | |
| 43 | +Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 44 | + | |
| 45 | +Rejouer la source seule : `python3 run.py sync region-bio` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='region-bio' ORDER BY ts DESC LIMIT 5;`). | |
| 46 | + | |
| 47 | +## Licence, attribution & conditions | |
| 48 | + | |
| 49 | +- **Cadre d'accès (registre)** : AUCUNE requête — relit les bios publiques déjà en base : ville DÉCLARÉE avec tournure locative (« de Sherbrooke », « based in Montreal ») ou gentilé (« montréalaise ») → région §7 + ville | |
| 50 | +- **Profils publics uniquement** : UA identifiable `CreaKaBot/1.0 (+https://www.crea-ka.com/bot; contact@spboucher.ai)`, throttling poli, respect des opt-out (`data/optout.json`) et du volet éthique (`creaka/ethics.py` — mineurs exclus via `is_minor`). | |
| 51 | +- Retrait sur demande : contact@spboucher.ai (opt-out honoré à la prochaine ingestion). | |
| 52 | + | |
| 53 | +## Historique | |
| 54 | + | |
| 55 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 56 | +- 2026-08-18 — vague d'enrichissement : standardisation de la documentation des connecteurs (fiche générée par `scripts/gen_connector_docs.py`). | |
modified
docs/connecteurs/tiktok-profil.md
+10 −10
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `tiktok-profil` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : Scrapfly · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,31 +25,31 @@ Connecteur ENRICHISSEMENT TikTok — profil public par créateur : abonnés, bad | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `tiktok` (199 comptes en BD, confiance moyenne 0.90). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `tiktok` (224 comptes en BD, confiance moyenne 0.90). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `handle` | Handle | 100 % | enola.bedard | |
| 33 | 33 | | `url` | URL du profil | 100 % | https://www.tiktok.com/@enola.bedard | |
| 34 | −| `followers` | Abonnés | 65 % | 17100000 | | |
| 35 | −| `verified` | Badge vérifié | 55 % | 1 | | |
| 34 | +| `followers` | Abonnés | 63 % | 17000000 | | |
| 35 | +| `verified` | Badge vérifié | 59 % | 1 | | |
| 36 | 36 | | `confidence` | Confiance d'identité | 100 % | 0.85 | |
| 37 | 37 | | `signal` | Signal d'identité | 100 % | base_publique | |
| 38 | −| `metrics` | Métriques détaillées (JSON) | 55 % | {"following": 813, "likes": 438100000, "videos": 2847} | | |
| 39 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T10:07:33Z | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 59 % | {"following": 813, "likes": 438100000, "videos": 2847} | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T14:44:09Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
| 43 | 43 | - **Cadence déclarée (registre)** : hebdomadaire (gros créateurs) / mensuelle |
| 44 | −- **Cadence observée** (médiane sync_log) : — | |
| 45 | −- **Dernier passage** : 2026-08-18T09:16:06Z — 76 créateurs, 257 comptes, +0 / ~76, 0 erreur(s), 5067 s | |
| 44 | +- **Cadence observée** (médiane sync_log) : ≈ 6.4 h | |
| 45 | +- **Dernier passage** : 2026-08-18T13:25:43Z — 67 créateurs, 255 comptes, +0 / ~67, 0 erreur(s), 4880 s | |
| 46 | 46 | - **Throttling** : 1.5 s entre requêtes (`request_delay`) |
| 47 | 47 | |
| 48 | 48 | ## Volumétrie & complétude |
| 49 | 49 | |
| 50 | 50 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 51 | −- **Comptes `tiktok` en BD** : 199 — abonnés 65 % · métriques 55 % · dernière vérification 2026-08-18T10:07:33Z | |
| 52 | −- **Runs journalisés (60 derniers)** : 2, dont 0 avec erreurs | |
| 51 | +- **Comptes `tiktok` en BD** : 224 — abonnés 63 % · métriques 59 % · dernière vérification 2026-08-18T17:29:45Z | |
| 52 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
| 55 | 55 | |
added
docs/connecteurs/twitch-decouverte.md
+72 −0
@@ -0,0 +1,72 @@ | ||
| 1 | +# `twitch-decouverte` — connecteur decouverte (palier 3) | |
| 2 | + | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | + | |
| 5 | +**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 262 · touchés : 262 | |
| 6 | + | |
| 7 | +## Description de la source | |
| 8 | + | |
| 9 | +Connecteur DÉCOUVERTE — streamers Twitch québécois via l'API GQL publique du site officiel (Client-ID public, sans clé) : recherche de chaînes par termes QC + répertoire des diffusions en français. Palier 3 (§9). Filtre conservateur : marqueur québécois OBLIGATOIRE dans le nom, la bio ou le titre du stream. | |
| 10 | + | |
| 11 | +- **Notes (registre)** : vague 4 — marqueur québécois OBLIGATOIRE dans nom/bio/titre du stream ; abonnés, avatar, partenaire/affilié, dernier direct et jeu captés à la source ; niche déduite du jeu (Just Chatting → lifestyle, Music → musique…) | |
| 12 | +- **Signal d'identité** : profil_source (0.98) — la chaîne est le compte d'origine de la fiche (colonne `accounts.signal` / `confidence`) | |
| 13 | +- **Module** : `creaka/connectors/twitch_decouverte.py` — classe `TwitchDecouverteConnector` (`kind = "discovery"`) | |
| 14 | + | |
| 15 | +## Accès | |
| 16 | + | |
| 17 | +- **Accès (registre)** : API GQL publique du site officiel de Twitch (Client-ID public web, sans clé) : recherche searchFor par ~43 termes QC paginée + répertoire des diffusions EN DIRECT en français (streams languages:[FR], 20 pages) | |
| 18 | +- **Type d'accès (code)** : pages HTML publiques | |
| 19 | +- **Endpoint de base** : — | |
| 20 | +- **Pagination** : curseur / continuation | |
| 21 | +- **Backend anti-bot / rendu** : requests direct (session UA CreaKaBot, throttling poli) | |
| 22 | +- **Politesse** : 1.0 s entre requêtes, timeout 30 s, UA `CreaKaBot/1.0 (+https://www.crea-ka.com/bot)` | |
| 23 | +- **Authentification** : clé(s) API requise(s) — voir statut/registre | |
| 24 | + | |
| 25 | +## Champs récupérés → schéma cible | |
| 26 | + | |
| 27 | +Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 262 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 28 | + | |
| 29 | +| Champ du doc créateur | Contenu | Renseigné | Exemple réel | | |
| 30 | +|---|---|---|---| | |
| 31 | +| `display_name` | Nom public | 100 % | PlaqueBoyMax | | |
| 32 | +| `bio` | Bio | 55 % | for business inquiries: [retiré] | | |
| 33 | +| `region` | Région | 4 % | — | | |
| 34 | +| `city` | Ville | 4 % | — | | |
| 35 | +| `niches` | Niches (liste) | 100 % | lifestyle | | |
| 36 | +| `languages` | Langues (liste) | 100 % | fr | | |
| 37 | +| `creator_type` | Type de créateur | 100 % | streamer | | |
| 38 | +| `primary_platform` | Plateforme principale | 100 % | twitch | | |
| 39 | +| `platforms` | Comptes sociaux (liste) | 100 % | twitch:@plaqueboymax | | |
| 40 | +| `avatar_url` | Avatar | 100 % | https://static-cdn.jtvnw.net/jtv_user_pictures/14f0fcfd-00d4-4004-9379-93e0c6336f5e-profi… | | |
| 41 | +| `total_reach` | Portée totale (abonnés cumulés) | 74 % | 2841225 | | |
| 42 | +| `link_in_bio_url` | Lien-en-bio | 0 % | — | | |
| 43 | + | |
| 44 | +## Fréquence & budget | |
| 45 | + | |
| 46 | +- **Cadence déclarée (registre)** : quotidienne (watch) — qui est en direct change chaque jour, la couverture s'accumule | |
| 47 | +- **Cadence observée** (médiane sync_log) : — | |
| 48 | +- **Dernier passage** : 2026-08-18T14:33:13Z — 262 créateurs, 262 comptes, +262 / ~0, 0 erreur(s), 147 s | |
| 49 | +- **Throttling** : 1.0 s entre requêtes (`request_delay`) | |
| 50 | + | |
| 51 | +## Volumétrie & complétude | |
| 52 | + | |
| 53 | +- **Créateurs découverts par la source** (`doc.source`) : 262 · **fiches touchées** (`source_ids`) : 262 | |
| 54 | +- **Complétude clé (découverts)** : niches 100 % · avatar 100 % · portée 74 % · région 4 % | |
| 55 | +- **Runs journalisés (60 derniers)** : 1, dont 0 avec erreurs | |
| 56 | + | |
| 57 | +## Erreurs connues & dépannage | |
| 58 | + | |
| 59 | +Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 60 | + | |
| 61 | +Rejouer la source seule : `python3 run.py sync twitch-decouverte` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='twitch-decouverte' ORDER BY ts DESC LIMIT 5;`). | |
| 62 | + | |
| 63 | +## Licence, attribution & conditions | |
| 64 | + | |
| 65 | +- **Cadre d'accès (registre)** : API GQL publique du site officiel de Twitch (Client-ID public web, sans clé) : recherche searchFor par ~43 termes QC paginée + répertoire des diffusions EN DIRECT en français (streams languages:[FR], 20 pages) | |
| 66 | +- **API publique** utilisée selon ses conditions (pas de clé détournée, throttling poli) ; données limitées aux profils publics. | |
| 67 | +- Retrait sur demande : contact@spboucher.ai (opt-out honoré à la prochaine ingestion). | |
| 68 | + | |
| 69 | +## Historique | |
| 70 | + | |
| 71 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 72 | +- 2026-08-18 — vague d'enrichissement : standardisation de la documentation des connecteurs (fiche générée par `scripts/gen_connector_docs.py`). | |
modified
docs/connecteurs/twitch.md
+10 −10
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `twitch` — connecteur enrichissement (palier 2) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,31 +25,31 @@ Connecteur ENRICHISSEMENT Twitch — profil public par créateur SANS clé via l | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `twitch` (28 comptes en BD, confiance moyenne 0.89). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `twitch` (292 comptes en BD, confiance moyenne 0.97). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `handle` | Handle | 100 % | xqc | |
| 33 | 33 | | `url` | URL du profil | 100 % | https://www.twitch.tv/xqc | |
| 34 | −| `followers` | Abonnés | 75 % | 12535964 | | |
| 35 | −| `verified` | Badge vérifié | 39 % | 1 | | |
| 34 | +| `followers` | Abonnés | 98 % | 12535878 | | |
| 35 | +| `verified` | Badge vérifié | 6 % | 1 | | |
| 36 | 36 | | `confidence` | Confiance d'identité | 100 % | 0.85 | |
| 37 | 37 | | `signal` | Signal d'identité | 100 % | base_publique | |
| 38 | −| `metrics` | Métriques détaillées (JSON) | 68 % | {"last_stream": "2026-08-18T08:03:23.924661Z", "game": "Just Chatting"} | | |
| 39 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T10:07:33Z | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 79 % | {"last_stream": "2026-08-18T08:03:23.924661Z", "game": "Just Chatting"} | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T17:05:24Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
| 43 | 43 | - **Cadence déclarée (registre)** : hebdomadaire |
| 44 | −- **Cadence observée** (médiane sync_log) : — | |
| 45 | −- **Dernier passage** : 2026-08-18T09:50:40Z — 24 créateurs, 90 comptes, +0 / ~24, 0 erreur(s), 1 s | |
| 44 | +- **Cadence observée** (médiane sync_log) : ≈ 3.9 h | |
| 45 | +- **Dernier passage** : 2026-08-18T17:05:40Z — 289 créateurs, 372 comptes, +0 / ~289, 0 erreur(s), 16 s | |
| 46 | 46 | - **Throttling** : 1.0 s entre requêtes (`request_delay`) |
| 47 | 47 | |
| 48 | 48 | ## Volumétrie & complétude |
| 49 | 49 | |
| 50 | 50 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 51 | −- **Comptes `twitch` en BD** : 28 — abonnés 75 % · métriques 68 % · dernière vérification 2026-08-18T10:07:33Z | |
| 52 | −- **Runs journalisés (60 derniers)** : 2, dont 0 avec erreurs | |
| 51 | +- **Comptes `twitch` en BD** : 292 — abonnés 98 % · métriques 79 % · dernière vérification 2026-08-18T17:28:20Z | |
| 52 | +- **Runs journalisés (60 derniers)** : 4, dont 0 avec erreurs | |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
| 55 | 55 | |
modified
docs/connecteurs/wikidata-qc.md
+10 −10
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `wikidata-qc` — connecteur decouverte (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 73 · touchés : 73 |
| 6 | 6 | |
@@ -30,30 +30,30 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 30 | 30 | | Champ du doc créateur | Contenu | Renseigné | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `display_name` | Nom public | 100 % | xQc | |
| 33 | −| `bio` | Bio | 75 % | Félix Lengyel, mieux connu sous le pseudonyme « xQc » (Félix Québec), né le 12 novembre 1… | | |
| 34 | −| `region` | Région | 0 % | — | | |
| 35 | −| `city` | Ville | 0 % | — | | |
| 33 | +| `bio` | Bio | 77 % | Félix Lengyel, mieux connu sous le pseudonyme « xQc » (Félix Québec), né le 12 novembre 1… | | |
| 34 | +| `region` | Région | 18 % | Laval | | |
| 35 | +| `city` | Ville | 18 % | Laval | | |
| 36 | 36 | | `niches` | Niches (liste) | 100 % | gaming, lifestyle | |
| 37 | 37 | | `languages` | Langues (liste) | 100 % | en, fr | |
| 38 | 38 | | `creator_type` | Type de créateur | 100 % | influenceur | |
| 39 | 39 | | `primary_platform` | Plateforme principale | 100 % | twitch | |
| 40 | 40 | | `platforms` | Comptes sociaux (liste) | 99 % | twitch:@xqc, youtube:@UCmDTrq0LNgPodDOFZiSbsww, x:@xqc | |
| 41 | −| `avatar_url` | Avatar | 71 % | https://scontent-yyz1-1.cdninstagram.com/v/t51.2885-19/387770319_137990486044045_21612287… | | |
| 42 | −| `total_reach` | Portée totale (abonnés cumulés) | 64 % | 17220047 | | |
| 41 | +| `avatar_url` | Avatar | 73 % | https://scontent-yyz1-1.cdninstagram.com/v/t51.2885-19/387770319_137990486044045_21612287… | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 64 % | 17219949 | | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 19 % | — | |
| 44 | 44 | |
| 45 | 45 | ## Fréquence & budget |
| 46 | 46 | |
| 47 | 47 | - **Cadence déclarée (registre)** : hebdomadaire |
| 48 | −- **Cadence observée** (médiane sync_log) : ≈ 30 min | |
| 49 | −- **Dernier passage** : 2026-08-18T06:27:51Z — 83 créateurs, 172 comptes, +0 / ~83, 0 erreur(s), 18 s | |
| 48 | +- **Cadence observée** (médiane sync_log) : ≈ 32 min | |
| 49 | +- **Dernier passage** : 2026-08-18T10:36:26Z — 83 créateurs, 172 comptes, +0 / ~83, 0 erreur(s), 39 s | |
| 50 | 50 | - **Throttling** : 2.0 s entre requêtes (`request_delay`) |
| 51 | 51 | |
| 52 | 52 | ## Volumétrie & complétude |
| 53 | 53 | |
| 54 | 54 | - **Créateurs découverts par la source** (`doc.source`) : 73 · **fiches touchées** (`source_ids`) : 73 |
| 55 | −- **Complétude clé (découverts)** : niches 100 % · avatar 71 % · portée 64 % · région 0 % | |
| 56 | −- **Runs journalisés (60 derniers)** : 9, dont 1 avec erreurs | |
| 55 | +- **Complétude clé (découverts)** : niches 100 % · avatar 73 % · portée 64 % · région 18 % | |
| 56 | +- **Runs journalisés (60 derniers)** : 10, dont 1 avec erreurs | |
| 57 | 57 | |
| 58 | 58 | ## Erreurs connues & dépannage |
| 59 | 59 | |
modified
docs/connecteurs/wikipedia-qc.md
+19 −19
@@ -1,8 +1,8 @@ | ||
| 1 | 1 | # `wikipedia-qc` — connecteur decouverte (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | −**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 76 · touchés : 76 | |
| 5 | +**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 84 · touchés : 84 | |
| 6 | 6 | |
| 7 | 7 | ## Description de la source |
| 8 | 8 | |
@@ -25,35 +25,35 @@ Connecteur DÉCOUVERTE — créateurs de contenu québécois recensés dans les | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 76 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 28 | +Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 84 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 29 | 29 | |
| 30 | 30 | | Champ du doc créateur | Contenu | Renseigné | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | −| `display_name` | Nom public | 100 % | Adib Alkhalidey | | |
| 33 | −| `bio` | Bio | 100 % | Adib Alkhalidey est un humoriste, auteur-compositeur-interprète, réalisateur et acteur qu… | | |
| 34 | −| `region` | Région | 0 % | — | | |
| 35 | −| `city` | Ville | 0 % | — | | |
| 36 | −| `niches` | Niches (liste) | 100 % | humour | | |
| 32 | +| `display_name` | Nom public | 100 % | Evil Uno | | |
| 33 | +| `bio` | Bio | 100 % | Nicolas Dansereau (born July 20, 1987), better known by the ring name Evil Uno, is a Cana… | | |
| 34 | +| `region` | Région | 49 % | — | | |
| 35 | +| `city` | Ville | 48 % | — | | |
| 36 | +| `niches` | Niches (liste) | 100 % | lifestyle | | |
| 37 | 37 | | `languages` | Langues (liste) | 100 % | fr | |
| 38 | −| `creator_type` | Type de créateur | 100 % | humoriste | | |
| 39 | −| `primary_platform` | Plateforme principale | 100 % | site-web | | |
| 40 | −| `platforms` | Comptes sociaux (liste) | 100 % | site-web:@adibalkhalidey.com | | |
| 41 | −| `avatar_url` | Avatar | 75 % | https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/IGP6508.jpg/500px-IGP6508.jpg?u… | | |
| 42 | −| `total_reach` | Portée totale (abonnés cumulés) | 0 % | — | | |
| 43 | −| `link_in_bio_url` | Lien-en-bio | 0 % | — | | |
| 38 | +| `creator_type` | Type de créateur | 100 % | youtubeur | | |
| 39 | +| `primary_platform` | Plateforme principale | 100 % | x | | |
| 40 | +| `platforms` | Comptes sociaux (liste) | 100 % | x:@eviluno, instagram:@evil.uno, twitch:@eviluno | | |
| 41 | +| `avatar_url` | Avatar | 80 % | https://upload.wikimedia.org/wikipedia/commons/thumb/a/a6/Unoenjoy.jpg/500px-Unoenjoy.jpg… | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 12 % | 268165 | | |
| 43 | +| `link_in_bio_url` | Lien-en-bio | 5 % | http://linktr.ee/eviluno | | |
| 44 | 44 | |
| 45 | 45 | ## Fréquence & budget |
| 46 | 46 | |
| 47 | 47 | - **Cadence déclarée (registre)** : hebdomadaire |
| 48 | −- **Cadence observée** (médiane sync_log) : — | |
| 49 | −- **Dernier passage** : 2026-08-18T10:07:33Z — 111 créateurs, 247 comptes, +76 / ~35, 0 erreur(s), 58 s | |
| 48 | +- **Cadence observée** (médiane sync_log) : ≈ 30 min | |
| 49 | +- **Dernier passage** : 2026-08-18T14:44:09Z — 120 créateurs, 262 comptes, +8 / ~112, 0 erreur(s), 83 s | |
| 50 | 50 | - **Throttling** : 1.0 s entre requêtes (`request_delay`) |
| 51 | 51 | |
| 52 | 52 | ## Volumétrie & complétude |
| 53 | 53 | |
| 54 | −- **Créateurs découverts par la source** (`doc.source`) : 76 · **fiches touchées** (`source_ids`) : 76 | |
| 55 | −- **Complétude clé (découverts)** : niches 100 % · avatar 75 % · portée 0 % · région 0 % | |
| 56 | −- **Runs journalisés (60 derniers)** : 2, dont 0 avec erreurs | |
| 54 | +- **Créateurs découverts par la source** (`doc.source`) : 84 · **fiches touchées** (`source_ids`) : 84 | |
| 55 | +- **Complétude clé (découverts)** : niches 100 % · avatar 80 % · portée 12 % · région 49 % | |
| 56 | +- **Runs journalisés (60 derniers)** : 4, dont 0 avec erreurs | |
| 57 | 57 | |
| 58 | 58 | ## Erreurs connues & dépannage |
| 59 | 59 | |
modified
docs/connecteurs/x-profil.md
+11 −10
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `x-profil` — connecteur enrichissement (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,40 +25,41 @@ Connecteur ENRICHISSEMENT « x-profil » — abonnés X (Twitter) SANS clé via | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `x` (209 comptes en BD, confiance moyenne 0.88). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `x` (228 comptes en BD, confiance moyenne 0.88). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `handle` | Handle | 100 % | xqc | |
| 33 | 33 | | `url` | URL du profil | 100 % | https://x.com/xqc | |
| 34 | −| `followers` | Abonnés | 9 % | 1598794 | | |
| 34 | +| `followers` | Abonnés | 18 % | 1598794 | | |
| 35 | 35 | | `verified` | Badge vérifié | 0 % | — | |
| 36 | 36 | | `confidence` | Confiance d'identité | 100 % | 0.9 | |
| 37 | 37 | | `signal` | Signal d'identité | 100 % | cross_link | |
| 38 | −| `metrics` | Métriques détaillées (JSON) | 10 % | {"following": 526, "x_checked": "2026-08-18T06:14:55Z"} | | |
| 39 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T10:07:33Z | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 32 % | {"following": 526, "x_checked": "2026-08-18T06:14:55Z"} | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T14:44:09Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
| 43 | 43 | - **Cadence déclarée (registre)** : quotidienne (watch), rotation hebdomadaire |
| 44 | −- **Cadence observée** (médiane sync_log) : ≈ 10 min | |
| 45 | −- **Dernier passage** : 2026-08-18T09:55:31Z — 4 créateurs, 20 comptes, +0 / ~4, 146 erreur(s), 325 s | |
| 44 | +- **Cadence observée** (médiane sync_log) : ≈ 3.7 h | |
| 45 | +- **Dernier passage** : 2026-08-18T17:27:39Z — 28 créateurs, 125 comptes, +0 / ~28, 122 erreur(s), 342 s | |
| 46 | 46 | - **Throttling** : 2.0 s entre requêtes (`request_delay`) |
| 47 | 47 | |
| 48 | 48 | ## Volumétrie & complétude |
| 49 | 49 | |
| 50 | 50 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 51 | −- **Comptes `x` en BD** : 209 — abonnés 9 % · métriques 10 % · dernière vérification 2026-08-18T10:07:33Z | |
| 52 | −- **Runs journalisés (60 derniers)** : 4, dont 4 avec erreurs | |
| 51 | +- **Comptes `x` en BD** : 228 — abonnés 18 % · métriques 32 % · dernière vérification 2026-08-18T17:29:45Z | |
| 52 | +- **Runs journalisés (60 derniers)** : 6, dont 6 avec erreurs | |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
| 55 | 55 | |
| 56 | 56 | | Passage | Erreurs | Alerte (sync_log) | |
| 57 | 57 | |---|---|---| |
| 58 | +| 2026-08-18T17:27:39Z | 122 | — | | |
| 59 | +| 2026-08-18T13:47:50Z | 127 | — | | |
| 58 | 60 | | 2026-08-18T09:55:31Z | 146 | — | |
| 59 | 61 | | 2026-08-18T06:15:49Z | 1 | — | |
| 60 | 62 | | 2026-08-18T06:12:35Z | 171 | — | |
| 61 | −| 2026-08-18T06:02:56Z | 1 | — | | |
| 62 | 63 | |
| 63 | 64 | Rejouer la source seule : `python3 run.py sync x-profil` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='x-profil' ORDER BY ts DESC LIMIT 5;`). |
| 64 | 65 | |
modified
docs/connecteurs/youtube-recherche.md
+17 −17
@@ -1,8 +1,8 @@ | ||
| 1 | 1 | # `youtube-recherche` — connecteur decouverte (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | −**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 4595 · touchés : 4595 | |
| 5 | +**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 7876 · touchés : 7876 | |
| 6 | 6 | |
| 7 | 7 | ## Description de la source |
| 8 | 8 | |
@@ -25,24 +25,24 @@ Connecteur DÉCOUVERTE — chaînes YouTube québécoises via la recherche publi | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 4595 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 28 | +Source de **découverte** : produit des fiches `Creator` (tables `creators` + `accounts`). Complétude mesurée sur les 7876 créateurs découverts par cette source (champ `doc.source`) ; exemple tiré d'une fiche réelle. | |
| 29 | 29 | |
| 30 | 30 | | Champ du doc créateur | Contenu | Renseigné | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `display_name` | Nom public | 100 % | Ça commence aujourd'hui - France Télévisions | |
| 33 | −| `bio` | Bio | 88 % | La vérité plus qu'ailleurs avec Faustine Bollaert. | | |
| 34 | −| `region` | Région | 0 % | — | | |
| 35 | −| `city` | Ville | 0 % | — | | |
| 33 | +| `bio` | Bio | 87 % | La vérité plus qu'ailleurs avec Faustine Bollaert. | | |
| 34 | +| `region` | Région | 16 % | — | | |
| 35 | +| `city` | Ville | 16 % | — | | |
| 36 | 36 | | `niches` | Niches (liste) | 100 % | sport-fitness | |
| 37 | 37 | | `languages` | Langues (liste) | 100 % | fr | |
| 38 | 38 | | `creator_type` | Type de créateur | 100 % | youtubeur | |
| 39 | 39 | | `primary_platform` | Plateforme principale | 100 % | youtube | |
| 40 | 40 | | `platforms` | Comptes sociaux (liste) | 100 % | youtube:@%c3%87acommenceaujourdhui-francet%c3%a9l | |
| 41 | −| `avatar_url` | Avatar | 91 % | https://yt3.ggpht.com/34WaPmV58PCfc9W7IvR_oAVkTcQrRyYMenz4phwmrE7LPm8f4zJfOIc2Jq4XkMZZsYj… | | |
| 42 | −| `total_reach` | Portée totale (abonnés cumulés) | 96 % | 1860000 | | |
| 41 | +| `avatar_url` | Avatar | 98 % | https://yt3.ggpht.com/34WaPmV58PCfc9W7IvR_oAVkTcQrRyYMenz4phwmrE7LPm8f4zJfOIc2Jq4XkMZZsYj… | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 95 % | 1860000 | | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 0 % | — | |
| 44 | 44 | |
| 45 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `youtube` (4784 comptes en BD, confiance moyenne 0.98). | |
| 45 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `youtube` (8084 comptes en BD, confiance moyenne 0.98). | |
| 46 | 46 | |
| 47 | 47 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 48 | 48 | |---|---|---|---| |
@@ -52,22 +52,22 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 52 | 52 | | `verified` | Badge vérifié | 0 % | — | |
| 53 | 53 | | `confidence` | Confiance d'identité | 100 % | 0.9 | |
| 54 | 54 | | `signal` | Signal d'identité | 100 % | cross_link | |
| 55 | −| `metrics` | Métriques détaillées (JSON) | 6 % | {"yt_checked": "2026-08-18T10:08:15Z", "videos": 400, "views": 4647638686, "last_video": … | | |
| 56 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T10:08:15Z | | |
| 55 | +| `metrics` | Métriques détaillées (JSON) | 10 % | {"yt_checked": "2026-08-18T10:08:15Z", "videos": 400, "views": 4647638686, "last_video": … | | |
| 56 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T11:35:25Z | | |
| 57 | 57 | |
| 58 | 58 | ## Fréquence & budget |
| 59 | 59 | |
| 60 | 60 | - **Cadence déclarée (registre)** : quotidienne (watch) — la couverture s'accumule à chaque passage |
| 61 | −- **Cadence observée** (médiane sync_log) : ≈ 5.3 h | |
| 62 | −- **Dernier passage** : 2026-08-18T07:22:54Z — 4155 créateurs, 4155 comptes, +555 / ~3600, 0 erreur(s), 3304 s | |
| 61 | +- **Cadence observée** (médiane sync_log) : ≈ 4.9 h | |
| 62 | +- **Dernier passage** : 2026-08-18T17:05:23Z — 7347 créateurs, 7347 comptes, +3180 / ~4167, 0 erreur(s), 8233 s | |
| 63 | 63 | - **Throttling** : 1.0 s entre requêtes (`request_delay`) |
| 64 | 64 | |
| 65 | 65 | ## Volumétrie & complétude |
| 66 | 66 | |
| 67 | −- **Créateurs découverts par la source** (`doc.source`) : 4595 · **fiches touchées** (`source_ids`) : 4595 | |
| 68 | −- **Complétude clé (découverts)** : niches 100 % · avatar 91 % · portée 96 % · région 0 % | |
| 69 | −- **Comptes `youtube` en BD** : 4784 — abonnés 94 % · métriques 6 % · dernière vérification 2026-08-18T10:24:39Z | |
| 70 | −- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 67 | +- **Créateurs découverts par la source** (`doc.source`) : 7876 · **fiches touchées** (`source_ids`) : 7876 | |
| 68 | +- **Complétude clé (découverts)** : niches 100 % · avatar 98 % · portée 95 % · région 16 % | |
| 69 | +- **Comptes `youtube` en BD** : 8084 — abonnés 94 % · métriques 10 % · dernière vérification 2026-08-18T17:29:45Z | |
| 70 | +- **Runs journalisés (60 derniers)** : 5, dont 0 avec erreurs | |
| 71 | 71 | |
| 72 | 72 | ## Erreurs connues & dépannage |
| 73 | 73 | |
modified
docs/connecteurs/youtube.md
+10 −8
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `youtube` — connecteur enrichissement (palier 2) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 06:25 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:01 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -25,7 +25,7 @@ Connecteur ENRICHISSEMENT YouTube — stats de chaîne par créateur. Mode d'acc | ||
| 25 | 25 | |
| 26 | 26 | ## Champs récupérés → schéma cible |
| 27 | 27 | |
| 28 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `youtube` (4784 comptes en BD, confiance moyenne 0.98). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `youtube` (8084 comptes en BD, confiance moyenne 0.98). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
@@ -35,26 +35,28 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 35 | 35 | | `verified` | Badge vérifié | 0 % | — | |
| 36 | 36 | | `confidence` | Confiance d'identité | 100 % | 0.9 | |
| 37 | 37 | | `signal` | Signal d'identité | 100 % | cross_link | |
| 38 | −| `metrics` | Métriques détaillées (JSON) | 6 % | {"yt_checked": "2026-08-18T10:08:15Z", "videos": 400, "views": 4647638686, "last_video": … | | |
| 39 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T10:08:15Z | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 10 % | {"yt_checked": "2026-08-18T10:08:15Z", "videos": 400, "views": 4647638686, "last_video": … | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T11:35:25Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
| 43 | 43 | - **Cadence déclarée (registre)** : quotidienne (watch) — cap 300 chaînes/passage, rotation 14 j (≈4 200 comptes → convergence ~2 semaines) |
| 44 | −- **Cadence observée** (médiane sync_log) : ≈ 4.7 h | |
| 45 | −- **Dernier passage** : 2026-08-18T10:24:39Z — 264 créateurs, 503 comptes, +0 / ~264, 36 erreur(s), 1001 s | |
| 44 | +- **Cadence observée** (médiane sync_log) : ≈ 3.5 h | |
| 45 | +- **Dernier passage** : 2026-08-18T17:21:57Z — 256 créateurs, 264 comptes, +0 / ~256, 44 erreur(s), 977 s | |
| 46 | 46 | - **Throttling** : 1.0 s entre requêtes (`request_delay`) |
| 47 | 47 | |
| 48 | 48 | ## Volumétrie & complétude |
| 49 | 49 | |
| 50 | 50 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 51 | −- **Comptes `youtube` en BD** : 4784 — abonnés 94 % · métriques 6 % · dernière vérification 2026-08-18T10:24:39Z | |
| 52 | −- **Runs journalisés (60 derniers)** : 3, dont 1 avec erreurs | |
| 51 | +- **Comptes `youtube` en BD** : 8084 — abonnés 94 % · métriques 10 % · dernière vérification 2026-08-18T17:29:45Z | |
| 52 | +- **Runs journalisés (60 derniers)** : 5, dont 3 avec erreurs | |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
| 55 | 55 | |
| 56 | 56 | | Passage | Erreurs | Alerte (sync_log) | |
| 57 | 57 | |---|---|---| |
| 58 | +| 2026-08-18T17:21:57Z | 44 | — | | |
| 59 | +| 2026-08-18T13:42:12Z | 38 | — | | |
| 58 | 60 | | 2026-08-18T10:24:39Z | 36 | — | |
| 59 | 61 | |
| 60 | 62 | Rejouer la source seule : `python3 run.py sync youtube` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='youtube' ORDER BY ts DESC LIMIT 5;`). |
| 61 | 63 | |