crea-ka: couverture 13 plateformes (Apify) + refresh auto 7j + max-parallélisme
- +patreon-apify +discord-apify (code invit sensible à la casse via URL) - run_actor_sharded : N runs parallèles (défaut 32x2Go), retry+jitter, hook target_of - rotation hebdo (APIFY_REVISIT_DAYS=7) : le watch PM2 quotidien couvre tout le bassin en <=7j - +tavily-seed (1271 graines moissonnées) +snowball-ig (related_profiles) pour lexpansion - frontend : stats/badges/contenu récent par plateforme Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
44 changed files +2,211 −217
modified
creaka/connectors/apify_social.py
+150 −37
@@ -27,7 +27,9 @@ Uniquement des profils PUBLICS (§15) ; un profil privé/introuvable est ignoré | ||
| 27 | 27 | from __future__ import annotations |
| 28 | 28 | |
| 29 | 29 | import os |
| 30 | +import random | |
| 30 | 31 | import time |
| 32 | +from concurrent.futures import ThreadPoolExecutor, as_completed | |
| 31 | 33 | from datetime import datetime, timedelta, timezone |
| 32 | 34 | |
| 33 | 35 | import requests |
@@ -42,34 +44,60 @@ APIFY_API = "https://api.apify.com/v2" | ||
| 42 | 44 | ACTOR_OWNER = "gorgeous_thistle" |
| 43 | 45 | RESIDENTIAL = {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"]} |
| 44 | 46 | |
| 45 | − | |
| 46 | −def run_actor(name: str, run_input: dict, *, timeout_s: int = 2400, | |
| 47 | − memory_mb: int = 1024) -> list[dict]: | |
| 48 | − """Lance un acteur KA sur Apify et retourne les items de son dataset. | |
| 49 | − | |
| 50 | − Run asynchrone + polling (run-sync plafonne à 300 s, trop court pour les | |
| 51 | − gros lots). Le run est avorté si `timeout_s` est dépassé. | |
| 52 | − """ | |
| 47 | +# --- parallélisme : on dispose de 256 Go de RAM Apify → au lieu d'UN run à | |
| 48 | +# 1 Go, on éclate le lot en tranches lancées EN PARALLÈLE, chacune avec plus de | |
| 49 | +# mémoire (donc plus de CPU/vCPU côté Apify) et une concurrence interne accrue. | |
| 50 | +# profil « max parallélisme » : ces acteurs sont I/O-bound (requêtes proxy), | |
| 51 | +# donc BEAUCOUP de petits runs > peu de gros runs. 32 × 2 Go = 64 Go de pointe | |
| 52 | +# (large sous les 256 Go / 128 runs concurrents du plan). | |
| 53 | +SHARD_SIZE = int(os.environ.get("APIFY_SHARD_SIZE", "60")) # handles / run | |
| 54 | +MAX_SHARDS = int(os.environ.get("APIFY_MAX_SHARDS", "32")) # runs simultanés | |
| 55 | +RUN_MEMORY_MB = int(os.environ.get("APIFY_RUN_MEMORY_MB", "2048")) # /run | |
| 56 | +RUN_CONCURRENCY = int(os.environ.get("APIFY_RUN_CONCURRENCY", "10")) # interne (max 10) | |
| 57 | +# rafraîchissement : un compte est re-sondé s'il n'a pas été enrichi depuis | |
| 58 | +# REVISIT_DAYS jours. Le watch quotidien couvre ainsi TOUT le bassin en ≤ N j. | |
| 59 | +REVISIT_DAYS = int(os.environ.get("APIFY_REVISIT_DAYS", "7")) | |
| 60 | + | |
| 61 | + | |
| 62 | +def _token() -> str: | |
| 53 | 63 | token = os.environ.get("APIFY_TOKEN") |
| 54 | 64 | if not token: |
| 55 | 65 | raise SkipSource("APIFY_TOKEN manquant (voir .env)") |
| 56 | − headers = {"Authorization": f"Bearer {token}"} | |
| 57 | − resp = requests.post( | |
| 58 | − f"{APIFY_API}/acts/{ACTOR_OWNER}~{name}/runs", | |
| 59 | − json=run_input, headers=headers, | |
| 60 | − params={"memory": memory_mb}, timeout=60) | |
| 66 | + return token | |
| 67 | + | |
| 68 | + | |
| 69 | +def _launch(name: str, run_input: dict, memory_mb: int, | |
| 70 | + retries: int = 6) -> str: | |
| 71 | + """Démarre un run. Retry sur 400/429 (limite mémoire concurrente atteinte : | |
| 72 | + elle se libère quand d'autres tranches terminent) avec backoff.""" | |
| 73 | + headers = {"Authorization": f"Bearer {_token()}"} | |
| 74 | + for attempt in range(retries): | |
| 75 | + resp = requests.post( | |
| 76 | + f"{APIFY_API}/acts/{ACTOR_OWNER}~{name}/runs", | |
| 77 | + json=run_input, headers=headers, | |
| 78 | + params={"memory": memory_mb}, timeout=60) | |
| 79 | + if resp.status_code in (400, 429, 402) or resp.status_code >= 500: | |
| 80 | + if attempt < retries - 1: | |
| 81 | + # backoff + jitter : désynchronise les tranches (évite le | |
| 82 | + # lockstep où toutes redemandent la RAM au même instant) | |
| 83 | + time.sleep(min(60, 8 * (attempt + 1)) + random.uniform(0, 6)) | |
| 84 | + continue | |
| 85 | + resp.raise_for_status() | |
| 86 | + return resp.json()["data"]["id"] | |
| 61 | 87 | resp.raise_for_status() |
| 62 | − run_id = resp.json()["data"]["id"] | |
| 88 | + return resp.json()["data"]["id"] | |
| 89 | + | |
| 90 | + | |
| 91 | +def _await_items(run_id: str, name: str, timeout_s: int) -> list[dict]: | |
| 92 | + headers = {"Authorization": f"Bearer {_token()}"} | |
| 63 | 93 | t0 = time.time() |
| 64 | − status: dict = {} | |
| 65 | 94 | while True: |
| 66 | 95 | time.sleep(15) |
| 67 | 96 | r = requests.get(f"{APIFY_API}/actor-runs/{run_id}", |
| 68 | 97 | headers=headers, timeout=60) |
| 69 | 98 | r.raise_for_status() |
| 70 | 99 | status = r.json()["data"] |
| 71 | − if status["status"] in ("SUCCEEDED", "FAILED", "ABORTED", | |
| 72 | − "TIMED-OUT"): | |
| 100 | + if status["status"] in ("SUCCEEDED", "FAILED", "ABORTED", "TIMED-OUT"): | |
| 73 | 101 | break |
| 74 | 102 | if time.time() - t0 > timeout_s: |
| 75 | 103 | requests.post(f"{APIFY_API}/actor-runs/{run_id}/abort", |
@@ -93,24 +121,68 @@ def run_actor(name: str, run_input: dict, *, timeout_s: int = 2400, | ||
| 93 | 121 | offset += 1000 |
| 94 | 122 | |
| 95 | 123 | |
| 124 | +def run_actor(name: str, run_input: dict, *, timeout_s: int = 2400, | |
| 125 | + memory_mb: int = RUN_MEMORY_MB) -> list[dict]: | |
| 126 | + """Un seul run (recherche, petit lot).""" | |
| 127 | + return _await_items(_launch(name, run_input, memory_mb), name, timeout_s) | |
| 128 | + | |
| 129 | + | |
| 130 | +def run_actor_sharded(name: str, base_input: dict, usernames: list[str], *, | |
| 131 | + timeout_s: int = 2400, | |
| 132 | + shard_size: int = SHARD_SIZE, | |
| 133 | + max_shards: int = MAX_SHARDS, | |
| 134 | + memory_mb: int = RUN_MEMORY_MB) -> list[dict]: | |
| 135 | + """Éclate `usernames` en tranches lancées EN PARALLÈLE sur Apify. | |
| 136 | + | |
| 137 | + Chaque tranche = un run indépendant (mémoire dédiée → plus de CPU). On | |
| 138 | + plafonne à `max_shards` runs simultanés (256 Go de RAM = large marge : | |
| 139 | + 12 × 4 Go = 48 Go). Les datasets sont fusionnés. Une tranche qui échoue | |
| 140 | + n'annule pas les autres. | |
| 141 | + """ | |
| 142 | + if not usernames: | |
| 143 | + return [] | |
| 144 | + n = max(1, min(max_shards, | |
| 145 | + (len(usernames) + shard_size - 1) // shard_size)) | |
| 146 | + shards = [usernames[i::n] for i in range(n)] # répartition équilibrée | |
| 147 | + items: list[dict] = [] | |
| 148 | + with ThreadPoolExecutor(max_workers=n) as pool: | |
| 149 | + futs = {pool.submit(run_actor, name, | |
| 150 | + {**base_input, "usernames": shard}, | |
| 151 | + timeout_s=timeout_s, memory_mb=memory_mb): i | |
| 152 | + for i, shard in enumerate(shards) if shard} | |
| 153 | + for fut in as_completed(futs): | |
| 154 | + try: | |
| 155 | + items.extend(fut.result()) | |
| 156 | + except Exception as exc: # une tranche morte ne bloque pas le reste | |
| 157 | + print(f"[crea-ka] {name} tranche {futs[fut]} échouée : {exc}") | |
| 158 | + return items | |
| 159 | + | |
| 160 | + | |
| 96 | 161 | class _ApifySocialEnrich(BaseConnector): |
| 97 | 162 | """Base commune des enrichissements Apify (un acteur par plateforme).""" |
| 98 | 163 | |
| 99 | 164 | kind = "enrichment" |
| 100 | 165 | platform = "" # plateforme canonique (§6.2) |
| 101 | 166 | actor = "" # nom court de l'acteur (ka-instagram…) |
| 102 | − cap = 300 # comptes max par run (maîtrise du coût) | |
| 103 | − revisit_days = 5 # ne pas re-sonder un compte plus frais que ça | |
| 167 | + cap = 3000 # comptes max par passage (shardé en parallèle) | |
| 168 | + revisit_days = REVISIT_DAYS # re-sonde hebdo par défaut (env APIFY_REVISIT_DAYS) | |
| 104 | 169 | content_key = "" # clé du contenu récent dans l'item acteur |
| 105 | 170 | # clés d'item copiées telles quelles dans account.metrics si non nulles |
| 106 | 171 | metric_map: dict[str, str] = {} |
| 107 | 172 | |
| 173 | + @property | |
| 174 | + def _stamp_key(self) -> str: | |
| 175 | + # tampon PROPRE au connecteur : quand CE connecteur a enrichi ce compte. | |
| 176 | + # On ne se base PAS sur acc.last_checked, re-tamponné par la découverte | |
| 177 | + # (kick-decouverte etc.) même sans enrichissement → fausse fraîcheur. | |
| 178 | + return f"{self.source_id}_at" | |
| 179 | + | |
| 108 | 180 | def _stale(self, acc) -> bool: |
| 109 | − if not acc.last_checked: | |
| 181 | + stamp = (acc.metrics or {}).get(self._stamp_key) | |
| 182 | + if not stamp: | |
| 110 | 183 | return True |
| 111 | 184 | try: |
| 112 | − seen = datetime.fromisoformat( | |
| 113 | − acc.last_checked.replace("Z", "+00:00")) | |
| 185 | + seen = datetime.fromisoformat(str(stamp).replace("Z", "+00:00")) | |
| 114 | 186 | except ValueError: |
| 115 | 187 | return True |
| 116 | 188 | return (datetime.now(timezone.utc) - seen |
@@ -119,6 +191,16 @@ class _ApifySocialEnrich(BaseConnector): | ||
| 119 | 191 | def extra_input(self) -> dict: |
| 120 | 192 | return {} |
| 121 | 193 | |
| 194 | + def target_of(self, acc) -> str: | |
| 195 | + """Valeur envoyée à l'acteur pour ce compte (défaut : le handle). | |
| 196 | + | |
| 197 | + Certaines plateformes exigent autre chose que le handle minusculé — | |
| 198 | + ex. Discord, dont le code d'invitation est SENSIBLE À LA CASSE et doit | |
| 199 | + être repris depuis l'URL. Le rapprochement se fait ensuite en | |
| 200 | + minuscules des deux côtés. | |
| 201 | + """ | |
| 202 | + return acc.handle | |
| 203 | + | |
| 122 | 204 | def enrich(self, creators: list[Creator]) -> list[Creator]: |
| 123 | 205 | targets: dict[str, list] = {} |
| 124 | 206 | for cr in creators: |
@@ -126,22 +208,23 @@ class _ApifySocialEnrich(BaseConnector): | ||
| 126 | 208 | if a.platform == self.platform and a.handle), None) |
| 127 | 209 | if acc is None or not self._stale(acc): |
| 128 | 210 | continue |
| 129 | − targets.setdefault(acc.handle, []).append((cr, acc)) | |
| 211 | + targets.setdefault(self.target_of(acc), []).append((cr, acc)) | |
| 130 | 212 | if len(targets) >= self.cap: |
| 131 | 213 | break |
| 132 | 214 | if not targets: |
| 133 | 215 | return [] |
| 134 | − items = run_actor(self.actor, { | |
| 135 | − "usernames": sorted(targets), | |
| 136 | − "proxyConfiguration": RESIDENTIAL, | |
| 137 | − **self.extra_input(), | |
| 138 | − }) | |
| 216 | + items = run_actor_sharded( | |
| 217 | + self.actor, | |
| 218 | + {"proxyConfiguration": RESIDENTIAL, | |
| 219 | + "concurrency": RUN_CONCURRENCY, | |
| 220 | + **self.extra_input()}, | |
| 221 | + sorted(targets)) | |
| 139 | 222 | by_handle = {str(it.get("username") or "").lower(): it |
| 140 | 223 | for it in items if it.get("kind") == "profile"} |
| 141 | 224 | enriched: list[Creator] = [] |
| 142 | 225 | self.errors = 0 |
| 143 | 226 | for handle, pairs in targets.items(): |
| 144 | − it = by_handle.get(handle) | |
| 227 | + it = by_handle.get(handle.lower()) | |
| 145 | 228 | if it is None: |
| 146 | 229 | continue |
| 147 | 230 | if not it.get("found"): |
@@ -163,6 +246,7 @@ class _ApifySocialEnrich(BaseConnector): | ||
| 163 | 246 | if it.get(src) is not None} |
| 164 | 247 | if self.content_key and it.get(self.content_key): |
| 165 | 248 | metrics[self.content_key] = it[self.content_key][:12] |
| 249 | + metrics[self._stamp_key] = now_iso() # tampon d'enrichissement propre | |
| 166 | 250 | acc.metrics.update(metrics) |
| 167 | 251 | if not cr.avatar_url and it.get("avatar"): |
| 168 | 252 | cr.avatar_url = it["avatar"] |
@@ -195,7 +279,7 @@ class ApifyInstagram(_ApifySocialEnrich): | ||
| 195 | 279 | source_id = "instagram-apify" |
| 196 | 280 | platform = "instagram" |
| 197 | 281 | actor = "ka-instagram" |
| 198 | − cap = 400 | |
| 282 | + cap = 1800 | |
| 199 | 283 | content_key = "recent_posts" |
| 200 | 284 | metric_map = {"following": "following", "posts_count": "posts", |
| 201 | 285 | "category": "category", "is_business": "is_business", |
@@ -224,7 +308,7 @@ class ApifyTikTok(_ApifySocialEnrich): | ||
| 224 | 308 | source_id = "tiktok-apify" |
| 225 | 309 | platform = "tiktok" |
| 226 | 310 | actor = "ka-tiktok" |
| 227 | − cap = 300 | |
| 311 | + cap = 1800 | |
| 228 | 312 | content_key = "recent_videos" |
| 229 | 313 | metric_map = {"following": "following", "total_likes": "likes", |
| 230 | 314 | "videos_count": "videos", "region": "region", |
@@ -245,7 +329,7 @@ class ApifyX(_ApifySocialEnrich): | ||
| 245 | 329 | source_id = "x-apify" |
| 246 | 330 | platform = "x" |
| 247 | 331 | actor = "ka-x" |
| 248 | − cap = 300 | |
| 332 | + cap = 1800 | |
| 249 | 333 | content_key = "recent_tweets" |
| 250 | 334 | metric_map = {"following": "following", "tweets_count": "tweets", |
| 251 | 335 | "location": "location", "created_at": "created_at", |
@@ -269,7 +353,7 @@ class ApifyFacebook(_ApifySocialEnrich): | ||
| 269 | 353 | source_id = "facebook-apify" |
| 270 | 354 | platform = "facebook" |
| 271 | 355 | actor = "ka-facebook" |
| 272 | − cap = 100 | |
| 356 | + cap = 400 | |
| 273 | 357 | revisit_days = 7 |
| 274 | 358 | metric_map = {"category": "category"} |
| 275 | 359 | |
@@ -306,7 +390,7 @@ class ApifyYouTube(_ApifySocialEnrich): | ||
| 306 | 390 | source_id = "youtube-apify" |
| 307 | 391 | platform = "youtube" |
| 308 | 392 | actor = "ka-youtube" |
| 309 | − cap = 300 | |
| 393 | + cap = 1800 | |
| 310 | 394 | content_key = "recent_videos" |
| 311 | 395 | metric_map = {"videos_count": "videos", "country": "country", |
| 312 | 396 | "keywords": "keywords", "channel_id": "channel_id", |
@@ -318,7 +402,7 @@ class ApifyTwitch(_ApifySocialEnrich): | ||
| 318 | 402 | source_id = "twitch-apify" |
| 319 | 403 | platform = "twitch" |
| 320 | 404 | actor = "ka-twitch" |
| 321 | − cap = 300 | |
| 405 | + cap = 1200 | |
| 322 | 406 | content_key = "recent_videos" |
| 323 | 407 | metric_map = {"is_partner": "is_partner", "is_affiliate": "is_affiliate", |
| 324 | 408 | "team": "team", "created_at": "created_at", |
@@ -334,7 +418,7 @@ class ApifyKick(_ApifySocialEnrich): | ||
| 334 | 418 | source_id = "kick-apify" |
| 335 | 419 | platform = "kick" |
| 336 | 420 | actor = "ka-kick" |
| 337 | − cap = 120 | |
| 421 | + cap = 600 | |
| 338 | 422 | metric_map = {"is_live_now": "is_live_now", "live_viewers": "live_viewers", |
| 339 | 423 | "subscription_enabled": "subscription_enabled", |
| 340 | 424 | "recent_categories": "recent_categories"} |
@@ -381,13 +465,42 @@ class ApifyFansly(_ApifySocialEnrich): | ||
| 381 | 465 | source_id = "fansly-apify" |
| 382 | 466 | platform = "fansly" |
| 383 | 467 | actor = "ka-fansly" |
| 384 | − cap = 200 | |
| 468 | + cap = 600 | |
| 385 | 469 | revisit_days = 7 |
| 386 | 470 | metric_map = {"posts_count": "posts", "images_count": "images", |
| 387 | 471 | "videos_count": "videos", "likes": "likes", |
| 388 | 472 | "following": "following", "location": "location"} |
| 389 | 473 | |
| 390 | 474 | |
| 475 | +class ApifyPatreon(_ApifySocialEnrich): | |
| 476 | + source_id = "patreon-apify" | |
| 477 | + platform = "patreon" | |
| 478 | + actor = "ka-patreon" | |
| 479 | + cap = 400 | |
| 480 | + revisit_days = 7 | |
| 481 | + metric_map = {"patrons": "patrons", "posts_count": "posts", | |
| 482 | + "is_monthly": "is_monthly"} | |
| 483 | + | |
| 484 | + | |
| 485 | +class ApifyDiscord(_ApifySocialEnrich): | |
| 486 | + source_id = "discord-apify" | |
| 487 | + platform = "discord" | |
| 488 | + actor = "ka-discord" | |
| 489 | + cap = 400 | |
| 490 | + revisit_days = 7 | |
| 491 | + metric_map = {"members": "members", "online": "online", "boosts": "boosts", | |
| 492 | + "partnered": "partnered", "guild_id": "guild_id"} | |
| 493 | + | |
| 494 | + def target_of(self, acc) -> str: | |
| 495 | + """Code d'invitation SENSIBLE À LA CASSE, repris de l'URL (pas du | |
| 496 | + handle minusculé) : discord.gg/<CODE> ou discord.com/invite/<CODE>.""" | |
| 497 | + url = acc.url or "" | |
| 498 | + for sep in ("discord.gg/", "discord.com/invite/", "/invite/"): | |
| 499 | + if sep in url: | |
| 500 | + return url.split(sep, 1)[1].split("/")[0].split("?")[0] | |
| 501 | + return acc.handle | |
| 502 | + | |
| 503 | + | |
| 391 | 504 | # --- découverte Instagram (topsearch, mots-clés QC) --------------------------- |
| 392 | 505 | |
| 393 | 506 | # thèmes × marqueurs QC — mêmes familles que youtube-recherche, adaptées à la |
added
creaka/connectors/snowball.py
+75 −0
@@ -0,0 +1,75 @@ | ||
| 1 | +# ============================================================================== | |
| 2 | +# Author: Simon-Pierre Boucher <contact@spboucher.ai> | |
| 3 | +# File: creaka/connectors/snowball.py | |
| 4 | +# Desc: Connecteur DÉCOUVERTE par boule de neige — exploite les profils | |
| 5 | +# reliés (`related_profiles`) captés par l'enrichissement Instagram | |
| 6 | +# (instagram-apify) pour créer de nouvelles fiches. C'est le levier | |
| 7 | +# d'échelle : chaque profil IG suggère ~10-20 comptes similaires → | |
| 8 | +# parcours en largeur qui fait croître le bassin de dizaines de milliers | |
| 9 | +# au fil des vagues quotidiennes. Aucune requête réseau (lit la base). | |
| 10 | +# ============================================================================== | |
| 11 | +"""Découverte par boule de neige sur les profils reliés Instagram. | |
| 12 | + | |
| 13 | +Déclaré `enrichment` pour recevoir la liste des créateurs existants, mais il | |
| 14 | +RETOURNE de NOUVELLES fiches (le pipeline sync_source les ajoute par uid). On | |
| 15 | +lit `account.metrics["related_profiles"]` (posé par instagram-apify), on écarte | |
| 16 | +les handles déjà connus, et on crée une graine par nouveau compte suggéré. | |
| 17 | +Signal `mention` (0.60) : proximité algorithmique, à confirmer par | |
| 18 | +l'enrichissement — sous le seuil de publication tant que non vérifié (§12.1). | |
| 19 | +""" | |
| 20 | +from __future__ import annotations | |
| 21 | + | |
| 22 | +from ..identity import account | |
| 23 | +from ..normalize import canonical_url | |
| 24 | +from ..schema import Creator | |
| 25 | +from .base import BaseConnector | |
| 26 | + | |
| 27 | + | |
| 28 | +class SnowballConnector(BaseConnector): | |
| 29 | + source_id = "snowball-ig" | |
| 30 | + kind = "enrichment" | |
| 31 | + max_new = 4000 # garde-fou par vague | |
| 32 | + | |
| 33 | + def enrich(self, creators: list[Creator]) -> list[Creator]: | |
| 34 | + known: set[str] = set() | |
| 35 | + for cr in creators: | |
| 36 | + for a in cr.platforms: | |
| 37 | + if a.platform == "instagram": | |
| 38 | + known.add(a.handle) | |
| 39 | + new: list[Creator] = [] | |
| 40 | + emitted: set[str] = set() | |
| 41 | + for cr in creators: | |
| 42 | + ig = next((a for a in cr.platforms | |
| 43 | + if a.platform == "instagram"), None) | |
| 44 | + if ig is None: | |
| 45 | + continue | |
| 46 | + for rel in (ig.metrics or {}).get("related_profiles", []) or []: | |
| 47 | + handle = (rel.get("username") if isinstance(rel, dict) | |
| 48 | + else rel) | |
| 49 | + handle = (handle or "").strip().lstrip("@").lower() | |
| 50 | + if (not handle or rel and isinstance(rel, dict) | |
| 51 | + and rel.get("is_private")): | |
| 52 | + continue | |
| 53 | + if handle in known or handle in emitted: | |
| 54 | + continue | |
| 55 | + emitted.add(handle) | |
| 56 | + try: | |
| 57 | + acc = account("instagram", handle, "mention", | |
| 58 | + url=canonical_url("instagram", handle), | |
| 59 | + verified=(rel.get("is_verified") | |
| 60 | + if isinstance(rel, dict) | |
| 61 | + else None)).finalize() | |
| 62 | + except Exception: | |
| 63 | + continue | |
| 64 | + name = (rel.get("full_name") if isinstance(rel, dict) | |
| 65 | + else None) or handle | |
| 66 | + new.append(Creator( | |
| 67 | + source=self.source_id, | |
| 68 | + external_id=f"instagram:{handle}", | |
| 69 | + display_name=name, | |
| 70 | + platforms=[acc], | |
| 71 | + notes="découvert par boule de neige (profils reliés IG)", | |
| 72 | + )) | |
| 73 | + if len(new) >= self.max_new: | |
| 74 | + return new | |
| 75 | + return new | |
added
creaka/connectors/tavily_seed.py
+71 −0
@@ -0,0 +1,71 @@ | ||
| 1 | +# ============================================================================== | |
| 2 | +# Author: Simon-Pierre Boucher <contact@spboucher.ai> | |
| 3 | +# File: creaka/connectors/tavily_seed.py | |
| 4 | +# Desc: Connecteur DÉCOUVERTE à grande échelle — graines de créateurs | |
| 5 | +# québécois moissonnées par le Tavily scout (outils/creator-harvest.py | |
| 6 | +# du dépôt groupe-ka-connecteurs) : handles sociaux extraits des pages | |
| 7 | +# d'annuaires/palmarès/agences QC. Dataset local (aucune requête ici) : | |
| 8 | +# data/seed/qc_creator_seeds.jsonl. L'enrichissement (Apify) vérifie | |
| 9 | +# ensuite l'existence et remplit nom/abonnés/contenu. | |
| 10 | +# ============================================================================== | |
| 11 | +"""Découverte massive par moisson web (Tavily). | |
| 12 | + | |
| 13 | +Chaque ligne du seed = `{"platform": "...", "handle": "..."}`. On crée une | |
| 14 | +fiche par handle avec un compte de plateforme (signal `listes_medias` 0.85 : | |
| 15 | +issu de listes publiques concordantes). Les handles qui n'existent pas seront | |
| 16 | +simplement non enrichis (found=false côté Apify) ; un balayage d'archivage | |
| 17 | +retire à terme les fiches jamais confirmées. But : élargir le bassin de | |
| 18 | +créateurs de plusieurs milliers par vague, sans requête réseau à ce stade. | |
| 19 | +""" | |
| 20 | +from __future__ import annotations | |
| 21 | + | |
| 22 | +import json | |
| 23 | +from pathlib import Path | |
| 24 | + | |
| 25 | +from ..identity import account | |
| 26 | +from ..normalize import canonical_url | |
| 27 | +from ..schema import Creator | |
| 28 | +from .base import BaseConnector | |
| 29 | + | |
| 30 | +SEED_PATH = (Path(__file__).resolve().parent.parent.parent | |
| 31 | + / "data" / "seed" / "qc_creator_seeds.jsonl") | |
| 32 | + | |
| 33 | + | |
| 34 | +class TavilySeedConnector(BaseConnector): | |
| 35 | + source_id = "tavily-seed" | |
| 36 | + kind = "discovery" | |
| 37 | + | |
| 38 | + def fetch(self) -> list[Creator]: | |
| 39 | + if not SEED_PATH.exists(): | |
| 40 | + return [] # pas encore de moisson : passage vide, pas d'erreur | |
| 41 | + creators: list[Creator] = [] | |
| 42 | + seen: set[str] = set() | |
| 43 | + for line in SEED_PATH.read_text(encoding="utf-8").splitlines(): | |
| 44 | + line = line.strip() | |
| 45 | + if not line: | |
| 46 | + continue | |
| 47 | + try: | |
| 48 | + row = json.loads(line) | |
| 49 | + except json.JSONDecodeError: | |
| 50 | + continue | |
| 51 | + platform = (row.get("platform") or "").strip().lower() | |
| 52 | + handle = (row.get("handle") or "").strip().lstrip("@").lower() | |
| 53 | + if not platform or not handle: | |
| 54 | + continue | |
| 55 | + key = f"{platform}:{handle}" | |
| 56 | + if key in seen: | |
| 57 | + continue | |
| 58 | + seen.add(key) | |
| 59 | + try: | |
| 60 | + acc = account(platform, handle, "listes_medias", | |
| 61 | + url=canonical_url(platform, handle)).finalize() | |
| 62 | + except Exception: | |
| 63 | + continue | |
| 64 | + creators.append(Creator( | |
| 65 | + source=self.source_id, | |
| 66 | + external_id=key, | |
| 67 | + display_name=handle, # nom réel rempli à l'enrichissement | |
| 68 | + platforms=[acc], | |
| 69 | + notes="découvert par moisson web Tavily (annuaires/palmarès QC)", | |
| 70 | + )) | |
| 71 | + return creators | |
modified
creaka/ingest.py
+2 −2
@@ -30,10 +30,10 @@ from .dedup import dedupe | ||
| 30 | 30 | # ordre d'exécution des connecteurs d'enrichissement — link-in-bio vers la |
| 31 | 31 | # fin (il consomme les link_in_bio_url des étapes précédentes) ; bio-liens en |
| 32 | 32 | # tout dernier (il relit les bios enrichies, sans aucune requête) |
| 33 | −ENRICH_ORDER = ["instagram-apify", "tiktok-apify", "x-apify", | |
| 33 | +ENRICH_ORDER = ["instagram-apify", "snowball-ig", "tiktok-apify", "x-apify", | |
| 34 | 34 | "facebook-apify", "threads-apify", "snapchat-apify", |
| 35 | 35 | "youtube-apify", "twitch-apify", "kick-apify", |
| 36 | − "fansly-apify", | |
| 36 | + "fansly-apify", "patreon-apify", "discord-apify", | |
| 37 | 37 | "instagram-profil", "tiktok-profil", "youtube", "twitch", |
| 38 | 38 | "x-profil", "balados-rss", "podcastindex", |
| 39 | 39 | "link-in-bio", "bio-liens", "region-bio"] |
added
data/seed/qc_creator_seeds.jsonl
+1271 −0
@@ -0,0 +1,1271 @@ | ||
| 1 | +{"platform": "instagram", "handle": "ppscanada"} | |
| 2 | +{"platform": "instagram", "handle": "engageunhumoriste"} | |
| 3 | +{"platform": "youtube", "handle": "engageunhumoriste"} | |
| 4 | +{"platform": "x", "handle": "etiennefg"} | |
| 5 | +{"platform": "instagram", "handle": "etiennefg"} | |
| 6 | +{"platform": "x", "handle": "icircpremiere"} | |
| 7 | +{"platform": "x", "handle": "lexpresstoronto"} | |
| 8 | +{"platform": "instagram", "handle": "journal_larotonde"} | |
| 9 | +{"platform": "x", "handle": "larotonde"} | |
| 10 | +{"platform": "x", "handle": "historicacanada"} | |
| 11 | +{"platform": "instagram", "handle": "levraijodion"} | |
| 12 | +{"platform": "instagram", "handle": "evelyne.r.m"} | |
| 13 | +{"platform": "x", "handle": "onfr_tfo"} | |
| 14 | +{"platform": "x", "handle": "icirctele"} | |
| 15 | +{"platform": "x", "handle": "radiocanadainfo"} | |
| 16 | +{"platform": "instagram", "handle": "_lebalbuzard"} | |
| 17 | +{"platform": "instagram", "handle": "lecourrierdelanouvelleecosse"} | |
| 18 | +{"platform": "tiktok", "handle": "le.courrier"} | |
| 19 | +{"platform": "youtube", "handle": "lecourrierdelanouvelle-ecosse"} | |
| 20 | +{"platform": "x", "handle": "courrierne1937"} | |
| 21 | +{"platform": "twitch", "handle": "montreal"} | |
| 22 | +{"platform": "twitch", "handle": "events"} | |
| 23 | +{"platform": "instagram", "handle": "seb.lerouxx"} | |
| 24 | +{"platform": "instagram", "handle": "amealbert_"} | |
| 25 | +{"platform": "instagram", "handle": "nu.skin____"} | |
| 26 | +{"platform": "instagram", "handle": "erzu.lie"} | |
| 27 | +{"platform": "instagram", "handle": "canada.council"} | |
| 28 | +{"platform": "tiktok", "handle": "cbcmontreal"} | |
| 29 | +{"platform": "instagram", "handle": "6000mhz"} | |
| 30 | +{"platform": "tiktok", "handle": "lp_lapresse"} | |
| 31 | +{"platform": "x", "handle": "lp_lapresse"} | |
| 32 | +{"platform": "twitch", "handle": "xqc"} | |
| 33 | +{"platform": "x", "handle": "cache"} | |
| 34 | +{"platform": "twitch", "handle": "dominic"} | |
| 35 | +{"platform": "twitch", "handle": "zhartan"} | |
| 36 | +{"platform": "twitch", "handle": "p4sc4l"} | |
| 37 | +{"platform": "twitch", "handle": "th0ny"} | |
| 38 | +{"platform": "twitch", "handle": "marhados"} | |
| 39 | +{"platform": "twitch", "handle": "thelfus"} | |
| 40 | +{"platform": "twitch", "handle": "corstrix"} | |
| 41 | +{"platform": "instagram", "handle": "mathieupellerin"} | |
| 42 | +{"platform": "instagram", "handle": "papimelv"} | |
| 43 | +{"platform": "twitch", "handle": "gfz_parfait"} | |
| 44 | +{"platform": "instagram", "handle": "lewislefou"} | |
| 45 | +{"platform": "instagram", "handle": "cocottee"} | |
| 46 | +{"platform": "instagram", "handle": "elijah"} | |
| 47 | +{"platform": "instagram", "handle": "shahinouest"} | |
| 48 | +{"platform": "instagram", "handle": "gfz.parfait"} | |
| 49 | +{"platform": "instagram", "handle": "alybrassard"} | |
| 50 | +{"platform": "instagram", "handle": "achillefps"} | |
| 51 | +{"platform": "instagram", "handle": "arnaud.od"} | |
| 52 | +{"platform": "instagram", "handle": "commuquebec"} | |
| 53 | +{"platform": "twitch", "handle": "directory"} | |
| 54 | +{"platform": "twitch", "handle": "commuquebec"} | |
| 55 | +{"platform": "x", "handle": "commuquebec"} | |
| 56 | +{"platform": "instagram", "handle": "lelobby.lotoquebec"} | |
| 57 | +{"platform": "youtube", "handle": "lelobby-lotoquebec"} | |
| 58 | +{"platform": "twitch", "handle": "lotoquebec"} | |
| 59 | +{"platform": "twitch", "handle": "acegamersam"} | |
| 60 | +{"platform": "twitch", "handle": "alsenic"} | |
| 61 | +{"platform": "twitch", "handle": "annamoonz"} | |
| 62 | +{"platform": "twitch", "handle": "araashi_"} | |
| 63 | +{"platform": "twitch", "handle": "ashtaal"} | |
| 64 | +{"platform": "twitch", "handle": "avecsimon"} | |
| 65 | +{"platform": "twitch", "handle": "bastienart"} | |
| 66 | +{"platform": "twitch", "handle": "lebergy"} | |
| 67 | +{"platform": "twitch", "handle": "bethlame"} | |
| 68 | +{"platform": "twitch", "handle": "bubblymarie"} | |
| 69 | +{"platform": "twitch", "handle": "cafeinelau"} | |
| 70 | +{"platform": "twitch", "handle": "camgrandebrune"} | |
| 71 | +{"platform": "twitch", "handle": "canellotv"} | |
| 72 | +{"platform": "twitch", "handle": "capt_n_bill"} | |
| 73 | +{"platform": "twitch", "handle": "charest"} | |
| 74 | +{"platform": "twitch", "handle": "charlene"} | |
| 75 | +{"platform": "x", "handle": "fr"} | |
| 76 | +{"platform": "instagram", "handle": "chanou__"} | |
| 77 | +{"platform": "instagram", "handle": "lychesrychee"} | |
| 78 | +{"platform": "instagram", "handle": "thesonofhan"} | |
| 79 | +{"platform": "instagram", "handle": "itzkevtvv"} | |
| 80 | +{"platform": "instagram", "handle": "collabstr"} | |
| 81 | +{"platform": "tiktok", "handle": "collabstr.com"} | |
| 82 | +{"platform": "instagram", "handle": "heyraion"} | |
| 83 | +{"platform": "instagram", "handle": "dwyane101"} | |
| 84 | +{"platform": "instagram", "handle": "kevinhana_"} | |
| 85 | +{"platform": "instagram", "handle": "itslemonsquares"} | |
| 86 | +{"platform": "instagram", "handle": "cadiegrace"} | |
| 87 | +{"platform": "instagram", "handle": "awkventurer"} | |
| 88 | +{"platform": "instagram", "handle": "babyybaconator"} | |
| 89 | +{"platform": "instagram", "handle": "rychee"} | |
| 90 | +{"platform": "instagram", "handle": "farhadxray"} | |
| 91 | +{"platform": "instagram", "handle": "katbyday"} | |
| 92 | +{"platform": "instagram", "handle": "ermillyy"} | |
| 93 | +{"platform": "instagram", "handle": "thechocolatecanvas"} | |
| 94 | +{"platform": "instagram", "handle": "queenglitterchaos"} | |
| 95 | +{"platform": "instagram", "handle": "yeaitsmt"} | |
| 96 | +{"platform": "instagram", "handle": "reaperky7"} | |
| 97 | +{"platform": "instagram", "handle": "villanarei"} | |
| 98 | +{"platform": "instagram", "handle": "ggria"} | |
| 99 | +{"platform": "instagram", "handle": "itsbenmalka"} | |
| 100 | +{"platform": "instagram", "handle": "chanou"} | |
| 101 | +{"platform": "instagram", "handle": "kevinhana"} | |
| 102 | +{"platform": "instagram", "handle": "ogrobinson10"} | |
| 103 | +{"platform": "instagram", "handle": "marcelo"} | |
| 104 | +{"platform": "instagram", "handle": "shinanova"} | |
| 105 | +{"platform": "instagram", "handle": "victoriacharlton"} | |
| 106 | +{"platform": "instagram", "handle": "oliprimeau"} | |
| 107 | +{"platform": "instagram", "handle": "lysandrenadeau"} | |
| 108 | +{"platform": "instagram", "handle": "enola.bedard"} | |
| 109 | +{"platform": "instagram", "handle": "sj.bleau"} | |
| 110 | +{"platform": "instagram", "handle": "laurent.dagenais"} | |
| 111 | +{"platform": "instagram", "handle": "aliciamoffet"} | |
| 112 | +{"platform": "instagram", "handle": "olivierprimeaubc"} | |
| 113 | +{"platform": "instagram", "handle": "elisabethrioux"} | |
| 114 | +{"platform": "instagram", "handle": "lefitcook"} | |
| 115 | +{"platform": "instagram", "handle": "claudiemercier_"} | |
| 116 | +{"platform": "instagram", "handle": "marc_fitt"} | |
| 117 | +{"platform": "instagram", "handle": "victoria.charlton"} | |
| 118 | +{"platform": "instagram", "handle": "maxgourgues"} | |
| 119 | +{"platform": "instagram", "handle": "lucierheaume"} | |
| 120 | +{"platform": "instagram", "handle": "rosalielessard_"} | |
| 121 | +{"platform": "tiktok", "handle": "enola.bedard"} | |
| 122 | +{"platform": "tiktok", "handle": "sjbleau"} | |
| 123 | +{"platform": "tiktok", "handle": "laurent.dagenais"} | |
| 124 | +{"platform": "tiktok", "handle": "shinanova"} | |
| 125 | +{"platform": "tiktok", "handle": "aliciamoffet"} | |
| 126 | +{"platform": "tiktok", "handle": "oliprimeau"} | |
| 127 | +{"platform": "tiktok", "handle": "lysandrenadeau"} | |
| 128 | +{"platform": "tiktok", "handle": "elisabeth.rioux"} | |
| 129 | +{"platform": "tiktok", "handle": "lefitcook"} | |
| 130 | +{"platform": "tiktok", "handle": "claudiemercier"} | |
| 131 | +{"platform": "tiktok", "handle": "victoriacharltonn"} | |
| 132 | +{"platform": "tiktok", "handle": "maxgourgues"} | |
| 133 | +{"platform": "tiktok", "handle": "lucie_rheaume"} | |
| 134 | +{"platform": "tiktok", "handle": "rosalielessard_"} | |
| 135 | +{"platform": "youtube", "handle": "enola.bedard"} | |
| 136 | +{"platform": "youtube", "handle": "sjbleau"} | |
| 137 | +{"platform": "youtube", "handle": "laurentdagenais"} | |
| 138 | +{"platform": "youtube", "handle": "shinanovayt"} | |
| 139 | +{"platform": "youtube", "handle": "aliciamoffetchannel"} | |
| 140 | +{"platform": "youtube", "handle": "olivierprimeau"} | |
| 141 | +{"platform": "youtube", "handle": "lysandrenadeau"} | |
| 142 | +{"platform": "youtube", "handle": "elisabethrioux7657"} | |
| 143 | +{"platform": "youtube", "handle": "lefitcook"} | |
| 144 | +{"platform": "youtube", "handle": "claudiemercier"} | |
| 145 | +{"platform": "youtube", "handle": "marcfitt"} | |
| 146 | +{"platform": "youtube", "handle": "victoriacharlton"} | |
| 147 | +{"platform": "youtube", "handle": "maxgourgues7062"} | |
| 148 | +{"platform": "youtube", "handle": "lucierheaume6512"} | |
| 149 | +{"platform": "youtube", "handle": "rosalielessardd"} | |
| 150 | +{"platform": "instagram", "handle": "sjbleau"} | |
| 151 | +{"platform": "instagram", "handle": "elisabeth.rioux"} | |
| 152 | +{"platform": "instagram", "handle": "claudiemercier"} | |
| 153 | +{"platform": "instagram", "handle": "marcfitt"} | |
| 154 | +{"platform": "instagram", "handle": "lucie"} | |
| 155 | +{"platform": "instagram", "handle": "rosalielessard"} | |
| 156 | +{"platform": "twitch", "handle": "quebec"} | |
| 157 | +{"platform": "twitch", "handle": "twitch"} | |
| 158 | +{"platform": "twitch", "handle": "assets"} | |
| 159 | +{"platform": "twitch", "handle": "videos"} | |
| 160 | +{"platform": "twitch", "handle": "inlacrimaelacrima"} | |
| 161 | +{"platform": "twitch", "handle": "acadianwoman"} | |
| 162 | +{"platform": "twitch", "handle": "alisonator"} | |
| 163 | +{"platform": "tiktok", "handle": "alisonation"} | |
| 164 | +{"platform": "twitch", "handle": "acadie"} | |
| 165 | +{"platform": "twitch", "handle": "acadiestream"} | |
| 166 | +{"platform": "x", "handle": "foxacadian"} | |
| 167 | +{"platform": "instagram", "handle": "foxacadian"} | |
| 168 | +{"platform": "instagram", "handle": "xboxuk"} | |
| 169 | +{"platform": "instagram", "handle": "noblechairs"} | |
| 170 | +{"platform": "instagram", "handle": "bethesda_uk"} | |
| 171 | +{"platform": "twitch", "handle": "acadianfox"} | |
| 172 | +{"platform": "x", "handle": "compose"} | |
| 173 | +{"platform": "x", "handle": "pixelatedvicka"} | |
| 174 | +{"platform": "x", "handle": "ff_xiv_en"} | |
| 175 | +{"platform": "x", "handle": "xboxuk"} | |
| 176 | +{"platform": "x", "handle": "xbox"} | |
| 177 | +{"platform": "x", "handle": "noblechairs"} | |
| 178 | +{"platform": "x", "handle": "bethesda_uk"} | |
| 179 | +{"platform": "x", "handle": "tos"} | |
| 180 | +{"platform": "x", "handle": "privacy"} | |
| 181 | +{"platform": "x", "handle": "articles"} | |
| 182 | +{"platform": "x", "handle": "resources"} | |
| 183 | +{"platform": "x", "handle": "en"} | |
| 184 | +{"platform": "instagram", "handle": "pixelatedvicka"} | |
| 185 | +{"platform": "instagram", "handle": "ff_xiv_en"} | |
| 186 | +{"platform": "instagram", "handle": "cbc"} | |
| 187 | +{"platform": "x", "handle": "cbc"} | |
| 188 | +{"platform": "tiktok", "handle": "alisonator"} | |
| 189 | +{"platform": "instagram", "handle": "minutemaquillage"} | |
| 190 | +{"platform": "instagram", "handle": "jeanfrancoiscd"} | |
| 191 | +{"platform": "instagram", "handle": "avedacanada"} | |
| 192 | +{"platform": "instagram", "handle": "virginievandelac"} | |
| 193 | +{"platform": "x", "handle": "vvandelac"} | |
| 194 | +{"platform": "instagram", "handle": "artistparmarilyn"} | |
| 195 | +{"platform": "tiktok", "handle": "artistparmarilyn"} | |
| 196 | +{"platform": "youtube", "handle": "artistparmarilyn"} | |
| 197 | +{"platform": "instagram", "handle": "lilirougecosmetics"} | |
| 198 | +{"platform": "tiktok", "handle": "lilirougecosmetics"} | |
| 199 | +{"platform": "instagram", "handle": "lapetitevengeance"} | |
| 200 | +{"platform": "instagram", "handle": "marcomarsolais"} | |
| 201 | +{"platform": "instagram", "handle": "aj.makeup"} | |
| 202 | +{"platform": "instagram", "handle": "sabiehairstylist"} | |
| 203 | +{"platform": "instagram", "handle": "luggageandlipstick"} | |
| 204 | +{"platform": "x", "handle": "luggage_lipstik"} | |
| 205 | +{"platform": "instagram", "handle": "bontraveler"} | |
| 206 | +{"platform": "instagram", "handle": "dominicpoirot"} | |
| 207 | +{"platform": "instagram", "handle": "lfayos"} | |
| 208 | +{"platform": "instagram", "handle": "loredana"} | |
| 209 | +{"platform": "instagram", "handle": "miss"} | |
| 210 | +{"platform": "instagram", "handle": "dermacureqc"} | |
| 211 | +{"platform": "instagram", "handle": "emmasroadmap"} | |
| 212 | +{"platform": "instagram", "handle": "antonioortegacouture"} | |
| 213 | +{"platform": "instagram", "handle": "mmodemtl"} | |
| 214 | +{"platform": "tiktok", "handle": "mmodemtl"} | |
| 215 | +{"platform": "youtube", "handle": "mmodelagrappemetropolitain4872"} | |
| 216 | +{"platform": "x", "handle": "linbleu"} | |
| 217 | +{"platform": "x", "handle": "gouvqc"} | |
| 218 | +{"platform": "instagram", "handle": "ellequebec"} | |
| 219 | +{"platform": "tiktok", "handle": "ellequebec"} | |
| 220 | +{"platform": "x", "handle": "ellequebec"} | |
| 221 | +{"platform": "instagram", "handle": "fringueefutee"} | |
| 222 | +{"platform": "instagram", "handle": "urbainedeschamps"} | |
| 223 | +{"platform": "instagram", "handle": "cestelle.ca"} | |
| 224 | +{"platform": "tiktok", "handle": "cestelle.ca"} | |
| 225 | +{"platform": "x", "handle": "cestellemode"} | |
| 226 | +{"platform": "instagram", "handle": "centrerockland"} | |
| 227 | +{"platform": "x", "handle": "centrerockland"} | |
| 228 | +{"platform": "instagram", "handle": "destinationnb"} | |
| 229 | +{"platform": "instagram", "handle": "village_acadien"} | |
| 230 | +{"platform": "youtube", "handle": "villagehistoriqueacadien_nb"} | |
| 231 | +{"platform": "instagram", "handle": "clubsportifmaa"} | |
| 232 | +{"platform": "instagram", "handle": "timeoutmontreal"} | |
| 233 | +{"platform": "instagram", "handle": "b52fit"} | |
| 234 | +{"platform": "instagram", "handle": "epix"} | |
| 235 | +{"platform": "instagram", "handle": "morphobleu.studio"} | |
| 236 | +{"platform": "instagram", "handle": "monstergymmtl"} | |
| 237 | +{"platform": "instagram", "handle": "cepsum"} | |
| 238 | +{"platform": "x", "handle": "cflri_icrcp"} | |
| 239 | +{"platform": "instagram", "handle": "econofitness"} | |
| 240 | +{"platform": "instagram", "handle": "jessica.b.25"} | |
| 241 | +{"platform": "instagram", "handle": "laulabo"} | |
| 242 | +{"platform": "instagram", "handle": "kaily"} | |
| 243 | +{"platform": "instagram", "handle": "fitnesssanteplus"} | |
| 244 | +{"platform": "tiktok", "handle": "fitnesssanteplus"} | |
| 245 | +{"platform": "instagram", "handle": "_chez_ashton_"} | |
| 246 | +{"platform": "instagram", "handle": "_qu"} | |
| 247 | +{"platform": "instagram", "handle": "_la_banquise_"} | |
| 248 | +{"platform": "instagram", "handle": "_le_plateau_"} | |
| 249 | +{"platform": "instagram", "handle": "_montr"} | |
| 250 | +{"platform": "instagram", "handle": "_poutineville_"} | |
| 251 | +{"platform": "instagram", "handle": "mywanderingvoyage"} | |
| 252 | +{"platform": "tiktok", "handle": "mywanderingvoyage"} | |
| 253 | +{"platform": "youtube", "handle": "mywanderingvoyage"} | |
| 254 | +{"platform": "instagram", "handle": "ontario"} | |
| 255 | +{"platform": "instagram", "handle": "scichefqc"} | |
| 256 | +{"platform": "x", "handle": "scichefqc"} | |
| 257 | +{"platform": "x", "handle": "francoislegault"} | |
| 258 | +{"platform": "instagram", "handle": "francoislegault"} | |
| 259 | +{"platform": "instagram", "handle": "frederiqueguay"} | |
| 260 | +{"platform": "x", "handle": "frederiqueguay"} | |
| 261 | +{"platform": "instagram", "handle": "urbanblisslife"} | |
| 262 | +{"platform": "tiktok", "handle": "urbanblisslife"} | |
| 263 | +{"platform": "x", "handle": "urbanblisslife"} | |
| 264 | +{"platform": "instagram", "handle": "noussommes.cafe"} | |
| 265 | +{"platform": "instagram", "handle": "berniebeigne"} | |
| 266 | +{"platform": "instagram", "handle": "lindork"} | |
| 267 | +{"platform": "instagram", "handle": "smithani"} | |
| 268 | +{"platform": "instagram", "handle": "suko287"} | |
| 269 | +{"platform": "instagram", "handle": "pamelinachang"} | |
| 270 | +{"platform": "instagram", "handle": "ginger"} | |
| 271 | +{"platform": "instagram", "handle": "erinbayly"} | |
| 272 | +{"platform": "instagram", "handle": "patisserie.coco"} | |
| 273 | +{"platform": "instagram", "handle": "kinkaizakayamtl"} | |
| 274 | +{"platform": "instagram", "handle": "raviolismaixiangyuan"} | |
| 275 | +{"platform": "instagram", "handle": "ottoyakitori"} | |
| 276 | +{"platform": "instagram", "handle": "fairmountbagel"} | |
| 277 | +{"platform": "instagram", "handle": "stviateurbagel"} | |
| 278 | +{"platform": "instagram", "handle": "bargeorgemtl"} | |
| 279 | +{"platform": "instagram", "handle": "lemalnecessaire"} | |
| 280 | +{"platform": "instagram", "handle": "lepetitdep"} | |
| 281 | +{"platform": "instagram", "handle": "kemcoba"} | |
| 282 | +{"platform": "instagram", "handle": "ladiperie"} | |
| 283 | +{"platform": "instagram", "handle": "zettiscremerie"} | |
| 284 | +{"platform": "instagram", "handle": "gibeauorangejulep"} | |
| 285 | +{"platform": "instagram", "handle": "restaurantaupieddecochon"} | |
| 286 | +{"platform": "instagram", "handle": "restaurant_cadet"} | |
| 287 | +{"platform": "instagram", "handle": "fiorellinosnackbar"} | |
| 288 | +{"platform": "instagram", "handle": "boustanrestaurant"} | |
| 289 | +{"platform": "instagram", "handle": "restolabanquise"} | |
| 290 | +{"platform": "instagram", "handle": "restobarmontrealpoutine"} | |
| 291 | +{"platform": "instagram", "handle": "schwartzsofficial"} | |
| 292 | +{"platform": "instagram", "handle": "ginger_mariah"} | |
| 293 | +{"platform": "instagram", "handle": "larisaopar"} | |
| 294 | +{"platform": "instagram", "handle": "biancaangotti"} | |
| 295 | +{"platform": "instagram", "handle": "jillds"} | |
| 296 | +{"platform": "instagram", "handle": "chels.robbins"} | |
| 297 | +{"platform": "instagram", "handle": "jengeegee"} | |
| 298 | +{"platform": "instagram", "handle": "shevonlam"} | |
| 299 | +{"platform": "instagram", "handle": "anisha_natalie"} | |
| 300 | +{"platform": "instagram", "handle": "gina._._marie"} | |
| 301 | +{"platform": "instagram", "handle": "dani.kuni"} | |
| 302 | +{"platform": "instagram", "handle": "maryannstep"} | |
| 303 | +{"platform": "instagram", "handle": "hopeful_li_soon"} | |
| 304 | +{"platform": "instagram", "handle": "fromnikiwithlove"} | |
| 305 | +{"platform": "instagram", "handle": "debs_wolf"} | |
| 306 | +{"platform": "instagram", "handle": "piggtailgirl"} | |
| 307 | +{"platform": "instagram", "handle": "rachelsrunway"} | |
| 308 | +{"platform": "instagram", "handle": "sketpicaljess"} | |
| 309 | +{"platform": "instagram", "handle": "justalillost"} | |
| 310 | +{"platform": "instagram", "handle": "elliotgaltgirl"} | |
| 311 | +{"platform": "instagram", "handle": "dr.neuroshannon"} | |
| 312 | +{"platform": "instagram", "handle": "sparrowandherbabies"} | |
| 313 | +{"platform": "instagram", "handle": "hiphu"} | |
| 314 | +{"platform": "instagram", "handle": "ansareece"} | |
| 315 | +{"platform": "instagram", "handle": "donopon"} | |
| 316 | +{"platform": "instagram", "handle": "hip_bean"} | |
| 317 | +{"platform": "instagram", "handle": "jaypeacee"} | |
| 318 | +{"platform": "instagram", "handle": "miktacular"} | |
| 319 | +{"platform": "instagram", "handle": "_paula.espinoza_"} | |
| 320 | +{"platform": "instagram", "handle": "dgordaneer"} | |
| 321 | +{"platform": "instagram", "handle": "pundogz"} | |
| 322 | +{"platform": "instagram", "handle": "anothernisha"} | |
| 323 | +{"platform": "instagram", "handle": "michelle835"} | |
| 324 | +{"platform": "instagram", "handle": "violet_pretty"} | |
| 325 | +{"platform": "instagram", "handle": "lillhabits"} | |
| 326 | +{"platform": "instagram", "handle": "habanerogal"} | |
| 327 | +{"platform": "instagram", "handle": "hojurific81"} | |
| 328 | +{"platform": "instagram", "handle": "devonhamplas"} | |
| 329 | +{"platform": "instagram", "handle": "dani_beee"} | |
| 330 | +{"platform": "instagram", "handle": "hunkaa.a"} | |
| 331 | +{"platform": "instagram", "handle": "adventuresofdustydoodle"} | |
| 332 | +{"platform": "instagram", "handle": "bestofshi"} | |
| 333 | +{"platform": "instagram", "handle": "asianting24"} | |
| 334 | +{"platform": "instagram", "handle": "shanss33"} | |
| 335 | +{"platform": "instagram", "handle": "miss_erin"} | |
| 336 | +{"platform": "instagram", "handle": "maepiq"} | |
| 337 | +{"platform": "instagram", "handle": "leslievarty"} | |
| 338 | +{"platform": "instagram", "handle": "mxmlvanity"} | |
| 339 | +{"platform": "instagram", "handle": "ofeliamtl2014"} | |
| 340 | +{"platform": "instagram", "handle": "kristenanto"} | |
| 341 | +{"platform": "instagram", "handle": "northernmint"} | |
| 342 | +{"platform": "instagram", "handle": "phoenixindacity"} | |
| 343 | +{"platform": "instagram", "handle": "kormachameleon"} | |
| 344 | +{"platform": "instagram", "handle": "liiveitout"} | |
| 345 | +{"platform": "instagram", "handle": "bom.yeg"} | |
| 346 | +{"platform": "instagram", "handle": "willing_an_abel"} | |
| 347 | +{"platform": "instagram", "handle": "natalie.mw"} | |
| 348 | +{"platform": "instagram", "handle": "jennie_fer"} | |
| 349 | +{"platform": "instagram", "handle": "alexandrabeley"} | |
| 350 | +{"platform": "instagram", "handle": "activechacha"} | |
| 351 | +{"platform": "instagram", "handle": "katierainboww"} | |
| 352 | +{"platform": "instagram", "handle": "thatjenk"} | |
| 353 | +{"platform": "instagram", "handle": "joannechau7"} | |
| 354 | +{"platform": "instagram", "handle": "globaljesus"} | |
| 355 | +{"platform": "instagram", "handle": "lieu.ski"} | |
| 356 | +{"platform": "instagram", "handle": "cup_of_josephine"} | |
| 357 | +{"platform": "instagram", "handle": "argenplath"} | |
| 358 | +{"platform": "instagram", "handle": "mig14"} | |
| 359 | +{"platform": "instagram", "handle": "genevieveshylo"} | |
| 360 | +{"platform": "tiktok", "handle": "lindorable"} | |
| 361 | +{"platform": "x", "handle": "lindork"} | |
| 362 | +{"platform": "x", "handle": "stviateurbagel"} | |
| 363 | +{"platform": "x", "handle": "pieddecochonmtl"} | |
| 364 | +{"platform": "x", "handle": "boustanmontreal"} | |
| 365 | +{"platform": "x", "handle": "montrealpoutine"} | |
| 366 | +{"platform": "instagram", "handle": "anisha"} | |
| 367 | +{"platform": "instagram", "handle": "gina"} | |
| 368 | +{"platform": "instagram", "handle": "hopeful"} | |
| 369 | +{"platform": "instagram", "handle": "debs"} | |
| 370 | +{"platform": "instagram", "handle": "rumbiman"} | |
| 371 | +{"platform": "instagram", "handle": "hip"} | |
| 372 | +{"platform": "instagram", "handle": "violet"} | |
| 373 | +{"platform": "instagram", "handle": "dani"} | |
| 374 | +{"platform": "instagram", "handle": "rwlovesfood"} | |
| 375 | +{"platform": "instagram", "handle": "arthursmtl"} | |
| 376 | +{"platform": "instagram", "handle": "willing"} | |
| 377 | +{"platform": "instagram", "handle": "jennie"} | |
| 378 | +{"platform": "instagram", "handle": "cup"} | |
| 379 | +{"platform": "instagram", "handle": "ohayocafemtl"} | |
| 380 | +{"platform": "instagram", "handle": "mapoulemouillee"} | |
| 381 | +{"platform": "instagram", "handle": "marcisurlaplaza"} | |
| 382 | +{"platform": "instagram", "handle": "tovogueorbust"} | |
| 383 | +{"platform": "x", "handle": "tovogueorbust"} | |
| 384 | +{"platform": "instagram", "handle": "glowtherapy"} | |
| 385 | +{"platform": "instagram", "handle": "mollylowerealtor"} | |
| 386 | +{"platform": "instagram", "handle": "mosaic_homes"} | |
| 387 | +{"platform": "instagram", "handle": "passion.escalade"} | |
| 388 | +{"platform": "instagram", "handle": "canyoningquebec"} | |
| 389 | +{"platform": "instagram", "handle": "au_canot_volant"} | |
| 390 | +{"platform": "instagram", "handle": "flora.bidaud"} | |
| 391 | +{"platform": "instagram", "handle": "ferme5etoiles"} | |
| 392 | +{"platform": "instagram", "handle": "meretmonde"} | |
| 393 | +{"platform": "instagram", "handle": "parckiamika"} | |
| 394 | +{"platform": "instagram", "handle": "parcpoissonblanc"} | |
| 395 | +{"platform": "instagram", "handle": "noryak_aventures"} | |
| 396 | +{"platform": "instagram", "handle": "noryak"} | |
| 397 | +{"platform": "instagram", "handle": "duvetnor"} | |
| 398 | +{"platform": "instagram", "handle": "echappee.bleue"} | |
| 399 | +{"platform": "instagram", "handle": "aventurequebec"} | |
| 400 | +{"platform": "instagram", "handle": "nature_aventure"} | |
| 401 | +{"platform": "instagram", "handle": "attitudenordique"} | |
| 402 | +{"platform": "instagram", "handle": "lesvagueshsp"} | |
| 403 | +{"platform": "instagram", "handle": "nature"} | |
| 404 | +{"platform": "instagram", "handle": "ottawatourism"} | |
| 405 | +{"platform": "tiktok", "handle": "ottawatourism"} | |
| 406 | +{"platform": "instagram", "handle": "liftoronto"} | |
| 407 | +{"platform": "youtube", "handle": "acpnation"} | |
| 408 | +{"platform": "x", "handle": "acpnation"} | |
| 409 | +{"platform": "x", "handle": "tele_mag_quebec"} | |
| 410 | +{"platform": "instagram", "handle": "tourismeontario"} | |
| 411 | +{"platform": "instagram", "handle": "_seripop_"} | |
| 412 | +{"platform": "instagram", "handle": "spotify"} | |
| 413 | +{"platform": "x", "handle": "spotify"} | |
| 414 | +{"platform": "instagram", "handle": "francomusique"} | |
| 415 | +{"platform": "x", "handle": "rocharchambault"} | |
| 416 | +{"platform": "instagram", "handle": "francaisavenir"} | |
| 417 | +{"platform": "x", "handle": "francaisavenir"} | |
| 418 | +{"platform": "instagram", "handle": "af_ottawa"} | |
| 419 | +{"platform": "x", "handle": "afottawa"} | |
| 420 | +{"platform": "instagram", "handle": "safwanmtl"} | |
| 421 | +{"platform": "instagram", "handle": "_celine_dion_concert.jpg"} | |
| 422 | +{"platform": "instagram", "handle": "hhqcofficiel"} | |
| 423 | +{"platform": "x", "handle": "hhqc"} | |
| 424 | +{"platform": "x", "handle": "hockeyrapper"} | |
| 425 | +{"platform": "instagram", "handle": "impac5canada"} | |
| 426 | +{"platform": "x", "handle": "impac5canada"} | |
| 427 | +{"platform": "instagram", "handle": "mtlelectronicmusic"} | |
| 428 | +{"platform": "instagram", "handle": "polyson"} | |
| 429 | +{"platform": "x", "handle": "edmmontreal"} | |
| 430 | +{"platform": "instagram", "handle": "edmtrain"} | |
| 431 | +{"platform": "instagram", "handle": "cassian"} | |
| 432 | +{"platform": "instagram", "handle": "bushbabybeats"} | |
| 433 | +{"platform": "instagram", "handle": "codymusic_"} | |
| 434 | +{"platform": "instagram", "handle": "whalesfm"} | |
| 435 | +{"platform": "instagram", "handle": "duskymusic"} | |
| 436 | +{"platform": "instagram", "handle": "romanceplanet"} | |
| 437 | +{"platform": "instagram", "handle": "avenueonemusic"} | |
| 438 | +{"platform": "instagram", "handle": "catalystgmail.com2"} | |
| 439 | +{"platform": "instagram", "handle": "sietch514"} | |
| 440 | +{"platform": "instagram", "handle": "rosasharin"} | |
| 441 | +{"platform": "instagram", "handle": "flytzmusic"} | |
| 442 | +{"platform": "instagram", "handle": "giorgia_angiuli"} | |
| 443 | +{"platform": "instagram", "handle": "felixpatry_"} | |
| 444 | +{"platform": "instagram", "handle": "kendal_ritmofatale"} | |
| 445 | +{"platform": "instagram", "handle": "mcmandiz"} | |
| 446 | +{"platform": "instagram", "handle": "noprospectscollective"} | |
| 447 | +{"platform": "instagram", "handle": "t78official"} | |
| 448 | +{"platform": "youtube", "handle": "emersonwoolf"} | |
| 449 | +{"platform": "instagram", "handle": "djprosper22"} | |
| 450 | +{"platform": "instagram", "handle": "1djjfro"} | |
| 451 | +{"platform": "instagram", "handle": "shiftermagazine"} | |
| 452 | +{"platform": "x", "handle": "shiftermagazine"} | |
| 453 | +{"platform": "instagram", "handle": "mrfloetic"} | |
| 454 | +{"platform": "instagram", "handle": "rxckz"} | |
| 455 | +{"platform": "instagram", "handle": "nightafternight"} | |
| 456 | +{"platform": "instagram", "handle": "eazyeldee"} | |
| 457 | +{"platform": "instagram", "handle": "djcsik"} | |
| 458 | +{"platform": "instagram", "handle": "sebcwestcoast"} | |
| 459 | +{"platform": "instagram", "handle": "djandre905"} | |
| 460 | +{"platform": "instagram", "handle": "rocswellradio"} | |
| 461 | +{"platform": "instagram", "handle": "dj.ftp"} | |
| 462 | +{"platform": "instagram", "handle": "topkatamazona"} | |
| 463 | +{"platform": "instagram", "handle": "godfather"} | |
| 464 | +{"platform": "instagram", "handle": "djfrankvinatra"} | |
| 465 | +{"platform": "instagram", "handle": "iamdjfusion"} | |
| 466 | +{"platform": "instagram", "handle": "icytouch"} | |
| 467 | +{"platform": "instagram", "handle": "djrychkydd"} | |
| 468 | +{"platform": "instagram", "handle": "lecolededansedequebec"} | |
| 469 | +{"platform": "instagram", "handle": "revuejeu"} | |
| 470 | +{"platform": "instagram", "handle": "enmoderythme"} | |
| 471 | +{"platform": "tiktok", "handle": "rythme105.7"} | |
| 472 | +{"platform": "youtube", "handle": "cogecomedia"} | |
| 473 | +{"platform": "x", "handle": "zaptele"} | |
| 474 | +{"platform": "instagram", "handle": "agence.m"} | |
| 475 | +{"platform": "instagram", "handle": "policy"} | |
| 476 | +{"platform": "instagram", "handle": "motelstudio"} | |
| 477 | +{"platform": "instagram", "handle": "moniteuracadien"} | |
| 478 | +{"platform": "tiktok", "handle": "jasonjouellette"} | |
| 479 | +{"platform": "youtube", "handle": "lemoniteuracadien"} | |
| 480 | +{"platform": "instagram", "handle": "onf_nfb"} | |
| 481 | +{"platform": "tiktok", "handle": "nfb_onf"} | |
| 482 | +{"platform": "x", "handle": "onf"} | |
| 483 | +{"platform": "instagram", "handle": "imdb"} | |
| 484 | +{"platform": "tiktok", "handle": "imdb"} | |
| 485 | +{"platform": "x", "handle": "imdb"} | |
| 486 | +{"platform": "instagram", "handle": "forteartists"} | |
| 487 | +{"platform": "instagram", "handle": "agence_ada"} | |
| 488 | +{"platform": "x", "handle": "adultes"} | |
| 489 | +{"platform": "x", "handle": "adolescents"} | |
| 490 | +{"platform": "x", "handle": "enfants"} | |
| 491 | +{"platform": "x", "handle": "voix"} | |
| 492 | +{"platform": "x", "handle": "variete"} | |
| 493 | +{"platform": "x", "handle": "agence"} | |
| 494 | +{"platform": "x", "handle": "ecole"} | |
| 495 | +{"platform": "x", "handle": "devenir"} | |
| 496 | +{"platform": "instagram", "handle": "agencechantalbrossard"} | |
| 497 | +{"platform": "instagram", "handle": "moffattariane"} | |
| 498 | +{"platform": "instagram", "handle": "anneelisabethbosse"} | |
| 499 | +{"platform": "instagram", "handle": "abeillegelinas"} | |
| 500 | +{"platform": "instagram", "handle": "emilybegin"} | |
| 501 | +{"platform": "instagram", "handle": "karinevanasse"} | |
| 502 | +{"platform": "instagram", "handle": "wonderwomanpicture"} | |
| 503 | +{"platform": "instagram", "handle": "magalielb"} | |
| 504 | +{"platform": "instagram", "handle": "julebreton"} | |
| 505 | +{"platform": "instagram", "handle": "mariloupwolfe"} | |
| 506 | +{"platform": "instagram", "handle": "mag_clindoeil"} | |
| 507 | +{"platform": "tiktok", "handle": "clindoeil.mag"} | |
| 508 | +{"platform": "instagram", "handle": "rebeccamakonnen"} | |
| 509 | +{"platform": "instagram", "handle": "sophiecads"} | |
| 510 | +{"platform": "instagram", "handle": "marieevelynelessard"} | |
| 511 | +{"platform": "instagram", "handle": "mariesoleildion"} | |
| 512 | +{"platform": "instagram", "handle": "kim_lizotte"} | |
| 513 | +{"platform": "instagram", "handle": "virginie_coossa"} | |
| 514 | +{"platform": "instagram", "handle": "waitresslacomediemusicale"} | |
| 515 | +{"platform": "instagram", "handle": "claudineprevost"} | |
| 516 | +{"platform": "instagram", "handle": "moniachokri"} | |
| 517 | +{"platform": "x", "handle": "cinemas"} | |
| 518 | +{"platform": "x", "handle": "activite"} | |
| 519 | +{"platform": "tiktok", "handle": "withnounna"} | |
| 520 | +{"platform": "instagram", "handle": "geneanet_officiel"} | |
| 521 | +{"platform": "tiktok", "handle": "geneanet"} | |
| 522 | +{"platform": "x", "handle": "geneanet"} | |
| 523 | +{"platform": "instagram", "handle": "bvachet"} | |
| 524 | +{"platform": "x", "handle": "bvachet"} | |
| 525 | +{"platform": "instagram", "handle": "maisondesparentsqc"} | |
| 526 | +{"platform": "instagram", "handle": "federationparentsacadiensne"} | |
| 527 | +{"platform": "youtube", "handle": "federationdesparentsacadie2075"} | |
| 528 | +{"platform": "instagram", "handle": "csap.officiel"} | |
| 529 | +{"platform": "x", "handle": "arsbfc"} | |
| 530 | +{"platform": "instagram", "handle": "ubereats"} | |
| 531 | +{"platform": "x", "handle": "ubereats"} | |
| 532 | +{"platform": "instagram", "handle": "santequebec.csmtl"} | |
| 533 | +{"platform": "youtube", "handle": "santequebec.csimtl"} | |
| 534 | +{"platform": "x", "handle": "montrealcc"} | |
| 535 | +{"platform": "x", "handle": "lacnpf"} | |
| 536 | +{"platform": "instagram", "handle": "fcfacanada"} | |
| 537 | +{"platform": "x", "handle": "fcfacanada"} | |
| 538 | +{"platform": "instagram", "handle": "samueltessierphotographe"} | |
| 539 | +{"platform": "youtube", "handle": "hellodarwin8652"} | |
| 540 | +{"platform": "instagram", "handle": "anniesimardphoto"} | |
| 541 | +{"platform": "instagram", "handle": "royaltonbavaroresort"} | |
| 542 | +{"platform": "instagram", "handle": "kaudet100"} | |
| 543 | +{"platform": "instagram", "handle": "fairmont"} | |
| 544 | +{"platform": "instagram", "handle": "fairmontfrontenac"} | |
| 545 | +{"platform": "instagram", "handle": "sparksmariages"} | |
| 546 | +{"platform": "instagram", "handle": "elodiefleuriste"} | |
| 547 | +{"platform": "instagram", "handle": "djkevinolsen"} | |
| 548 | +{"platform": "instagram", "handle": "lavieestunefete.ca"} | |
| 549 | +{"platform": "instagram", "handle": "groupeabp"} | |
| 550 | +{"platform": "instagram", "handle": "4elevation.ca"} | |
| 551 | +{"platform": "instagram", "handle": "manoirhovey"} | |
| 552 | +{"platform": "instagram", "handle": "alicemonnierphotographie"} | |
| 553 | +{"platform": "instagram", "handle": "anniegagnonphotographie"} | |
| 554 | +{"platform": "instagram", "handle": "highlightmarysebelanger"} | |
| 555 | +{"platform": "instagram", "handle": "madamealicefleuristestecath"} | |
| 556 | +{"platform": "instagram", "handle": "loccasion_dembellir"} | |
| 557 | +{"platform": "instagram", "handle": "highlight_maryse_belanger"} | |
| 558 | +{"platform": "instagram", "handle": "dreamityourselfmontreal"} | |
| 559 | +{"platform": "instagram", "handle": "montreal_bandindelloye"} | |
| 560 | +{"platform": "instagram", "handle": "mimosadesign.invitations"} | |
| 561 | +{"platform": "instagram", "handle": "lafleur_sucree"} | |
| 562 | +{"platform": "instagram", "handle": "justinequintaljewellery"} | |
| 563 | +{"platform": "instagram", "handle": "yasminerosedesigner"} | |
| 564 | +{"platform": "instagram", "handle": "meggie_lapointe"} | |
| 565 | +{"platform": "instagram", "handle": "maxalexleblanc"} | |
| 566 | +{"platform": "instagram", "handle": "missis101"} | |
| 567 | +{"platform": "instagram", "handle": "makeupbyalexandra.p"} | |
| 568 | +{"platform": "instagram", "handle": "marysewithlove"} | |
| 569 | +{"platform": "instagram", "handle": "aubergesaintantoine"} | |
| 570 | +{"platform": "instagram", "handle": "emiliesoprano"} | |
| 571 | +{"platform": "instagram", "handle": "cathylessardphoto"} | |
| 572 | +{"platform": "instagram", "handle": "so_lia"} | |
| 573 | +{"platform": "instagram", "handle": "helly819"} | |
| 574 | +{"platform": "instagram", "handle": "lamarieusesophiesamson"} | |
| 575 | +{"platform": "instagram", "handle": "sandosplayacar"} | |
| 576 | +{"platform": "instagram", "handle": "maebonnetphotographe"} | |
| 577 | +{"platform": "instagram", "handle": "alwaysplayingwithmakeup"} | |
| 578 | +{"platform": "instagram", "handle": "mart.menardimage"} | |
| 579 | +{"platform": "instagram", "handle": "karrelaubert"} | |
| 580 | +{"platform": "instagram", "handle": "erikaco.events"} | |
| 581 | +{"platform": "instagram", "handle": "robmalofilms"} | |
| 582 | +{"platform": "instagram", "handle": "club_atwater"} | |
| 583 | +{"platform": "instagram", "handle": "jacinthe.benoit"} | |
| 584 | +{"platform": "instagram", "handle": "ivoiremontreal"} | |
| 585 | +{"platform": "instagram", "handle": "montreal_blandindelloye"} | |
| 586 | +{"platform": "instagram", "handle": "anabelfrechettephotographe"} | |
| 587 | +{"platform": "instagram", "handle": "leplusbojour"} | |
| 588 | +{"platform": "instagram", "handle": "resort_entourage"} | |
| 589 | +{"platform": "instagram", "handle": "by_lemay"} | |
| 590 | +{"platform": "instagram", "handle": "fleurdeurope"} | |
| 591 | +{"platform": "instagram", "handle": "papeterieetconfetti"} | |
| 592 | +{"platform": "instagram", "handle": "cleobolduc"} | |
| 593 | +{"platform": "instagram", "handle": "chezmarcus"} | |
| 594 | +{"platform": "instagram", "handle": "xperience_applyrs"} | |
| 595 | +{"platform": "instagram", "handle": "mart.menard"} | |
| 596 | +{"platform": "instagram", "handle": "laurenceflortie"} | |
| 597 | +{"platform": "instagram", "handle": "paulinaco.events"} | |
| 598 | +{"platform": "instagram", "handle": "beyondthehearts"} | |
| 599 | +{"platform": "instagram", "handle": "annieli.mtl"} | |
| 600 | +{"platform": "instagram", "handle": "wang_dion"} | |
| 601 | +{"platform": "instagram", "handle": "kerstinhahnphotography"} | |
| 602 | +{"platform": "instagram", "handle": "myriammenardphoto"} | |
| 603 | +{"platform": "instagram", "handle": "chateausteagnes"} | |
| 604 | +{"platform": "instagram", "handle": "studio_ck_flowers"} | |
| 605 | +{"platform": "instagram", "handle": "blandindelloye.mariage"} | |
| 606 | +{"platform": "instagram", "handle": "nargessheed"} | |
| 607 | +{"platform": "instagram", "handle": "fulkoweddings"} | |
| 608 | +{"platform": "instagram", "handle": "loft.bijoux"} | |
| 609 | +{"platform": "instagram", "handle": "whitewillowpaperco"} | |
| 610 | +{"platform": "instagram", "handle": "letraiteurarcher"} | |
| 611 | +{"platform": "instagram", "handle": "buvette_mobile_lapero"} | |
| 612 | +{"platform": "instagram", "handle": "celebrationsgroup"} | |
| 613 | +{"platform": "instagram", "handle": "simplybeautifuldecor"} | |
| 614 | +{"platform": "instagram", "handle": "emilieviolon"} | |
| 615 | +{"platform": "instagram", "handle": "fairmontmanoir"} | |
| 616 | +{"platform": "instagram", "handle": "eclatprive.signature"} | |
| 617 | +{"platform": "instagram", "handle": "fetesgrenadine"} | |
| 618 | +{"platform": "instagram", "handle": "cvezinabride"} | |
| 619 | +{"platform": "instagram", "handle": "mepm"} | |
| 620 | +{"platform": "instagram", "handle": "joe_lbri"} | |
| 621 | +{"platform": "instagram", "handle": "christianlouboutin"} | |
| 622 | +{"platform": "instagram", "handle": "arvirestaurant"} | |
| 623 | +{"platform": "instagram", "handle": "cremesodaevenement"} | |
| 624 | +{"platform": "instagram", "handle": "cremesodaevenements"} | |
| 625 | +{"platform": "instagram", "handle": "maecaouette"} | |
| 626 | +{"platform": "instagram", "handle": "dior"} | |
| 627 | +{"platform": "instagram", "handle": "hiltonquebec"} | |
| 628 | +{"platform": "instagram", "handle": "agence.elegance"} | |
| 629 | +{"platform": "instagram", "handle": "mapatisserie.ca"} | |
| 630 | +{"platform": "instagram", "handle": "chateau.nadia"} | |
| 631 | +{"platform": "instagram", "handle": "catherinehardy_photographe"} | |
| 632 | +{"platform": "instagram", "handle": "dekoraalbum"} | |
| 633 | +{"platform": "instagram", "handle": "elisabethb_eb"} | |
| 634 | +{"platform": "instagram", "handle": "wed_vibes"} | |
| 635 | +{"platform": "instagram", "handle": "happy.moments.collector"} | |
| 636 | +{"platform": "instagram", "handle": "villapizzo"} | |
| 637 | +{"platform": "instagram", "handle": "sociallymichelleandco"} | |
| 638 | +{"platform": "instagram", "handle": "riccardociceri"} | |
| 639 | +{"platform": "instagram", "handle": "blunotteventi"} | |
| 640 | +{"platform": "instagram", "handle": "latinidesign"} | |
| 641 | +{"platform": "instagram", "handle": "tablesetrentals"} | |
| 642 | +{"platform": "instagram", "handle": "raraavis_group"} | |
| 643 | +{"platform": "instagram", "handle": "evgeniadragun"} | |
| 644 | +{"platform": "instagram", "handle": "jennymakeupland"} | |
| 645 | +{"platform": "instagram", "handle": "dadoallestimenti"} | |
| 646 | +{"platform": "instagram", "handle": "einpraegsam.co"} | |
| 647 | +{"platform": "instagram", "handle": "louska.v"} | |
| 648 | +{"platform": "instagram", "handle": "raphaelpalmeer"} | |
| 649 | +{"platform": "instagram", "handle": "coiffuredistinctiveqc"} | |
| 650 | +{"platform": "instagram", "handle": "wedding_chateaufrontenac"} | |
| 651 | +{"platform": "instagram", "handle": "magentastudiophoto"} | |
| 652 | +{"platform": "instagram", "handle": "photo_g.b"} | |
| 653 | +{"platform": "x", "handle": "blogue"} | |
| 654 | +{"platform": "x", "handle": "wp"} | |
| 655 | +{"platform": "instagram", "handle": "raavquebec"} | |
| 656 | +{"platform": "instagram", "handle": "francoisgaudet"} | |
| 657 | +{"platform": "instagram", "handle": "macbsp"} | |
| 658 | +{"platform": "instagram", "handle": "aaapnb"} | |
| 659 | +{"platform": "instagram", "handle": "leseloizes"} | |
| 660 | +{"platform": "instagram", "handle": "olyangertattoo"} | |
| 661 | +{"platform": "instagram", "handle": "tatouageroyal"} | |
| 662 | +{"platform": "instagram", "handle": "imagotattoo"} | |
| 663 | +{"platform": "instagram", "handle": "studioartease"} | |
| 664 | +{"platform": "instagram", "handle": "le.malandrin"} | |
| 665 | +{"platform": "instagram", "handle": "velours.studio"} | |
| 666 | +{"platform": "instagram", "handle": "velours.tattoo"} | |
| 667 | +{"platform": "instagram", "handle": "dominiquebodkintattoo"} | |
| 668 | +{"platform": "instagram", "handle": "arnostattoos"} | |
| 669 | +{"platform": "instagram", "handle": "e.a.tattoo"} | |
| 670 | +{"platform": "instagram", "handle": "christianlanouette"} | |
| 671 | +{"platform": "instagram", "handle": "tattoo.noirsurpeau"} | |
| 672 | +{"platform": "instagram", "handle": "phylotattoos"} | |
| 673 | +{"platform": "instagram", "handle": "lucitattoos"} | |
| 674 | +{"platform": "instagram", "handle": "lmariera"} | |
| 675 | +{"platform": "instagram", "handle": "softbrattattz"} | |
| 676 | +{"platform": "instagram", "handle": "mllealyx_tattoo"} | |
| 677 | +{"platform": "instagram", "handle": "piewchoquette"} | |
| 678 | +{"platform": "instagram", "handle": "murieldemai_tattoo"} | |
| 679 | +{"platform": "instagram", "handle": "laracailletattoo"} | |
| 680 | +{"platform": "instagram", "handle": "fredpokes"} | |
| 681 | +{"platform": "instagram", "handle": "b.hurricane"} | |
| 682 | +{"platform": "instagram", "handle": "lav4gurl"} | |
| 683 | +{"platform": "instagram", "handle": "steamboat_vinnie"} | |
| 684 | +{"platform": "instagram", "handle": "mllealyx"} | |
| 685 | +{"platform": "instagram", "handle": "murieldemai"} | |
| 686 | +{"platform": "instagram", "handle": "bb.hurricane"} | |
| 687 | +{"platform": "instagram", "handle": "steamboat"} | |
| 688 | +{"platform": "instagram", "handle": "lukalajoie"} | |
| 689 | +{"platform": "instagram", "handle": "christinastattoos"} | |
| 690 | +{"platform": "instagram", "handle": "ayako666"} | |
| 691 | +{"platform": "instagram", "handle": "maxxlemieux"} | |
| 692 | +{"platform": "instagram", "handle": "yannblacktattoo"} | |
| 693 | +{"platform": "instagram", "handle": "zema1"} | |
| 694 | +{"platform": "instagram", "handle": "ink.maude"} | |
| 695 | +{"platform": "instagram", "handle": "waynemcfarlane"} | |
| 696 | +{"platform": "instagram", "handle": "shaemotztattoos"} | |
| 697 | +{"platform": "instagram", "handle": "draworking"} | |
| 698 | +{"platform": "instagram", "handle": "getmooretattoos"} | |
| 699 | +{"platform": "instagram", "handle": "inkredible"} | |
| 700 | +{"platform": "instagram", "handle": "inkredible_shawn"} | |
| 701 | +{"platform": "instagram", "handle": "rebeccablairtattoos"} | |
| 702 | +{"platform": "instagram", "handle": "johnnynoirtattoo"} | |
| 703 | +{"platform": "instagram", "handle": "the_burning_jewel"} | |
| 704 | +{"platform": "instagram", "handle": "808byjack"} | |
| 705 | +{"platform": "instagram", "handle": "tattoomontreal"} | |
| 706 | +{"platform": "instagram", "handle": "montrealtattooguide"} | |
| 707 | +{"platform": "instagram", "handle": "monsieur.pitch"} | |
| 708 | +{"platform": "instagram", "handle": "lashopchaos"} | |
| 709 | +{"platform": "instagram", "handle": "velco.tattoo"} | |
| 710 | +{"platform": "instagram", "handle": "baroquebabetattoos"} | |
| 711 | +{"platform": "instagram", "handle": "chez.bebelala"} | |
| 712 | +{"platform": "instagram", "handle": "thedavidcote"} | |
| 713 | +{"platform": "instagram", "handle": "noirsurpeau"} | |
| 714 | +{"platform": "instagram", "handle": "studio.amormio"} | |
| 715 | +{"platform": "instagram", "handle": "brizz.amor"} | |
| 716 | +{"platform": "instagram", "handle": "dani.l.pokes"} | |
| 717 | +{"platform": "instagram", "handle": "passelebriquet"} | |
| 718 | +{"platform": "instagram", "handle": "isabelroseink"} | |
| 719 | +{"platform": "instagram", "handle": "industrial.inktattoo"} | |
| 720 | +{"platform": "instagram", "handle": "itslumibeauty"} | |
| 721 | +{"platform": "instagram", "handle": "permanence.pmu"} | |
| 722 | +{"platform": "instagram", "handle": "hayls.ink"} | |
| 723 | +{"platform": "instagram", "handle": "tattoobysoso"} | |
| 724 | +{"platform": "instagram", "handle": "saintpaul.tattoo"} | |
| 725 | +{"platform": "instagram", "handle": "subielachani.cs"} | |
| 726 | +{"platform": "instagram", "handle": "charlessimardcoiffeur"} | |
| 727 | +{"platform": "instagram", "handle": "hair_by_pk.t"} | |
| 728 | +{"platform": "instagram", "handle": "marcuuus"} | |
| 729 | +{"platform": "instagram", "handle": "cathesoe_hair"} | |
| 730 | +{"platform": "instagram", "handle": "kimmcgillis"} | |
| 731 | +{"platform": "instagram", "handle": "andree.anne.gagne"} | |
| 732 | +{"platform": "instagram", "handle": "hairbynathaliemichaud"} | |
| 733 | +{"platform": "instagram", "handle": "vikingmax.hair"} | |
| 734 | +{"platform": "instagram", "handle": "salonno1coiffure"} | |
| 735 | +{"platform": "instagram", "handle": "la_capillicultrice"} | |
| 736 | +{"platform": "instagram", "handle": "laurence_hairstylist"} | |
| 737 | +{"platform": "instagram", "handle": "sam.chab"} | |
| 738 | +{"platform": "instagram", "handle": "staellecolorful"} | |
| 739 | +{"platform": "instagram", "handle": "melagagn"} | |
| 740 | +{"platform": "instagram", "handle": "les_couloirs"} | |
| 741 | +{"platform": "instagram", "handle": "st_laurent_coiffure"} | |
| 742 | +{"platform": "instagram", "handle": "karianne_artistika"} | |
| 743 | +{"platform": "instagram", "handle": "eleganzaqc"} | |
| 744 | +{"platform": "instagram", "handle": "billie.qc"} | |
| 745 | +{"platform": "instagram", "handle": "luxetmusa"} | |
| 746 | +{"platform": "instagram", "handle": "zazzpareleganza"} | |
| 747 | +{"platform": "instagram", "handle": "salontestuvulallure"} | |
| 748 | +{"platform": "instagram", "handle": "alia_victoria_coiffure"} | |
| 749 | +{"platform": "instagram", "handle": "labelleetlatete"} | |
| 750 | +{"platform": "instagram", "handle": "parikart_"} | |
| 751 | +{"platform": "instagram", "handle": "litchicoiffure"} | |
| 752 | +{"platform": "instagram", "handle": "mcoupebeaute"} | |
| 753 | +{"platform": "instagram", "handle": "lakwaflevis"} | |
| 754 | +{"platform": "instagram", "handle": "hakima_matata"} | |
| 755 | +{"platform": "instagram", "handle": "matrix"} | |
| 756 | +{"platform": "instagram", "handle": "schwarzkopfpro"} | |
| 757 | +{"platform": "instagram", "handle": "babylissprousa"} | |
| 758 | +{"platform": "instagram", "handle": "neumabeauty"} | |
| 759 | +{"platform": "instagram", "handle": "joellienadeau"} | |
| 760 | +{"platform": "instagram", "handle": "goldwellca"} | |
| 761 | +{"platform": "instagram", "handle": "coiffure_le_saint"} | |
| 762 | +{"platform": "instagram", "handle": "hair_by_roxks"} | |
| 763 | +{"platform": "instagram", "handle": "carolabelleetlatete"} | |
| 764 | +{"platform": "instagram", "handle": "annieracine01"} | |
| 765 | +{"platform": "x", "handle": "jdequebec"} | |
| 766 | +{"platform": "instagram", "handle": "alexandrinepoirier"} | |
| 767 | +{"platform": "instagram", "handle": "maudegervais_"} | |
| 768 | +{"platform": "instagram", "handle": "lorealpro"} | |
| 769 | +{"platform": "instagram", "handle": "olaplex"} | |
| 770 | +{"platform": "instagram", "handle": "mutetienne"} | |
| 771 | +{"platform": "instagram", "handle": "gab.brulotte"} | |
| 772 | +{"platform": "instagram", "handle": "annepier"} | |
| 773 | +{"platform": "instagram", "handle": "klaudiaodeth"} | |
| 774 | +{"platform": "instagram", "handle": "biolage"} | |
| 775 | +{"platform": "instagram", "handle": "ruskhaircare"} | |
| 776 | +{"platform": "instagram", "handle": "ruskcanada"} | |
| 777 | +{"platform": "instagram", "handle": "aquagecanada"} | |
| 778 | +{"platform": "instagram", "handle": "aquagehaircare"} | |
| 779 | +{"platform": "instagram", "handle": "alexeloranger"} | |
| 780 | +{"platform": "instagram", "handle": "cath_marier"} | |
| 781 | +{"platform": "instagram", "handle": "fresha"} | |
| 782 | +{"platform": "instagram", "handle": "virginietrc"} | |
| 783 | +{"platform": "instagram", "handle": "clemencexchezmarcus"} | |
| 784 | +{"platform": "instagram", "handle": "kingperse"} | |
| 785 | +{"platform": "instagram", "handle": "annejuice10"} | |
| 786 | +{"platform": "instagram", "handle": "charlesxeda"} | |
| 787 | +{"platform": "instagram", "handle": "lau.gre"} | |
| 788 | +{"platform": "instagram", "handle": "cynth.haircolors"} | |
| 789 | +{"platform": "instagram", "handle": "kellyextensions"} | |
| 790 | +{"platform": "instagram", "handle": "sxmos_"} | |
| 791 | +{"platform": "instagram", "handle": "kateextensions"} | |
| 792 | +{"platform": "instagram", "handle": "est"} | |
| 793 | +{"platform": "instagram", "handle": "saloncoiffurelestudio"} | |
| 794 | +{"platform": "instagram", "handle": "conceptbeaute.esthetique"} | |
| 795 | +{"platform": "instagram", "handle": "institut.esthetique.qc"} | |
| 796 | +{"platform": "instagram", "handle": "skinandcoesthetique"} | |
| 797 | +{"platform": "tiktok", "handle": "skinco.esthtique"} | |
| 798 | +{"platform": "tiktok", "handle": "dermacureqc"} | |
| 799 | +{"platform": "instagram", "handle": "cfameriques"} | |
| 800 | +{"platform": "instagram", "handle": "icrml.cirlm"} | |
| 801 | +{"platform": "x", "handle": "icrml_cirlm"} | |
| 802 | +{"platform": "instagram", "handle": "nalyses"} | |
| 803 | +{"platform": "instagram", "handle": "gmc"} | |
| 804 | +{"platform": "instagram", "handle": "gmccanada"} | |
| 805 | +{"platform": "tiktok", "handle": "gmccanada"} | |
| 806 | +{"platform": "instagram", "handle": "triumphamerica"} | |
| 807 | +{"platform": "x", "handle": "triumphamerica"} | |
| 808 | +{"platform": "instagram", "handle": "motomontrealcycle"} | |
| 809 | +{"platform": "instagram", "handle": "motorcycleandpowersportshows"} | |
| 810 | +{"platform": "instagram", "handle": "bmwmotorradmontreal"} | |
| 811 | +{"platform": "instagram", "handle": "themotosocial"} | |
| 812 | +{"platform": "instagram", "handle": "idlegarageandcoffee"} | |
| 813 | +{"platform": "instagram", "handle": "cafelefalco"} | |
| 814 | +{"platform": "instagram", "handle": "hocheglace"} | |
| 815 | +{"platform": "instagram", "handle": "cantinova.cafe"} | |
| 816 | +{"platform": "instagram", "handle": "beausallnatural"} | |
| 817 | +{"platform": "instagram", "handle": "la_fille_au_casque_rouge_"} | |
| 818 | +{"platform": "instagram", "handle": "hawley_martin"} | |
| 819 | +{"platform": "instagram", "handle": "motor_cycle_bro"} | |
| 820 | +{"platform": "instagram", "handle": "nak_attaque"} | |
| 821 | +{"platform": "instagram", "handle": "vikpiccreative"} | |
| 822 | +{"platform": "instagram", "handle": "yamahamotorcanada"} | |
| 823 | +{"platform": "instagram", "handle": "mic"} | |
| 824 | +{"platform": "x", "handle": "enduro"} | |
| 825 | +{"platform": "instagram", "handle": "perrondesign"} | |
| 826 | +{"platform": "instagram", "handle": "adomicile_"} | |
| 827 | +{"platform": "instagram", "handle": "atelierzebulonperron"} | |
| 828 | +{"platform": "instagram", "handle": "atelierdansereau"} | |
| 829 | +{"platform": "instagram", "handle": "les"} | |
| 830 | +{"platform": "instagram", "handle": "bureautempo"} | |
| 831 | +{"platform": "instagram", "handle": "vivesstlaurent"} | |
| 832 | +{"platform": "instagram", "handle": "michaelgodmerstudio"} | |
| 833 | +{"platform": "instagram", "handle": "akbdesign"} | |
| 834 | +{"platform": "instagram", "handle": "bipede.design"} | |
| 835 | +{"platform": "instagram", "handle": "entrequatremurs"} | |
| 836 | +{"platform": "instagram", "handle": "entrepot_de_la_reno"} | |
| 837 | +{"platform": "instagram", "handle": "brookandpeony"} | |
| 838 | +{"platform": "instagram", "handle": "house_to_home.interiors"} | |
| 839 | +{"platform": "instagram", "handle": "rien_ne_se_perd"} | |
| 840 | +{"platform": "instagram", "handle": "alexandralarouche"} | |
| 841 | +{"platform": "instagram", "handle": "ashleyshaanan"} | |
| 842 | +{"platform": "x", "handle": "logisquebec"} | |
| 843 | +{"platform": "instagram", "handle": "davani_realtor"} | |
| 844 | +{"platform": "x", "handle": "behrooziani"} | |
| 845 | +{"platform": "instagram", "handle": "realtorpointca"} | |
| 846 | +{"platform": "x", "handle": "realtorpointca"} | |
| 847 | +{"platform": "instagram", "handle": "lespac"} | |
| 848 | +{"platform": "instagram", "handle": "royal_lepage"} | |
| 849 | +{"platform": "instagram", "handle": "remaxcanada"} | |
| 850 | +{"platform": "tiktok", "handle": "remax.canada"} | |
| 851 | +{"platform": "youtube", "handle": "remaxcanada_no1"} | |
| 852 | +{"platform": "x", "handle": "assets"} | |
| 853 | +{"platform": "x", "handle": "mex"} | |
| 854 | +{"platform": "instagram", "handle": "viacapitale"} | |
| 855 | +{"platform": "x", "handle": "viacapitale"} | |
| 856 | +{"platform": "instagram", "handle": "remaxquebec"} | |
| 857 | +{"platform": "tiktok", "handle": "remax.quebec"} | |
| 858 | +{"platform": "x", "handle": "notoriete"} | |
| 859 | +{"platform": "x", "handle": "formation"} | |
| 860 | +{"platform": "x", "handle": "contact"} | |
| 861 | +{"platform": "x", "handle": "remaxquebec"} | |
| 862 | +{"platform": "x", "handle": "default"} | |
| 863 | +{"platform": "youtube", "handle": "findevcanada"} | |
| 864 | +{"platform": "x", "handle": "findev_canada"} | |
| 865 | +{"platform": "instagram", "handle": "eycanada"} | |
| 866 | +{"platform": "instagram", "handle": "quebecintl"} | |
| 867 | +{"platform": "tiktok", "handle": "quebecintl"} | |
| 868 | +{"platform": "instagram", "handle": "yesmontreal"} | |
| 869 | +{"platform": "x", "handle": "yesmontreal"} | |
| 870 | +{"platform": "instagram", "handle": "fahdalhattab"} | |
| 871 | +{"platform": "youtube", "handle": "fahdalhattab"} | |
| 872 | +{"platform": "x", "handle": "fahdalhattab"} | |
| 873 | +{"platform": "instagram", "handle": "myriambariltessier_v4.jpg"} | |
| 874 | +{"platform": "instagram", "handle": "punctuatedesign"} | |
| 875 | +{"platform": "instagram", "handle": "startupfest"} | |
| 876 | +{"platform": "instagram", "handle": "inrsciences"} | |
| 877 | +{"platform": "x", "handle": "u_inrs"} | |
| 878 | +{"platform": "instagram", "handle": "fse_udem"} | |
| 879 | +{"platform": "instagram", "handle": "englishmtl"} | |
| 880 | +{"platform": "instagram", "handle": "hecmontreal"} | |
| 881 | +{"platform": "x", "handle": "hec_montreal"} | |
| 882 | +{"platform": "x", "handle": "recordingservic"} | |
| 883 | +{"platform": "instagram", "handle": "csf_cb"} | |
| 884 | +{"platform": "instagram", "handle": "bibliothequedequebec"} | |
| 885 | +{"platform": "youtube", "handle": "bibliotheque_quebec"} | |
| 886 | +{"platform": "instagram", "handle": "moongirlreads"} | |
| 887 | +{"platform": "instagram", "handle": "bookedj"} | |
| 888 | +{"platform": "instagram", "handle": "meemoreads"} | |
| 889 | +{"platform": "instagram", "handle": "thrillerbooklover"} | |
| 890 | +{"platform": "instagram", "handle": "literallyjohngreen"} | |
| 891 | +{"platform": "instagram", "handle": "thechloegong"} | |
| 892 | +{"platform": "instagram", "handle": "victoriaaveyard"} | |
| 893 | +{"platform": "instagram", "handle": "runwithskizzers"} | |
| 894 | +{"platform": "instagram", "handle": "michael.bjork"} | |
| 895 | +{"platform": "instagram", "handle": "penguin"} | |
| 896 | +{"platform": "tiktok", "handle": "girlyalex83"} | |
| 897 | +{"platform": "tiktok", "handle": "morgannbook"} | |
| 898 | +{"platform": "tiktok", "handle": "yabooktok"} | |
| 899 | +{"platform": "x", "handle": "ncbi"} | |
| 900 | +{"platform": "x", "handle": "nlm_nih"} | |
| 901 | +{"platform": "instagram", "handle": "daansbooks"} | |
| 902 | +{"platform": "instagram", "handle": "spinesvines"} | |
| 903 | +{"platform": "instagram", "handle": "spinesandvines"} | |
| 904 | +{"platform": "tiktok", "handle": "baker.reads"} | |
| 905 | +{"platform": "tiktok", "handle": "c15r5y4"} | |
| 906 | +{"platform": "tiktok", "handle": "ajunxx"} | |
| 907 | +{"platform": "tiktok", "handle": "iamstephanienoble"} | |
| 908 | +{"platform": "tiktok", "handle": "bigbooklady"} | |
| 909 | +{"platform": "tiktok", "handle": "thelibraryofdais"} | |
| 910 | +{"platform": "x", "handle": "culture"} | |
| 911 | +{"platform": "x", "handle": "exhaustdata"} | |
| 912 | +{"platform": "instagram", "handle": "booknet"} | |
| 913 | +{"platform": "instagram", "handle": "cbcbooks"} | |
| 914 | +{"platform": "instagram", "handle": "lat46publishing"} | |
| 915 | +{"platform": "instagram", "handle": "readflare"} | |
| 916 | +{"platform": "x", "handle": "pcitoyen"} | |
| 917 | +{"platform": "instagram", "handle": "msss_qc"} | |
| 918 | +{"platform": "x", "handle": "msss_qc"} | |
| 919 | +{"platform": "instagram", "handle": "acadianhealth"} | |
| 920 | +{"platform": "instagram", "handle": "creons_la_suite"} | |
| 921 | +{"platform": "x", "handle": "creonslasuite"} | |
| 922 | +{"platform": "x", "handle": "santefrancais"} | |
| 923 | +{"platform": "instagram", "handle": "lunayogamtl"} | |
| 924 | +{"platform": "instagram", "handle": "institutyogaessentiel"} | |
| 925 | +{"platform": "instagram", "handle": "yogashakmontreal"} | |
| 926 | +{"platform": "instagram", "handle": "naadayoga"} | |
| 927 | +{"platform": "x", "handle": "naadayoga"} | |
| 928 | +{"platform": "instagram", "handle": "sfvictoria.ca"} | |
| 929 | +{"platform": "x", "handle": "francophone_vic"} | |
| 930 | +{"platform": "x", "handle": "podkatt"} | |
| 931 | +{"platform": "instagram", "handle": "podkatt"} | |
| 932 | +{"platform": "instagram", "handle": "podthenorth"} | |
| 933 | +{"platform": "instagram", "handle": "labrigadepod.th"} | |
| 934 | +{"platform": "instagram", "handle": "jezebel.bardotsuivez"} | |
| 935 | +{"platform": "instagram", "handle": "celestelevisyoutube"} | |
| 936 | +{"platform": "instagram", "handle": "srnhasselaslinkedin"} | |
| 937 | +{"platform": "instagram", "handle": "makhena"} | |
| 938 | +{"platform": "instagram", "handle": "miquemichellesuivez"} | |
| 939 | +{"platform": "instagram", "handle": "leflofrancosite"} | |
| 940 | +{"platform": "instagram", "handle": "lexinemenard"} | |
| 941 | +{"platform": "instagram", "handle": "lexinephotographie"} | |
| 942 | +{"platform": "instagram", "handle": "lexiphotoboothsite"} | |
| 943 | +{"platform": "instagram", "handle": "lydiamariebpinstagram"} | |
| 944 | +{"platform": "instagram", "handle": "lydiamariebplinkedin"} | |
| 945 | +{"platform": "instagram", "handle": "monassemblee"} | |
| 946 | +{"platform": "instagram", "handle": "danieroy11"} | |
| 947 | +{"platform": "tiktok", "handle": "ledevoir"} | |
| 948 | +{"platform": "x", "handle": "ledevoir"} | |
| 949 | +{"platform": "instagram", "handle": "rubytdoll"} | |
| 950 | +{"platform": "instagram", "handle": "aleeranight"} | |
| 951 | +{"platform": "instagram", "handle": "verona_verushka"} | |
| 952 | +{"platform": "instagram", "handle": "madolamotte"} | |
| 953 | +{"platform": "instagram", "handle": "huffpost"} | |
| 954 | +{"platform": "instagram", "handle": "rainbow.drag"} | |
| 955 | +{"platform": "instagram", "handle": "ritabagaz"} | |
| 956 | +{"platform": "instagram", "handle": "gabryelledrag"} | |
| 957 | +{"platform": "instagram", "handle": "matante.alex"} | |
| 958 | +{"platform": "instagram", "handle": "gisele_lullaby"} | |
| 959 | +{"platform": "instagram", "handle": "kiara.qc.ca"} | |
| 960 | +{"platform": "instagram", "handle": "ladydeboomboom"} | |
| 961 | +{"platform": "instagram", "handle": "pythia.queen"} | |
| 962 | +{"platform": "instagram", "handle": "umagahd"} | |
| 963 | +{"platform": "instagram", "handle": "itsheavengenderfck"} | |
| 964 | +{"platform": "instagram", "handle": "selmagahd"} | |
| 965 | +{"platform": "x", "handle": "huffpost"} | |
| 966 | +{"platform": "x", "handle": "philippelepine"} | |
| 967 | +{"platform": "instagram", "handle": "sugarandspice"} | |
| 968 | +{"platform": "instagram", "handle": "callmespice"} | |
| 969 | +{"platform": "instagram", "handle": "sugar"} | |
| 970 | +{"platform": "instagram", "handle": "rc.ohdio"} | |
| 971 | +{"platform": "instagram", "handle": "she_laa9"} | |
| 972 | +{"platform": "tiktok", "handle": "samilandri"} | |
| 973 | +{"platform": "tiktok", "handle": "queenrosebeef"} | |
| 974 | +{"platform": "tiktok", "handle": "radpointca"} | |
| 975 | +{"platform": "tiktok", "handle": "she_laa9"} | |
| 976 | +{"platform": "tiktok", "handle": "danslebainaveccelin"} | |
| 977 | +{"platform": "tiktok", "handle": "rc.ohdio"} | |
| 978 | +{"platform": "tiktok", "handle": "sugarandspice"} | |
| 979 | +{"platform": "tiktok", "handle": "rainbow.drag"} | |
| 980 | +{"platform": "tiktok", "handle": "demone_lastrange"} | |
| 981 | +{"platform": "tiktok", "handle": "paspeufieres"} | |
| 982 | +{"platform": "tiktok", "handle": "rosiepetalsdrag"} | |
| 983 | +{"platform": "tiktok", "handle": "cityofquebec"} | |
| 984 | +{"platform": "tiktok", "handle": "scoobydoobydrew22"} | |
| 985 | +{"platform": "tiktok", "handle": "yap.mtl"} | |
| 986 | +{"platform": "tiktok", "handle": "ximena.do.santos"} | |
| 987 | +{"platform": "instagram", "handle": "samilandri"} | |
| 988 | +{"platform": "instagram", "handle": "queenrosebeef"} | |
| 989 | +{"platform": "instagram", "handle": "radpointca"} | |
| 990 | +{"platform": "instagram", "handle": "danslebainaveccelin"} | |
| 991 | +{"platform": "instagram", "handle": "agence.ludik"} | |
| 992 | +{"platform": "instagram", "handle": "barbada"} | |
| 993 | +{"platform": "instagram", "handle": "rita"} | |
| 994 | +{"platform": "instagram", "handle": "demone_lastrange"} | |
| 995 | +{"platform": "instagram", "handle": "paspeufieres"} | |
| 996 | +{"platform": "instagram", "handle": "chiquita"} | |
| 997 | +{"platform": "instagram", "handle": "rosiepetalsdrag"} | |
| 998 | +{"platform": "instagram", "handle": "cityofquebec"} | |
| 999 | +{"platform": "instagram", "handle": "scoobydoobydrew22"} | |
| 1000 | +{"platform": "instagram", "handle": "yap.mtl"} | |
| 1001 | +{"platform": "instagram", "handle": "ximena.do.santos"} | |
| 1002 | +{"platform": "instagram", "handle": "cult_mag_"} | |
| 1003 | +{"platform": "youtube", "handle": "cultmagazine"} | |
| 1004 | +{"platform": "youtube", "handle": "helpez-moi"} | |
| 1005 | +{"platform": "x", "handle": "cult_mag_"} | |
| 1006 | +{"platform": "instagram", "handle": "samilandri_"} | |
| 1007 | +{"platform": "instagram", "handle": "velma.johnny"} | |
| 1008 | +{"platform": "instagram", "handle": "chiquita.mere"} | |
| 1009 | +{"platform": "instagram", "handle": "queermtl"} | |
| 1010 | +{"platform": "instagram", "handle": "stefan"} | |
| 1011 | +{"platform": "instagram", "handle": "cclgbtqplus"} | |
| 1012 | +{"platform": "youtube", "handle": "bibliothequealivresouverts7986"} | |
| 1013 | +{"platform": "instagram", "handle": "barlestud"} | |
| 1014 | +{"platform": "instagram", "handle": "champs_montreal"} | |
| 1015 | +{"platform": "instagram", "handle": "motel_motel"} | |
| 1016 | +{"platform": "instagram", "handle": "bar_taboo_inc"} | |
| 1017 | +{"platform": "instagram", "handle": "ballroom4community"} | |
| 1018 | +{"platform": "instagram", "handle": "bareoke"} | |
| 1019 | +{"platform": "instagram", "handle": "violet_hour_lit"} | |
| 1020 | +{"platform": "instagram", "handle": "leclubdds"} | |
| 1021 | +{"platform": "instagram", "handle": "jontaemccrory"} | |
| 1022 | +{"platform": "instagram", "handle": "blackgxrlsesh"} | |
| 1023 | +{"platform": "instagram", "handle": "queerkaraokemtl"} | |
| 1024 | +{"platform": "instagram", "handle": "p10montreal"} | |
| 1025 | +{"platform": "instagram", "handle": "queerbodiesmontreal"} | |
| 1026 | +{"platform": "instagram", "handle": "bring_it_mtl"} | |
| 1027 | +{"platform": "instagram", "handle": "juke.collective"} | |
| 1028 | +{"platform": "instagram", "handle": "bmqs.mtl"} | |
| 1029 | +{"platform": "instagram", "handle": "dodgeball.ratons.chasseurs"} | |
| 1030 | +{"platform": "instagram", "handle": "out_runclub"} | |
| 1031 | +{"platform": "instagram", "handle": "queer_bloc"} | |
| 1032 | +{"platform": "instagram", "handle": "theunfitclub"} | |
| 1033 | +{"platform": "instagram", "handle": "justice.trans"} | |
| 1034 | +{"platform": "instagram", "handle": "audreyrivet"} | |
| 1035 | +{"platform": "instagram", "handle": "josianekonate"} | |
| 1036 | +{"platform": "instagram", "handle": "faulhaber.agency"} | |
| 1037 | +{"platform": "instagram", "handle": "trangreeny"} | |
| 1038 | +{"platform": "x", "handle": "faulhabercomm"} | |
| 1039 | +{"platform": "instagram", "handle": "legurky"} | |
| 1040 | +{"platform": "instagram", "handle": "adamparadisio"} | |
| 1041 | +{"platform": "instagram", "handle": "alexane"} | |
| 1042 | +{"platform": "instagram", "handle": "samanthaleclerc"} | |
| 1043 | +{"platform": "instagram", "handle": "emylalune"} | |
| 1044 | +{"platform": "instagram", "handle": "agenceoneway"} | |
| 1045 | +{"platform": "tiktok", "handle": "emylalune"} | |
| 1046 | +{"platform": "tiktok", "handle": "adamparadisio"} | |
| 1047 | +{"platform": "tiktok", "handle": "hydroquebec"} | |
| 1048 | +{"platform": "tiktok", "handle": "accouuu"} | |
| 1049 | +{"platform": "tiktok", "handle": "influencecreation"} | |
| 1050 | +{"platform": "instagram", "handle": "influencecreation"} | |
| 1051 | +{"platform": "instagram", "handle": "la.boite.dinfluence"} | |
| 1052 | +{"platform": "instagram", "handle": "nath.hebert"} | |
| 1053 | +{"platform": "instagram", "handle": "sarahmboily"} | |
| 1054 | +{"platform": "instagram", "handle": "samonthenews"} | |
| 1055 | +{"platform": "tiktok", "handle": "camilledufresne_"} | |
| 1056 | +{"platform": "instagram", "handle": "iamjahantea"} | |
| 1057 | +{"platform": "instagram", "handle": "aiequi"} | |
| 1058 | +{"platform": "tiktok", "handle": "sjbleauellington"} | |
| 1059 | +{"platform": "tiktok", "handle": "denyzee"} | |
| 1060 | +{"platform": "tiktok", "handle": "iamjahantea"} | |
| 1061 | +{"platform": "youtube", "handle": "denyzee"} | |
| 1062 | +{"platform": "youtube", "handle": "cocottee_"} | |
| 1063 | +{"platform": "instagram", "handle": "sjbleauellington"} | |
| 1064 | +{"platform": "instagram", "handle": "denyzee"} | |
| 1065 | +{"platform": "instagram", "handle": "felixdolci"} | |
| 1066 | +{"platform": "instagram", "handle": "nailzzbymyka"} | |
| 1067 | +{"platform": "instagram", "handle": "lasenza"} | |
| 1068 | +{"platform": "instagram", "handle": "quebecbroue"} | |
| 1069 | +{"platform": "instagram", "handle": "msfphotographie"} | |
| 1070 | +{"platform": "instagram", "handle": "calvinklein"} | |
| 1071 | +{"platform": "instagram", "handle": "tvanouvelles"} | |
| 1072 | +{"platform": "instagram", "handle": "salutbonjourofficiel"} | |
| 1073 | +{"platform": "instagram", "handle": "pascalerobitaille"} | |
| 1074 | +{"platform": "instagram", "handle": "upawasessions"} | |
| 1075 | +{"platform": "instagram", "handle": "soufiane"} | |
| 1076 | +{"platform": "instagram", "handle": "wherepaganoat"} | |
| 1077 | +{"platform": "instagram", "handle": "clatetu"} | |
| 1078 | +{"platform": "instagram", "handle": "killwilliamhennessey"} | |
| 1079 | +{"platform": "instagram", "handle": "d.rec.2"} | |
| 1080 | +{"platform": "instagram", "handle": "duber72_"} | |
| 1081 | +{"platform": "instagram", "handle": "bahoboxing"} | |
| 1082 | +{"platform": "instagram", "handle": "kayttykat"} | |
| 1083 | +{"platform": "instagram", "handle": "kaikupanda"} | |
| 1084 | +{"platform": "instagram", "handle": "yturcotte17"} | |
| 1085 | +{"platform": "instagram", "handle": "verolagachette"} | |
| 1086 | +{"platform": "instagram", "handle": "emiliebruncormier"} | |
| 1087 | +{"platform": "instagram", "handle": "laureantardif"} | |
| 1088 | +{"platform": "instagram", "handle": "ecoledecirquedequebec"} | |
| 1089 | +{"platform": "instagram", "handle": "speedbird3000"} | |
| 1090 | +{"platform": "instagram", "handle": "katiacuradeau"} | |
| 1091 | +{"platform": "instagram", "handle": "annagervaiss"} | |
| 1092 | +{"platform": "instagram", "handle": "kellyannturcot"} | |
| 1093 | +{"platform": "instagram", "handle": "juliette_painchaud"} | |
| 1094 | +{"platform": "tiktok", "handle": "emiliebruncormier"} | |
| 1095 | +{"platform": "tiktok", "handle": "juliettepainchaud"} | |
| 1096 | +{"platform": "instagram", "handle": "ledraguecabaretclub"} | |
| 1097 | +{"platform": "instagram", "handle": "unholyzipper"} | |
| 1098 | +{"platform": "instagram", "handle": "capitals"} | |
| 1099 | +{"platform": "instagram", "handle": "duber72"} | |
| 1100 | +{"platform": "instagram", "handle": "jecoursqc"} | |
| 1101 | +{"platform": "instagram", "handle": "lecoachingducoureur"} | |
| 1102 | +{"platform": "instagram", "handle": "yvesstlouis"} | |
| 1103 | +{"platform": "instagram", "handle": "lacliniqueducoureur"} | |
| 1104 | +{"platform": "instagram", "handle": "dioafitness"} | |
| 1105 | +{"platform": "instagram", "handle": "velocartel"} | |
| 1106 | +{"platform": "instagram", "handle": "kartelmusik"} | |
| 1107 | +{"platform": "instagram", "handle": "blackxlfc"} | |
| 1108 | +{"platform": "instagram", "handle": "goodjudy.ca"} | |
| 1109 | +{"platform": "instagram", "handle": "lunenoiretatouage"} | |
| 1110 | +{"platform": "instagram", "handle": "northerntattoosupply"} | |
| 1111 | +{"platform": "instagram", "handle": "bishoprotary"} | |
| 1112 | +{"platform": "instagram", "handle": "sportsexpertslaurier"} | |
| 1113 | +{"platform": "instagram", "handle": "julbocanada"} | |
| 1114 | +{"platform": "instagram", "handle": "krononutrition"} | |
| 1115 | +{"platform": "instagram", "handle": "heyheytiskenny"} | |
| 1116 | +{"platform": "instagram", "handle": "choco"} | |
| 1117 | +{"platform": "instagram", "handle": "photokurado"} | |
| 1118 | +{"platform": "instagram", "handle": "qbedshostel"} | |
| 1119 | +{"platform": "instagram", "handle": "elorouthe"} | |
| 1120 | +{"platform": "instagram", "handle": "skyvision.optometrie"} | |
| 1121 | +{"platform": "instagram", "handle": "lapetiteecoledeliledorleans"} | |
| 1122 | +{"platform": "instagram", "handle": "undz"} | |
| 1123 | +{"platform": "instagram", "handle": "audrey"} | |
| 1124 | +{"platform": "instagram", "handle": "spekoptics"} | |
| 1125 | +{"platform": "instagram", "handle": "popeyesquebec"} | |
| 1126 | +{"platform": "instagram", "handle": "lecoureurnordique"} | |
| 1127 | +{"platform": "instagram", "handle": "juliette"} | |
| 1128 | +{"platform": "instagram", "handle": "juliettepainchaud"} | |
| 1129 | +{"platform": "instagram", "handle": "eugeniemalenfant"} | |
| 1130 | +{"platform": "instagram", "handle": "pellandworkout"} | |
| 1131 | +{"platform": "instagram", "handle": "rachelledion"} | |
| 1132 | +{"platform": "instagram", "handle": "pcnphysio"} | |
| 1133 | +{"platform": "instagram", "handle": "kev"} | |
| 1134 | +{"platform": "instagram", "handle": "sim"} | |
| 1135 | +{"platform": "instagram", "handle": "elianne"} | |
| 1136 | +{"platform": "instagram", "handle": "jeannot.bou"} | |
| 1137 | +{"platform": "instagram", "handle": "srxproducts"} | |
| 1138 | +{"platform": "instagram", "handle": "supraathletique"} | |
| 1139 | +{"platform": "instagram", "handle": "vb.pod"} | |
| 1140 | +{"platform": "instagram", "handle": "tyrsport"} | |
| 1141 | +{"platform": "instagram", "handle": "ta.tristan"} | |
| 1142 | +{"platform": "instagram", "handle": "julieanneho"} | |
| 1143 | +{"platform": "instagram", "handle": "franceskafournier"} | |
| 1144 | +{"platform": "instagram", "handle": "marc"} | |
| 1145 | +{"platform": "instagram", "handle": "mikechabotfitness"} | |
| 1146 | +{"platform": "instagram", "handle": "claudiatihan"} | |
| 1147 | +{"platform": "instagram", "handle": "maudelavoie"} | |
| 1148 | +{"platform": "instagram", "handle": "emyjade.g"} | |
| 1149 | +{"platform": "instagram", "handle": "recklessxminds"} | |
| 1150 | +{"platform": "instagram", "handle": "rymnebbak"} | |
| 1151 | +{"platform": "instagram", "handle": "myriamlemaay"} | |
| 1152 | +{"platform": "instagram", "handle": "sousinfluencepc"} | |
| 1153 | +{"platform": "instagram", "handle": "essaimcollective"} | |
| 1154 | +{"platform": "instagram", "handle": "girlcrushgang"} | |
| 1155 | +{"platform": "instagram", "handle": "mariloublg_"} | |
| 1156 | +{"platform": "instagram", "handle": "milaydie"} | |
| 1157 | +{"platform": "instagram", "handle": "alanis.desilets"} | |
| 1158 | +{"platform": "instagram", "handle": "lacampagnedici"} | |
| 1159 | +{"platform": "instagram", "handle": "lajasette.co"} | |
| 1160 | +{"platform": "instagram", "handle": "fautquonsappelle"} | |
| 1161 | +{"platform": "instagram", "handle": "emmaverdeyt"} | |
| 1162 | +{"platform": "instagram", "handle": "lisahomsy"} | |
| 1163 | +{"platform": "instagram", "handle": "catherinepeachh"} | |
| 1164 | +{"platform": "instagram", "handle": "appy.secret"} | |
| 1165 | +{"platform": "instagram", "handle": "beatricebouchard"} | |
| 1166 | +{"platform": "instagram", "handle": "cath_belle"} | |
| 1167 | +{"platform": "instagram", "handle": "mahdiba"} | |
| 1168 | +{"platform": "instagram", "handle": "andreanec"} | |
| 1169 | +{"platform": "instagram", "handle": "audreyannej"} | |
| 1170 | +{"platform": "instagram", "handle": "alexcentomo"} | |
| 1171 | +{"platform": "instagram", "handle": "rise"} | |
| 1172 | +{"platform": "instagram", "handle": "hoaka_swimwear"} | |
| 1173 | +{"platform": "instagram", "handle": "hoaka_apparel"} | |
| 1174 | +{"platform": "instagram", "handle": "tastiofficial"} | |
| 1175 | +{"platform": "instagram", "handle": "mariloublg"} | |
| 1176 | +{"platform": "instagram", "handle": "cath"} | |
| 1177 | +{"platform": "instagram", "handle": "mariloubiz"} | |
| 1178 | +{"platform": "instagram", "handle": "boblechef"} | |
| 1179 | +{"platform": "instagram", "handle": "emilierossignolarts"} | |
| 1180 | +{"platform": "instagram", "handle": "antho.tran"} | |
| 1181 | +{"platform": "instagram", "handle": "carlarsenault"} | |
| 1182 | +{"platform": "instagram", "handle": "ricardocuisine"} | |
| 1183 | +{"platform": "instagram", "handle": "influenceursquebecois"} | |
| 1184 | +{"platform": "instagram", "handle": "justinebrouill"} | |
| 1185 | +{"platform": "instagram", "handle": "vivitowers"} | |
| 1186 | +{"platform": "instagram", "handle": "teachme"} | |
| 1187 | +{"platform": "instagram", "handle": "rcitystyle"} | |
| 1188 | +{"platform": "instagram", "handle": "winnspiration"} | |
| 1189 | +{"platform": "instagram", "handle": "pldetails"} | |
| 1190 | +{"platform": "instagram", "handle": "carli.vanheerden"} | |
| 1191 | +{"platform": "instagram", "handle": "toninabaratta"} | |
| 1192 | +{"platform": "instagram", "handle": "shayna"} | |
| 1193 | +{"platform": "instagram", "handle": "natalieast"} | |
| 1194 | +{"platform": "instagram", "handle": "struckblog"} | |
| 1195 | +{"platform": "instagram", "handle": "mylittlesecrets"} | |
| 1196 | +{"platform": "instagram", "handle": "leoniepelletier"} | |
| 1197 | +{"platform": "instagram", "handle": "mfpellerin"} | |
| 1198 | +{"platform": "instagram", "handle": "anacruz"} | |
| 1199 | +{"platform": "instagram", "handle": "working"} | |
| 1200 | +{"platform": "instagram", "handle": "mllegeri"} | |
| 1201 | +{"platform": "instagram", "handle": "thefitfatale"} | |
| 1202 | +{"platform": "tiktok", "handle": "thecordwlu"} | |
| 1203 | +{"platform": "x", "handle": "cordnews"} | |
| 1204 | +{"platform": "instagram", "handle": "festivalfranco"} | |
| 1205 | +{"platform": "instagram", "handle": "amys.clients"} | |
| 1206 | +{"platform": "instagram", "handle": "kyleandcodesign"} | |
| 1207 | +{"platform": "instagram", "handle": "sportsclubatelier"} | |
| 1208 | +{"platform": "instagram", "handle": "bartroveca"} | |
| 1209 | +{"platform": "instagram", "handle": "trovelivingca"} | |
| 1210 | +{"platform": "instagram", "handle": "crissycutz"} | |
| 1211 | +{"platform": "instagram", "handle": "iza.bee"} | |
| 1212 | +{"platform": "instagram", "handle": "narcityquebec"} | |
| 1213 | +{"platform": "instagram", "handle": "makeup"} | |
| 1214 | +{"platform": "instagram", "handle": "schulichmeddent"} | |
| 1215 | +{"platform": "instagram", "handle": "datcrusher"} | |
| 1216 | +{"platform": "instagram", "handle": "wearfigs"} | |
| 1217 | +{"platform": "instagram", "handle": "ashiamade"} | |
| 1218 | +{"platform": "instagram", "handle": "illkeepthese"} | |
| 1219 | +{"platform": "instagram", "handle": "trywhyte.ca"} | |
| 1220 | +{"platform": "instagram", "handle": "untilimdone"} | |
| 1221 | +{"platform": "instagram", "handle": "elite"} | |
| 1222 | +{"platform": "instagram", "handle": "style.withintention"} | |
| 1223 | +{"platform": "instagram", "handle": "boutiqueevolutionhomme"} | |
| 1224 | +{"platform": "instagram", "handle": "reneythemc"} | |
| 1225 | +{"platform": "instagram", "handle": "speke"} | |
| 1226 | +{"platform": "instagram", "handle": "sartoriameucci"} | |
| 1227 | +{"platform": "instagram", "handle": "giabymeucci"} | |
| 1228 | +{"platform": "instagram", "handle": "meuccifoundation"} | |
| 1229 | +{"platform": "instagram", "handle": "midnighthoopclub"} | |
| 1230 | +{"platform": "instagram", "handle": "carnetdyves"} | |
| 1231 | +{"platform": "instagram", "handle": "sj.mortgages"} | |
| 1232 | +{"platform": "instagram", "handle": "lapelinc"} | |
| 1233 | +{"platform": "instagram", "handle": "hellfiretattooco"} | |
| 1234 | +{"platform": "instagram", "handle": "heathenhandrecords"} | |
| 1235 | +{"platform": "instagram", "handle": "nikkarooo"} | |
| 1236 | +{"platform": "instagram", "handle": "forgatherfloralco"} | |
| 1237 | +{"platform": "instagram", "handle": "designingpolly"} | |
| 1238 | +{"platform": "instagram", "handle": "bluehavenwellness"} | |
| 1239 | +{"platform": "instagram", "handle": "livpilateswellness"} | |
| 1240 | +{"platform": "instagram", "handle": "pinklablondeclub"} | |
| 1241 | +{"platform": "instagram", "handle": "pinklablondeatelier"} | |
| 1242 | +{"platform": "instagram", "handle": "maurten"} | |
| 1243 | +{"platform": "instagram", "handle": "rouvyapp"} | |
| 1244 | +{"platform": "instagram", "handle": "bookishlifeofbrie"} | |
| 1245 | +{"platform": "instagram", "handle": "kindred.lindsay"} | |
| 1246 | +{"platform": "instagram", "handle": "kindred.bobcaygeon"} | |
| 1247 | +{"platform": "instagram", "handle": "dmilstein75"} | |
| 1248 | +{"platform": "instagram", "handle": "hrlexperience"} | |
| 1249 | +{"platform": "instagram", "handle": "arccommunity"} | |
| 1250 | +{"platform": "instagram", "handle": "okeanasretreats"} | |
| 1251 | +{"platform": "instagram", "handle": "thesoulslife"} | |
| 1252 | +{"platform": "instagram", "handle": "op.pfc"} | |
| 1253 | +{"platform": "instagram", "handle": "goldenheartcacao"} | |
| 1254 | +{"platform": "instagram", "handle": "sherisesfestival"} | |
| 1255 | +{"platform": "instagram", "handle": "cloudrealty"} | |
| 1256 | +{"platform": "instagram", "handle": "moresoona"} | |
| 1257 | +{"platform": "instagram", "handle": "thebarberszone.ca"} | |
| 1258 | +{"platform": "instagram", "handle": "dishwithjudy"} | |
| 1259 | +{"platform": "instagram", "handle": "lakeshoretattoocollective"} | |
| 1260 | +{"platform": "instagram", "handle": "clearcanvas.lasers"} | |
| 1261 | +{"platform": "instagram", "handle": "sandosmusic"} | |
| 1262 | +{"platform": "instagram", "handle": "amaaramaara"} | |
| 1263 | +{"platform": "instagram", "handle": "williamshirschtalent"} | |
| 1264 | +{"platform": "instagram", "handle": "chum1045"} | |
| 1265 | +{"platform": "instagram", "handle": "cynthiaandjosie"} | |
| 1266 | +{"platform": "instagram", "handle": "olivier.boyer"} | |
| 1267 | +{"platform": "instagram", "handle": "lovetunay"} | |
| 1268 | +{"platform": "instagram", "handle": "pineandpaisleyminiatures"} | |
| 1269 | +{"platform": "instagram", "handle": "drcindyhovington"} | |
| 1270 | +{"platform": "instagram", "handle": "thefeduppotter"} | |
| 1271 | +{"platform": "instagram", "handle": "cedricgrolet"} | |
modified
data/sources.json
+36 −0
@@ -283,6 +283,42 @@ | ||
| 283 | 283 | "signal_identite": "—", |
| 284 | 284 | "cadence": "hebdomadaire (rotation 7 j, lot <=200)", |
| 285 | 285 | "notes": "abonnés, bio, badge, compteurs de médias, avatar" |
| 286 | + }, | |
| 287 | + { | |
| 288 | + "id": "tavily-seed", | |
| 289 | + "famille": "decouverte", | |
| 290 | + "palier": 3, | |
| 291 | + "acces": "dataset local moissonné par le Tavily scout (outils/creator-harvest.py) : handles extraits des annuaires/palmarès/agences QC", | |
| 292 | + "signal_identite": "listes_medias (0.85)", | |
| 293 | + "cadence": "par vague (re-moisson périodique)", | |
| 294 | + "notes": "expansion massive du bassin ; existence vérifiée ensuite par lenrichissement Apify" | |
| 295 | + }, | |
| 296 | + { | |
| 297 | + "id": "snowball-ig", | |
| 298 | + "famille": "decouverte", | |
| 299 | + "palier": 1, | |
| 300 | + "acces": "base interne : profils reliés Instagram (related_profiles) captés par instagram-apify", | |
| 301 | + "signal_identite": "mention (0.60) — à confirmer par enrichissement", | |
| 302 | + "cadence": "quotidienne (parcours en largeur, cap 4000/vague)", | |
| 303 | + "notes": "levier déchelle : chaque profil IG suggère ~10-20 comptes similaires" | |
| 304 | + }, | |
| 305 | + { | |
| 306 | + "id": "patreon-apify", | |
| 307 | + "famille": "enrichissement", | |
| 308 | + "palier": 3, | |
| 309 | + "acces": "acteur Apify maison ka-patreon (données embarquées de la page publique)", | |
| 310 | + "signal_identite": "—", | |
| 311 | + "cadence": "hebdomadaire (rotation 7 j)", | |
| 312 | + "notes": "patrons, publications, nom, avatar" | |
| 313 | + }, | |
| 314 | + { | |
| 315 | + "id": "discord-apify", | |
| 316 | + "famille": "enrichissement", | |
| 317 | + "palier": 2, | |
| 318 | + "acces": "acteur Apify maison ka-discord (API publique d'invitation, code sensible à la casse depuis l'URL)", | |
| 319 | + "signal_identite": "—", | |
| 320 | + "cadence": "hebdomadaire (rotation 7 j)", | |
| 321 | + "notes": "membres approximatifs, en ligne, boosts, nom/description du serveur" | |
| 286 | 322 | } |
| 287 | 323 | ] |
| 288 | 324 | } |
| \ No newline at end of file | ||
modified
docs/connecteurs/INDEX.md
+20 −16
@@ -1,21 +1,21 @@ | ||
| 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 14:47 — ne pas éditer à la main, régénérer._ | |
| 3 | +_Généré automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | −**31 sources au registre** · **9437 créateurs** et **10512 comptes** en BD. | |
| 5 | +**35 sources au registre** · **9437 créateurs** et **10533 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 | 9 | | [`listes-medias`](listes-medias.md) | decouverte | P3 | dataset local compilé (data/seed) | direct | 310 | — | actif | 2026-08-18T10:27… | |
| 10 | 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… | | |
| 11 | +| [`onlyqueb`](onlyqueb.md) | decouverte | P3 | sitemap XML + JSON-LD des pages profil (S… | direct | 253 | 250 (onlyfans) | actif | 2026-08-18T10:32… | | |
| 12 | +| [`youtube-recherche`](youtube-recherche.md) | decouverte | P3 | API JSON | direct | 7876 | 8086 (youtube) | actif | 2026-08-18T17:05… | | |
| 13 | 13 | | [`wikipedia-qc`](wikipedia-qc.md) | decouverte | P3 | API SPARQL publique (Wikidata) | direct | 84 | — | actif | 2026-08-18T14:44… | |
| 14 | 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… | | |
| 15 | +| [`balados-itunes`](balados-itunes.md) | decouverte | P2 | API iTunes Search/Lookup (publique) | direct | 460 | 462 (podcast) | actif | 2026-08-18T20:11… | | |
| 16 | 16 | | [`instagram-profil`](instagram-profil.md) | enrichissement | P4 | pages HTML publiques | Scrapfly | 0 | 495 (instagram) | actif | 2026-08-18T12:04… | |
| 17 | 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… | | |
| 18 | +| [`youtube`](youtube.md) | enrichissement | P2 | API JSON | direct | 0 | 8086 (youtube) | actif | 2026-08-18T17:21… | | |
| 19 | 19 | | [`twitch`](twitch.md) | enrichissement | P2 | API JSON | direct | 0 | 292 (twitch) | actif | 2026-08-18T17:05… | |
| 20 | 20 | | [`link-in-bio`](link-in-bio.md) | enrichissement | P1 | pages HTML publiques | Firecrawl | 0 | — | actif | 2026-08-18T17:29… | |
| 21 | 21 | | [`balados-rss`](balados-rss.md) | enrichissement | P1 | flux RSS publics | direct | 0 | 462 (podcast) | actif | 2026-08-18T13:48… | |
@@ -25,15 +25,19 @@ _Généré automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14: | ||
| 25 | 25 | | [`twitch-decouverte`](twitch-decouverte.md) | decouverte | P3 | pages HTML publiques | direct | 262 | — | actif | 2026-08-18T14:33… | |
| 26 | 26 | | [`kick-decouverte`](kick-decouverte.md) | decouverte | P4 | pages HTML publiques | Scrapfly | 119 | — | actif | 2026-08-18T14:42… | |
| 27 | 27 | | [`region-bio`](region-bio.md) | enrichissement | P1 | pages HTML publiques | direct | 0 | — | actif | 2026-08-18T17:29… | |
| 28 | −| [`instagram-apify`](instagram-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | — | | |
| 29 | −| [`tiktok-apify`](tiktok-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | — | | |
| 30 | −| [`x-apify`](x-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | — | | |
| 31 | −| [`facebook-apify`](facebook-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | — | | |
| 32 | −| [`threads-apify`](threads-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | — | | |
| 33 | −| [`snapchat-apify`](snapchat-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | — | | |
| 28 | +| [`instagram-apify`](instagram-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | 2026-08-18T19:58… | | |
| 29 | +| [`tiktok-apify`](tiktok-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | 2026-08-18T20:05… | | |
| 30 | +| [`x-apify`](x-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | 2026-08-18T19:51… | | |
| 31 | +| [`facebook-apify`](facebook-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | 2026-08-18T19:21… | | |
| 32 | +| [`threads-apify`](threads-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | 2026-08-18T19:21… | | |
| 33 | +| [`snapchat-apify`](snapchat-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | 2026-08-18T19:21… | | |
| 34 | 34 | | [`instagram-decouverte`](instagram-decouverte.md) | decouverte | P4 | API JSON | direct | 0 | — | actif | — | |
| 35 | −| [`youtube-apify`](youtube-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | — | | |
| 36 | −| [`twitch-apify`](twitch-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | — | | |
| 37 | −| [`kick-apify`](kick-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | — | | |
| 35 | +| [`youtube-apify`](youtube-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | 2026-08-18T19:55… | | |
| 36 | +| [`twitch-apify`](twitch-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | 2026-08-18T19:21… | | |
| 37 | +| [`kick-apify`](kick-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | 2026-08-18T19:21… | | |
| 38 | 38 | | [`onlyfans-apify`](onlyfans-apify.md) | enrichissement | P4 | — | — | 0 | — | actif | — | |
| 39 | −| [`fansly-apify`](fansly-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | — | | |
| 39 | +| [`fansly-apify`](fansly-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | 2026-08-18T19:21… | | |
| 40 | +| [`tavily-seed`](tavily-seed.md) | decouverte | P3 | dataset local compilé (data/seed) | direct | 0 | — | actif | — | | |
| 41 | +| [`snowball-ig`](snowball-ig.md) | decouverte | P1 | pages HTML publiques | direct | 0 | — | actif | — | | |
| 42 | +| [`patreon-apify`](patreon-apify.md) | enrichissement | P3 | — | — | 0 | — | actif | — | | |
| 43 | +| [`discord-apify`](discord-apify.md) | enrichissement | P2 | — | — | 0 | — | actif | — | | |
modified
docs/connecteurs/balados-itunes.md
+7 −7
@@ -1,6 +1,6 @@ | ||
| 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 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 460 · touchés : 460 |
| 6 | 6 | |
@@ -39,7 +39,7 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 39 | 39 | | `primary_platform` | Plateforme principale | 100 % | instagram | |
| 40 | 40 | | `platforms` | Comptes sociaux (liste) | 100 % | instagram:@quebec_nostalgie, youtube:@UC10F7nTroeQocT2vqf2LoIw, podcast:@1741442896 | |
| 41 | 41 | | `avatar_url` | Avatar | 100 % | https://is1-ssl.mzstatic.com/image/thumb/Podcasts211/v4/3a/5f/12/3a5f1256-74a6-f716-ffb8-… | |
| 42 | −| `total_reach` | Portée totale (abonnés cumulés) | 0 % | 109744 | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 1 % | 109741 | | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 0 % | https://linktr.ee/QuebecNostalgie | |
| 44 | 44 | |
| 45 | 45 | Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `podcast` (462 comptes en BD, confiance moyenne 0.98). |
@@ -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) : ≈ 40 min | |
| 62 | −- **Dernier passage** : 2026-08-18T14:48:10Z — 460 créateurs, 460 comptes, +27 / ~433, 0 erreur(s), 241 s | |
| 61 | +- **Cadence observée** (médiane sync_log) : ≈ 47 min | |
| 62 | +- **Dernier passage** : 2026-08-18T20:11:39Z — 460 créateurs, 460 comptes, +0 / ~460, 0 erreur(s), 224 s | |
| 63 | 63 | - **Throttling** : 1.5 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`) : 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 | |
| 68 | +- **Complétude clé (découverts)** : niches 100 % · avatar 100 % · portée 1 % · région 8 % | |
| 69 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T20:11:39Z | |
| 70 | +- **Runs journalisés (60 derniers)** : 10, dont 0 avec erreurs | |
| 71 | 71 | |
| 72 | 72 | ## Erreurs connues & dépannage |
| 73 | 73 | |
modified
docs/connecteurs/balados-rss.md
+2 −2
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -48,7 +48,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T17:28:28Z | |
| 51 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T20:11:39Z | |
| 52 | 52 | - **Runs journalisés (60 derniers)** : 6, dont 5 avec erreurs |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/bio-liens.md
+1 −1
@@ -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 14:47 — 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 16:14 — 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 | |
added
docs/connecteurs/discord-apify.md
+45 −0
@@ -0,0 +1,45 @@ | ||
| 1 | +# `discord-apify` — connecteur enrichissement (palier 2) | |
| 2 | + | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | + | |
| 5 | +**État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 | |
| 6 | + | |
| 7 | +## Description de la source | |
| 8 | + | |
| 9 | +- **Notes (registre)** : membres approximatifs, en ligne, boosts, nom/description du serveur | |
| 10 | +- **Signal d'identité** : — (colonne `accounts.signal` / `confidence`) | |
| 11 | +- **Module** : introuvable (vérifier le registre) | |
| 12 | + | |
| 13 | +## Accès | |
| 14 | + | |
| 15 | +- **Accès (registre)** : acteur Apify maison ka-discord (API publique d'invitation, code sensible à la casse depuis l'URL) | |
| 16 | + | |
| 17 | +## Champs récupérés → schéma cible | |
| 18 | + | |
| 19 | +Aucune donnée attribuable à cette source en BD pour l'instant (clés manquantes ou source en attente) — schéma cible : `creators` + `accounts`. | |
| 20 | + | |
| 21 | +## Fréquence & budget | |
| 22 | + | |
| 23 | +- **Cadence déclarée (registre)** : hebdomadaire (rotation 7 j) | |
| 24 | +- **Cadence observée** (médiane sync_log) : — | |
| 25 | + | |
| 26 | +## Volumétrie & complétude | |
| 27 | + | |
| 28 | +- **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 | |
| 29 | +- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | + | |
| 31 | +## Erreurs connues & dépannage | |
| 32 | + | |
| 33 | +Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | + | |
| 35 | +Rejouer la source seule : `python3 run.py sync discord-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='discord-apify' ORDER BY ts DESC LIMIT 5;`). | |
| 36 | + | |
| 37 | +## Licence, attribution & conditions | |
| 38 | + | |
| 39 | +- **Cadre d'accès (registre)** : acteur Apify maison ka-discord (API publique d'invitation, code sensible à la casse depuis l'URL) | |
| 40 | +- **API publique** utilisée selon ses conditions (pas de clé détournée, throttling poli) ; données limitées aux profils publics. | |
| 41 | +- Retrait sur demande : contact@spboucher.ai (opt-out honoré à la prochaine ingestion). | |
| 42 | + | |
| 43 | +## Historique | |
| 44 | + | |
| 45 | +- 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/facebook-apify.md
+9 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `facebook-apify` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,20 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : hebdomadaire (rotation 7 j, lot <=100) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 9 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:21:41Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 0 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:21:41Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:03:59Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 38 | |
| 35 | 39 | Rejouer la source seule : `python3 run.py sync facebook-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='facebook-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 40 | |
@@ -42,4 +46,5 @@ Rejouer la source seule : `python3 run.py sync facebook-apify` · vérifier `syn | ||
| 42 | 46 | |
| 43 | 47 | ## Historique |
| 44 | 48 | |
| 49 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 50 | - 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/fansly-apify.md
+9 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `fansly-apify` — connecteur enrichissement (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,20 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : hebdomadaire (rotation 7 j, lot <=200) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 9 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:21:41Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 0 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:21:41Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:03:58Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 38 | |
| 35 | 39 | Rejouer la source seule : `python3 run.py sync fansly-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='fansly-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 40 | |
@@ -42,4 +46,5 @@ Rejouer la source seule : `python3 run.py sync fansly-apify` · vérifier `sync_ | ||
| 42 | 46 | |
| 43 | 47 | ## Historique |
| 44 | 48 | |
| 49 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 50 | - 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/instagram-apify.md
+10 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `instagram-apify` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,21 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : quotidienne (rotation 5 j, lot <=400) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 18 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:58:58Z — 276 créateurs, 767 comptes, +0 / ~276, 0 erreur(s), 182 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 4, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:29:35Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:21:42Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 38 | +| 2026-08-18T19:03:58Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 39 | |
| 35 | 40 | Rejouer la source seule : `python3 run.py sync instagram-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='instagram-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 41 | |
@@ -42,4 +47,5 @@ Rejouer la source seule : `python3 run.py sync instagram-apify` · vérifier `sy | ||
| 42 | 47 | |
| 43 | 48 | ## Historique |
| 44 | 49 | |
| 50 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 51 | - 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/instagram-decouverte.md
+1 −1
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `instagram-decouverte` — connecteur decouverte (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — 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 | |
modified
docs/connecteurs/instagram-profil.md
+6 −6
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -31,12 +31,12 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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 % | 7023251 | | |
| 35 | −| `verified` | Badge vérifié | 58 % | 1 | | |
| 34 | +| `followers` | Abonnés | 73 % | 7022873 | | |
| 35 | +| `verified` | Badge vérifié | 62 % | 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) | 58 % | {"following": 248, "posts": 667, "is_business": false} | | |
| 39 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T11:35:29Z | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 62 % | {"following": 248, "posts": 667, "is_business": false, "highlight_reels": 22, "avg_likes"… | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T19:58:58Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
@@ -48,7 +48,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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** : 495 — abonnés 70 % · métriques 58 % · dernière vérification 2026-08-18T17:29:45Z | |
| 51 | +- **Comptes `instagram` en BD** : 495 — abonnés 73 % · métriques 62 % · dernière vérification 2026-08-18T20:05:02Z | |
| 52 | 52 | - **Runs journalisés (60 derniers)** : 5, dont 0 avec erreurs |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/kick-apify.md
+9 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `kick-apify` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,20 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : quotidienne (rotation 5 j, lot <=120) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 9 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:21:40Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 0 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:21:40Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:03:58Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 38 | |
| 35 | 39 | Rejouer la source seule : `python3 run.py sync kick-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='kick-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 40 | |
@@ -42,4 +46,5 @@ Rejouer la source seule : `python3 run.py sync kick-apify` · vérifier `sync_lo | ||
| 42 | 46 | |
| 43 | 47 | ## Historique |
| 44 | 48 | |
| 49 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 50 | - 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/kick-decouverte.md
+7 −7
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `kick-decouverte` — connecteur decouverte (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : Scrapfly · Créateurs découverts : 119 · touchés : 119 |
| 6 | 6 | |
@@ -29,17 +29,17 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 29 | 29 | |
| 30 | 30 | | Champ du doc créateur | Contenu | Renseigné | Exemple réel | |
| 31 | 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 … | | |
| 32 | +| `display_name` | Nom public | 100 % | juandemontreal | | |
| 33 | +| `bio` | Bio | 28 % | Gracias por seguirme hasta aqui tmb............ | | |
| 34 | 34 | | `region` | Région | 0 % | — | |
| 35 | 35 | | `city` | Ville | 0 % | — | |
| 36 | 36 | | `niches` | Niches (liste) | 100 % | gaming | |
| 37 | 37 | | `languages` | Langues (liste) | 100 % | fr | |
| 38 | 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 | | |
| 39 | +| `primary_platform` | Plateforme principale | 100 % | tiktok | | |
| 40 | +| `platforms` | Comptes sociaux (liste) | 100 % | tiktok:@juandemontrealoficial, instagram:@juandemontreal, kick:@juandemontreal | | |
| 41 | +| `avatar_url` | Avatar | 40 % | https://files.kick.com/images/user/36432333/profile_image/conversion/2e63a30c-e041-4915-9… | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 56 % | 23455724 | | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 0 % | — | |
| 44 | 44 | |
| 45 | 45 | ## Fréquence & budget |
modified
docs/connecteurs/link-in-bio.md
+1 −1
@@ -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 14:47 — 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 16:14 — 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 | |
modified
docs/connecteurs/listes-medias.md
+6 −6
@@ -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 14:47 — 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 16:14 — 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,7 +29,7 @@ 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 | 73 % | Énola Bédard (born September 14, 2000) is a Canadian dancer, singer, and social media per… | | |
| 32 | +| `bio` | Bio | 76 % | Énola Bédard (born September 14, 2000) is a Canadian dancer, singer, and social media per… | | |
| 33 | 33 | | `region` | Région | 51 % | Capitale-Nationale | |
| 34 | 34 | | `city` | Ville | 51 % | Québec | |
| 35 | 35 | | `niches` | Niches (liste) | 100 % | danse, lifestyle | |
@@ -37,9 +37,9 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 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 | 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 | −| `link_in_bio_url` | Lien-en-bio | 24 % | — | | |
| 40 | +| `avatar_url` | Avatar | 78 % | https://scontent-lga3-2.cdninstagram.com/v/t51.82787-19/515154150_18510310135012441_32506… | | |
| 41 | +| `total_reach` | Portée totale (abonnés cumulés) | 91 % | 24996097 | | |
| 42 | +| `link_in_bio_url` | Lien-en-bio | 25 % | — | | |
| 43 | 43 | |
| 44 | 44 | ## Fréquence & budget |
| 45 | 45 | |
@@ -51,7 +51,7 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 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 75 % · portée 90 % · région 51 % | |
| 54 | +- **Complétude clé (découverts)** : niches 100 % · avatar 78 % · portée 91 % · région 51 % | |
| 55 | 55 | - **Runs journalisés (60 derniers)** : 12, dont 0 avec erreurs |
| 56 | 56 | |
| 57 | 57 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/onlyfans-apify.md
+1 −1
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `onlyfans-apify` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
modified
docs/connecteurs/onlyqueb.md
+7 −7
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -37,12 +37,12 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 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 | −| `platforms` | Comptes sociaux (liste) | 100 % | instagram:@jadelavoie, x:@missjadelavoie, onlyfans:@misslavoie | | |
| 40 | +| `platforms` | Comptes sociaux (liste) | 100 % | instagram:@jadelavoie, tiktok:@miss.jadelavoie, x:@missjadelavoie | | |
| 41 | 41 | | `avatar_url` | Avatar | 100 % | https://storage.googleapis.com/onlyqueb/MQZBiXsbMQa31zxj9P_mabNxNITFBxa6 | |
| 42 | −| `total_reach` | Portée totale (abonnés cumulés) | 20 % | 1571053 | | |
| 43 | −| `link_in_bio_url` | Lien-en-bio | 2 % | — | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 35 % | 2615987 | | |
| 43 | +| `link_in_bio_url` | Lien-en-bio | 5 % | — | | |
| 44 | 44 | |
| 45 | −Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `onlyfans` (248 comptes en BD, confiance moyenne 0.90). | |
| 45 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `onlyfans` (250 comptes en BD, confiance moyenne 0.90). | |
| 46 | 46 | |
| 47 | 47 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 48 | 48 | |---|---|---|---| |
@@ -65,8 +65,8 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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 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 | |
| 68 | +- **Complétude clé (découverts)** : niches 100 % · avatar 100 % · portée 35 % · région 2 % | |
| 69 | +- **Comptes `onlyfans` en BD** : 250 — abonnés 0 % · métriques 0 % · dernière vérification 2026-08-18T19:58:58Z | |
| 70 | 70 | - **Runs journalisés (60 derniers)** : 8, dont 0 avec erreurs |
| 71 | 71 | |
| 72 | 72 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/palmares-apple.md
+2 −2
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -48,7 +48,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T17:28:28Z | |
| 51 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T20:11:39Z | |
| 52 | 52 | - **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
added
docs/connecteurs/patreon-apify.md
+45 −0
@@ -0,0 +1,45 @@ | ||
| 1 | +# `patreon-apify` — connecteur enrichissement (palier 3) | |
| 2 | + | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | + | |
| 5 | +**État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 | |
| 6 | + | |
| 7 | +## Description de la source | |
| 8 | + | |
| 9 | +- **Notes (registre)** : patrons, publications, nom, avatar | |
| 10 | +- **Signal d'identité** : — (colonne `accounts.signal` / `confidence`) | |
| 11 | +- **Module** : introuvable (vérifier le registre) | |
| 12 | + | |
| 13 | +## Accès | |
| 14 | + | |
| 15 | +- **Accès (registre)** : acteur Apify maison ka-patreon (données embarquées de la page publique) | |
| 16 | + | |
| 17 | +## Champs récupérés → schéma cible | |
| 18 | + | |
| 19 | +Aucune donnée attribuable à cette source en BD pour l'instant (clés manquantes ou source en attente) — schéma cible : `creators` + `accounts`. | |
| 20 | + | |
| 21 | +## Fréquence & budget | |
| 22 | + | |
| 23 | +- **Cadence déclarée (registre)** : hebdomadaire (rotation 7 j) | |
| 24 | +- **Cadence observée** (médiane sync_log) : — | |
| 25 | + | |
| 26 | +## Volumétrie & complétude | |
| 27 | + | |
| 28 | +- **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 | |
| 29 | +- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | + | |
| 31 | +## Erreurs connues & dépannage | |
| 32 | + | |
| 33 | +Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | + | |
| 35 | +Rejouer la source seule : `python3 run.py sync patreon-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='patreon-apify' ORDER BY ts DESC LIMIT 5;`). | |
| 36 | + | |
| 37 | +## Licence, attribution & conditions | |
| 38 | + | |
| 39 | +- **Cadre d'accès (registre)** : acteur Apify maison ka-patreon (données embarquées de la page publique) | |
| 40 | +- **API publique** utilisée selon ses conditions (pas de clé détournée, throttling poli) ; données limitées aux profils publics. | |
| 41 | +- Retrait sur demande : contact@spboucher.ai (opt-out honoré à la prochaine ingestion). | |
| 42 | + | |
| 43 | +## Historique | |
| 44 | + | |
| 45 | +- 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/podcastindex.md
+2 −2
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -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** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T17:28:28Z | |
| 50 | +- **Comptes `podcast` en BD** : 462 — abonnés 0 % · métriques 100 % · dernière vérification 2026-08-18T20:11:39Z | |
| 51 | 51 | - **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs |
| 52 | 52 | |
| 53 | 53 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/region-bio.md
+1 −1
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `region-bio` — connecteur enrichissement (palier 1) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — 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 | |
modified
docs/connecteurs/snapchat-apify.md
+9 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `snapchat-apify` — connecteur enrichissement (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,20 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : hebdomadaire (rotation 7 j, lot <=60) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 9 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:21:40Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 0 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:21:40Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:03:59Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 38 | |
| 35 | 39 | Rejouer la source seule : `python3 run.py sync snapchat-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='snapchat-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 40 | |
@@ -42,4 +46,5 @@ Rejouer la source seule : `python3 run.py sync snapchat-apify` · vérifier `syn | ||
| 42 | 46 | |
| 43 | 47 | ## Historique |
| 44 | 48 | |
| 49 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 50 | - 2026-08-18 — vague d'enrichissement : standardisation de la documentation des connecteurs (fiche générée par `scripts/gen_connector_docs.py`). |
added
docs/connecteurs/snowball-ig.md
+54 −0
@@ -0,0 +1,54 @@ | ||
| 1 | +# `snowball-ig` — connecteur decouverte (palier 1) | |
| 2 | + | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | + | |
| 5 | +**État : actif** · Famille : decouverte (enrichment) · Backend : direct · Créateurs découverts : 0 · touchés : 0 | |
| 6 | + | |
| 7 | +## Description de la source | |
| 8 | + | |
| 9 | +Connecteur DÉCOUVERTE par boule de neige — exploite les profils reliés (`related_profiles`) captés par l'enrichissement Instagram (instagram-apify) pour créer de nouvelles fiches. C'est le levier d'échelle : chaque profil IG suggère ~10-20 comptes similaires → parcours en largeur qui fait croître le bassin de dizaines de milliers au fil des vagues quotidiennes. Aucune requête réseau (lit la base). | |
| 10 | + | |
| 11 | +- **Notes (registre)** : levier déchelle : chaque profil IG suggère ~10-20 comptes similaires | |
| 12 | +- **Signal d'identité** : mention (0.60) — à confirmer par enrichissement (colonne `accounts.signal` / `confidence`) | |
| 13 | +- **Module** : `creaka/connectors/snowball.py` — classe `SnowballConnector` (`kind = "enrichment"`) | |
| 14 | + | |
| 15 | +## Accès | |
| 16 | + | |
| 17 | +- **Accès (registre)** : base interne : profils reliés Instagram (related_profiles) captés par instagram-apify | |
| 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.8 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 (parcours en largeur, cap 4000/vague) | |
| 32 | +- **Cadence observée** (médiane sync_log) : — | |
| 33 | +- **Throttling** : 0.8 s entre requêtes (`request_delay`) | |
| 34 | + | |
| 35 | +## Volumétrie & complétude | |
| 36 | + | |
| 37 | +- **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 | |
| 38 | +- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 39 | + | |
| 40 | +## Erreurs connues & dépannage | |
| 41 | + | |
| 42 | +Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 43 | + | |
| 44 | +Rejouer la source seule : `python3 run.py sync snowball-ig` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='snowball-ig' ORDER BY ts DESC LIMIT 5;`). | |
| 45 | + | |
| 46 | +## Licence, attribution & conditions | |
| 47 | + | |
| 48 | +- **Cadre d'accès (registre)** : base interne : profils reliés Instagram (related_profiles) captés par instagram-apify | |
| 49 | +- **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`). | |
| 50 | +- Retrait sur demande : contact@spboucher.ai (opt-out honoré à la prochaine ingestion). | |
| 51 | + | |
| 52 | +## Historique | |
| 53 | + | |
| 54 | +- 2026-08-18 — vague d'enrichissement : standardisation de la documentation des connecteurs (fiche générée par `scripts/gen_connector_docs.py`). | |
added
docs/connecteurs/tavily-seed.md
+54 −0
@@ -0,0 +1,54 @@ | ||
| 1 | +# `tavily-seed` — connecteur decouverte (palier 3) | |
| 2 | + | |
| 3 | +_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | + | |
| 5 | +**État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 0 · touchés : 0 | |
| 6 | + | |
| 7 | +## Description de la source | |
| 8 | + | |
| 9 | +Connecteur DÉCOUVERTE à grande échelle — graines de créateurs québécois moissonnées par le Tavily scout (outils/creator-harvest.py du dépôt groupe-ka-connecteurs) : handles sociaux extraits des pages d'annuaires/palmarès/agences QC. Dataset local (aucune requête ici) : data/seed/qc_creator_seeds.jsonl. L'enrichissement (Apify) vérifie ensuite l'existence et remplit nom/abonnés/contenu. | |
| 10 | + | |
| 11 | +- **Notes (registre)** : expansion massive du bassin ; existence vérifiée ensuite par lenrichissement Apify | |
| 12 | +- **Signal d'identité** : listes_medias (0.85) (colonne `accounts.signal` / `confidence`) | |
| 13 | +- **Module** : `creaka/connectors/tavily_seed.py` — classe `TavilySeedConnector` (`kind = "discovery"`) | |
| 14 | + | |
| 15 | +## Accès | |
| 16 | + | |
| 17 | +- **Accès (registre)** : dataset local moissonné par le Tavily scout (outils/creator-harvest.py) : handles extraits des annuaires/palmarès/agences QC | |
| 18 | +- **Type d'accès (code)** : dataset local compilé (data/seed) | |
| 19 | +- **Endpoint de base** : — | |
| 20 | +- **Pagination** : réponse unique (pas de pagination) | |
| 21 | +- **Backend anti-bot / rendu** : requests direct | |
| 22 | +- **Politesse** : 0.8 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)** : par vague (re-moisson périodique) | |
| 32 | +- **Cadence observée** (médiane sync_log) : — | |
| 33 | +- **Throttling** : 0.8 s entre requêtes (`request_delay`) | |
| 34 | + | |
| 35 | +## Volumétrie & complétude | |
| 36 | + | |
| 37 | +- **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 | |
| 38 | +- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 39 | + | |
| 40 | +## Erreurs connues & dépannage | |
| 41 | + | |
| 42 | +Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 43 | + | |
| 44 | +Rejouer la source seule : `python3 run.py sync tavily-seed` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='tavily-seed' ORDER BY ts DESC LIMIT 5;`). | |
| 45 | + | |
| 46 | +## Licence, attribution & conditions | |
| 47 | + | |
| 48 | +- **Cadre d'accès (registre)** : dataset local moissonné par le Tavily scout (outils/creator-harvest.py) : handles extraits des annuaires/palmarès/agences QC | |
| 49 | +- **Données compilées** de listes et palmarès médias **publics** ; seuls des faits publics (nom, handle, audience approximative) sont conservés. | |
| 50 | +- Retrait sur demande : contact@spboucher.ai (opt-out honoré à la prochaine ingestion). | |
| 51 | + | |
| 52 | +## Historique | |
| 53 | + | |
| 54 | +- 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/threads-apify.md
+9 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `threads-apify` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,20 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : hebdomadaire (rotation 7 j, lot <=60) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 9 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:21:41Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 0 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:21:41Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:03:59Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 38 | |
| 35 | 39 | Rejouer la source seule : `python3 run.py sync threads-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='threads-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 40 | |
@@ -42,4 +46,5 @@ Rejouer la source seule : `python3 run.py sync threads-apify` · vérifier `sync | ||
| 42 | 46 | |
| 43 | 47 | ## Historique |
| 44 | 48 | |
| 49 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 50 | - 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-apify.md
+10 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `tiktok-apify` — connecteur enrichissement (palier 4) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,21 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : quotidienne (rotation 5 j, lot <=300) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 31 min | |
| 25 | +- **Dernier passage** : 2026-08-18T20:05:02Z — 176 créateurs, 642 comptes, +0 / ~176, 38 erreur(s), 364 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 3, dont 1 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T20:05:02Z | 38 | — | | |
| 37 | +| 2026-08-18T19:21:42Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 38 | +| 2026-08-18T19:03:58Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 39 | |
| 35 | 40 | Rejouer la source seule : `python3 run.py sync tiktok-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='tiktok-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 41 | |
@@ -42,4 +47,5 @@ Rejouer la source seule : `python3 run.py sync tiktok-apify` · vérifier `sync_ | ||
| 42 | 47 | |
| 43 | 48 | ## Historique |
| 44 | 49 | |
| 50 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 51 | - 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 14:47 — 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 16:14 — 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 | |
@@ -29,14 +29,14 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | −| `handle` | Handle | 100 % | enola.bedard | | |
| 33 | −| `url` | URL du profil | 100 % | https://www.tiktok.com/@enola.bedard | | |
| 34 | −| `followers` | Abonnés | 63 % | 17000000 | | |
| 35 | −| `verified` | Badge vérifié | 59 % | 1 | | |
| 36 | −| `confidence` | Confiance d'identité | 100 % | 0.85 | | |
| 37 | −| `signal` | Signal d'identité | 100 % | base_publique | | |
| 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 | | |
| 32 | +| `handle` | Handle | 100 % | juandemontrealoficial | | |
| 33 | +| `url` | URL du profil | 100 % | https://www.tiktok.com/@juandemontrealoficial | | |
| 34 | +| `followers` | Abonnés | 84 % | 19810972 | | |
| 35 | +| `verified` | Badge vérifié | 83 % | 1 | | |
| 36 | +| `confidence` | Confiance d'identité | 100 % | 0.9 | | |
| 37 | +| `signal` | Signal d'identité | 100 % | cross_link | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 83 % | {"following": 3800, "likes": 686001479, "videos": 5366, "friends": 3637, "is_seller": fal… | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T20:05:02Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
@@ -48,7 +48,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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** : 224 — abonnés 63 % · métriques 59 % · dernière vérification 2026-08-18T17:29:45Z | |
| 51 | +- **Comptes `tiktok` en BD** : 224 — abonnés 84 % · métriques 83 % · dernière vérification 2026-08-18T20:05:02Z | |
| 52 | 52 | - **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/twitch-apify.md
+9 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `twitch-apify` — connecteur enrichissement (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,20 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : quotidienne (rotation 5 j, lot <=300) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 9 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:21:40Z — 0 créateurs, 0 comptes, +0 / ~0, 0 erreur(s), 0 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 3, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:21:40Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:03:58Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 38 | |
| 35 | 39 | Rejouer la source seule : `python3 run.py sync twitch-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='twitch-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 40 | |
@@ -42,4 +46,5 @@ Rejouer la source seule : `python3 run.py sync twitch-apify` · vérifier `sync_ | ||
| 42 | 46 | |
| 43 | 47 | ## Historique |
| 44 | 48 | |
| 49 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 50 | - 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-decouverte.md
+2 −2
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `twitch-decouverte` — connecteur decouverte (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 262 · touchés : 262 |
| 6 | 6 | |
@@ -38,7 +38,7 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 38 | 38 | | `primary_platform` | Plateforme principale | 100 % | twitch | |
| 39 | 39 | | `platforms` | Comptes sociaux (liste) | 100 % | twitch:@plaqueboymax | |
| 40 | 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 | | |
| 41 | +| `total_reach` | Portée totale (abonnés cumulés) | 74 % | 2841236 | | |
| 42 | 42 | | `link_in_bio_url` | Lien-en-bio | 0 % | — | |
| 43 | 43 | |
| 44 | 44 | ## Fréquence & budget |
modified
docs/connecteurs/twitch.md
+6 −6
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -31,12 +31,12 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `handle` | Handle | 100 % | xqc | |
| 33 | 33 | | `url` | URL du profil | 100 % | https://www.twitch.tv/xqc | |
| 34 | −| `followers` | Abonnés | 98 % | 12535878 | | |
| 35 | −| `verified` | Badge vérifié | 6 % | 1 | | |
| 34 | +| `followers` | Abonnés | 98 % | 12535875 | | |
| 35 | +| `verified` | Badge vérifié | 96 % | 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) | 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 | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 97 % | {"last_stream": "2026-08-18T08:03:23.924661Z", "game": "Just Chatting", "is_partner": tru… | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T19:10:08Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
@@ -48,7 +48,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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** : 292 — abonnés 98 % · métriques 79 % · dernière vérification 2026-08-18T17:28:20Z | |
| 51 | +- **Comptes `twitch` en BD** : 292 — abonnés 98 % · métriques 97 % · dernière vérification 2026-08-18T20:05:02Z | |
| 52 | 52 | - **Runs journalisés (60 derniers)** : 4, dont 0 avec erreurs |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/wikidata-qc.md
+12 −12
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -29,17 +29,17 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 29 | 29 | |
| 30 | 30 | | Champ du doc créateur | Contenu | Renseigné | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
| 32 | −| `display_name` | Nom public | 100 % | xQc | | |
| 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 | −| `niches` | Niches (liste) | 100 % | gaming, lifestyle | | |
| 37 | −| `languages` | Langues (liste) | 100 % | en, fr | | |
| 32 | +| `display_name` | Nom public | 100 % | Nigel Braun | | |
| 33 | +| `bio` | Bio | 78 % | Capturing the natural beauty of chemistry Find me on YouTube: @NileRed/@NileBlue | | |
| 34 | +| `region` | Région | 18 % | — | | |
| 35 | +| `city` | Ville | 18 % | — | | |
| 36 | +| `niches` | Niches (liste) | 100 % | lifestyle | | |
| 37 | +| `languages` | Langues (liste) | 100 % | fr | | |
| 38 | 38 | | `creator_type` | Type de créateur | 100 % | influenceur | |
| 39 | −| `primary_platform` | Plateforme principale | 100 % | twitch | | |
| 40 | −| `platforms` | Comptes sociaux (liste) | 99 % | twitch:@xqc, youtube:@UCmDTrq0LNgPodDOFZiSbsww, x:@xqc | | |
| 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 | | |
| 39 | +| `primary_platform` | Plateforme principale | 100 % | youtube | | |
| 40 | +| `platforms` | Comptes sociaux (liste) | 99 % | youtube:@nilered, tiktok:@nilered, instagram:@nile.red | | |
| 41 | +| `avatar_url` | Avatar | 75 % | https://scontent-yyz1-1.cdninstagram.com/v/t51.2885-19/441008830_1124225362150102_4410959… | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 67 % | 22759897 | | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 19 % | — | |
| 44 | 44 | |
| 45 | 45 | ## Fréquence & budget |
@@ -52,7 +52,7 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 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 73 % · portée 64 % · région 18 % | |
| 55 | +- **Complétude clé (découverts)** : niches 100 % · avatar 75 % · portée 67 % · région 18 % | |
| 56 | 56 | - **Runs journalisés (60 derniers)** : 10, dont 1 avec erreurs |
| 57 | 57 | |
| 58 | 58 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/wikipedia-qc.md
+4 −4
@@ -1,6 +1,6 @@ | ||
| 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 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 84 · touchés : 84 |
| 6 | 6 | |
@@ -38,8 +38,8 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 38 | 38 | | `creator_type` | Type de créateur | 100 % | youtubeur | |
| 39 | 39 | | `primary_platform` | Plateforme principale | 100 % | x | |
| 40 | 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 | | |
| 41 | +| `avatar_url` | Avatar | 83 % | https://upload.wikimedia.org/wikipedia/commons/thumb/a/a6/Unoenjoy.jpg/500px-Unoenjoy.jpg… | | |
| 42 | +| `total_reach` | Portée totale (abonnés cumulés) | 17 % | 268180 | | |
| 43 | 43 | | `link_in_bio_url` | Lien-en-bio | 5 % | http://linktr.ee/eviluno | |
| 44 | 44 | |
| 45 | 45 | ## Fréquence & budget |
@@ -52,7 +52,7 @@ Source de **découverte** : produit des fiches `Creator` (tables `creators` + `a | ||
| 52 | 52 | ## Volumétrie & complétude |
| 53 | 53 | |
| 54 | 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 % | |
| 55 | +- **Complétude clé (découverts)** : niches 100 % · avatar 83 % · portée 17 % · région 49 % | |
| 56 | 56 | - **Runs journalisés (60 derniers)** : 4, dont 0 avec erreurs |
| 57 | 57 | |
| 58 | 58 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/x-apify.md
+12 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `x-apify` — connecteur enrichissement (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,23 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : quotidienne (rotation 5 j, lot <=300) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 8 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:51:07Z — 30 créateurs, 121 comptes, +0 / ~30, 2 erreur(s), 515 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 6, dont 1 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:51:07Z | 2 | — | | |
| 37 | +| 2026-08-18T19:39:57Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 38 | +| 2026-08-18T19:33:34Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 39 | +| 2026-08-18T19:25:32Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 40 | +| 2026-08-18T19:21:41Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 41 | |
| 35 | 42 | Rejouer la source seule : `python3 run.py sync x-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='x-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 43 | |
@@ -42,4 +49,5 @@ Rejouer la source seule : `python3 run.py sync x-apify` · vérifier `sync_log` | ||
| 42 | 49 | |
| 43 | 50 | ## Historique |
| 44 | 51 | |
| 52 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 53 | - 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/x-profil.md
+6 −6
@@ -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 14:47 — 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 16:14 — 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 | |
@@ -31,12 +31,12 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 31 | 31 | |---|---|---|---| |
| 32 | 32 | | `handle` | Handle | 100 % | xqc | |
| 33 | 33 | | `url` | URL du profil | 100 % | https://x.com/xqc | |
| 34 | −| `followers` | Abonnés | 18 % | 1598794 | | |
| 35 | −| `verified` | Badge vérifié | 0 % | — | | |
| 34 | +| `followers` | Abonnés | 26 % | 1599135 | | |
| 35 | +| `verified` | Badge vérifié | 13 % | 1 | | |
| 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) | 32 % | {"following": 526, "x_checked": "2026-08-18T06:14:55Z"} | | |
| 39 | −| `last_checked` | Dernière vérification | 100 % | 2026-08-18T14:44:09Z | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 39 % | {"following": 526, "x_checked": "2026-08-18T06:14:55Z", "tweets": 4328, "location": "", "… | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T19:58:58Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
@@ -48,7 +48,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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** : 228 — abonnés 18 % · métriques 32 % · dernière vérification 2026-08-18T17:29:45Z | |
| 51 | +- **Comptes `x` en BD** : 228 — abonnés 26 % · métriques 39 % · dernière vérification 2026-08-18T19:58:58Z | |
| 52 | 52 | - **Runs journalisés (60 derniers)** : 6, dont 6 avec erreurs |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/youtube-apify.md
+12 −4
@@ -1,6 +1,6 @@ | ||
| 1 | 1 | # `youtube-apify` — connecteur enrichissement (palier 3) |
| 2 | 2 | |
| 3 | −_Fiche générée automatiquement par `scripts/gen_connector_docs.py` le 2026-08-18 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : enrichissement (enrichissement) · Backend : — · Créateurs découverts : 0 · touchés : 0 |
| 6 | 6 | |
@@ -21,16 +21,23 @@ Aucune donnée attribuable à cette source en BD pour l'instant (clés manquante | ||
| 21 | 21 | ## Fréquence & budget |
| 22 | 22 | |
| 23 | 23 | - **Cadence déclarée (registre)** : quotidienne (rotation 5 j, lot <=300) |
| 24 | −- **Cadence observée** (médiane sync_log) : — | |
| 24 | +- **Cadence observée** (médiane sync_log) : ≈ 8 min | |
| 25 | +- **Dernier passage** : 2026-08-18T19:55:55Z — 1220 créateurs, 1352 comptes, +0 / ~1220, 0 erreur(s), 288 s | |
| 25 | 26 | |
| 26 | 27 | ## Volumétrie & complétude |
| 27 | 28 | |
| 28 | 29 | - **Créateurs découverts par la source** (`doc.source`) : 0 · **fiches touchées** (`source_ids`) : 0 |
| 29 | −- **Runs journalisés (60 derniers)** : 0, dont 0 avec erreurs | |
| 30 | +- **Runs journalisés (60 derniers)** : 6, dont 0 avec erreurs | |
| 30 | 31 | |
| 31 | 32 | ## Erreurs connues & dépannage |
| 32 | 33 | |
| 33 | −Aucune erreur ni alerte dans les 60 derniers runs journalisés. | |
| 34 | +| Passage | Erreurs | Alerte (sync_log) | | |
| 35 | +|---|---|---| | |
| 36 | +| 2026-08-18T19:42:16Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 37 | +| 2026-08-18T19:35:56Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 38 | +| 2026-08-18T19:27:33Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 39 | +| 2026-08-18T19:21:42Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 40 | +| 2026-08-18T19:03:58Z | 0 | 0 créateur retourné — source possiblement bloquée | | |
| 34 | 41 | |
| 35 | 42 | Rejouer la source seule : `python3 run.py sync youtube-apify` · vérifier `sync_log` (`SELECT * FROM sync_log WHERE source='youtube-apify' ORDER BY ts DESC LIMIT 5;`). |
| 36 | 43 | |
@@ -42,4 +49,5 @@ Rejouer la source seule : `python3 run.py sync youtube-apify` · vérifier `sync | ||
| 42 | 49 | |
| 43 | 50 | ## Historique |
| 44 | 51 | |
| 52 | +- 2026-08-18 — plus ancien passage journalisé dans `sync_log` (fenêtre des 60 derniers). | |
| 45 | 53 | - 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/youtube-recherche.md
+5 −5
@@ -1,6 +1,6 @@ | ||
| 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 14:47 — 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 16:14 — ne pas éditer à la main, régénérer._ | |
| 4 | 4 | |
| 5 | 5 | **État : actif** · Famille : decouverte (discovery) · Backend : direct · Créateurs découverts : 7876 · touchés : 7876 |
| 6 | 6 | |
@@ -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) | 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` (8084 comptes en BD, confiance moyenne 0.98). | |
| 45 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `youtube` (8086 comptes en BD, confiance moyenne 0.98). | |
| 46 | 46 | |
| 47 | 47 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 48 | 48 | |---|---|---|---| |
@@ -52,8 +52,8 @@ 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) | 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 | | |
| 55 | +| `metrics` | Métriques détaillées (JSON) | 18 % | {"yt_checked": "2026-08-18T10:08:15Z", "videos": 400, "views": 4647638686, "last_video": … | | |
| 56 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T19:58:58Z | | |
| 57 | 57 | |
| 58 | 58 | ## Fréquence & budget |
| 59 | 59 | |
@@ -66,7 +66,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 66 | 66 | |
| 67 | 67 | - **Créateurs découverts par la source** (`doc.source`) : 7876 · **fiches touchées** (`source_ids`) : 7876 |
| 68 | 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 | |
| 69 | +- **Comptes `youtube` en BD** : 8086 — abonnés 94 % · métriques 18 % · dernière vérification 2026-08-18T20:05:02Z | |
| 70 | 70 | - **Runs journalisés (60 derniers)** : 5, dont 0 avec erreurs |
| 71 | 71 | |
| 72 | 72 | ## Erreurs connues & dépannage |
modified
docs/connecteurs/youtube.md
+5 −5
@@ -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 14:47 — 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 16:14 — 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` (8084 comptes en BD, confiance moyenne 0.98). | |
| 28 | +Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les plateforme(s) `youtube` (8086 comptes en BD, confiance moyenne 0.98). | |
| 29 | 29 | |
| 30 | 30 | | Colonne `accounts` | Contenu | Renseignée | Exemple réel | |
| 31 | 31 | |---|---|---|---| |
@@ -35,8 +35,8 @@ 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) | 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 | | |
| 38 | +| `metrics` | Métriques détaillées (JSON) | 18 % | {"yt_checked": "2026-08-18T10:08:15Z", "videos": 400, "views": 4647638686, "last_video": … | | |
| 39 | +| `last_checked` | Dernière vérification | 100 % | 2026-08-18T19:58:58Z | | |
| 40 | 40 | |
| 41 | 41 | ## Fréquence & budget |
| 42 | 42 | |
@@ -48,7 +48,7 @@ Cible d'**enrichissement** : colonnes de la table `accounts` pour la/les platefo | ||
| 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** : 8084 — abonnés 94 % · métriques 10 % · dernière vérification 2026-08-18T17:29:45Z | |
| 51 | +- **Comptes `youtube` en BD** : 8086 — abonnés 94 % · métriques 18 % · dernière vérification 2026-08-18T20:05:02Z | |
| 52 | 52 | - **Runs journalisés (60 derniers)** : 5, dont 3 avec erreurs |
| 53 | 53 | |
| 54 | 54 | ## Erreurs connues & dépannage |
modified
frontend/dist/index.html
+98 −14
@@ -722,12 +722,47 @@ select.f.active{background-color:var(--accent-soft);color:var(--ink);border-colo | ||
| 722 | 722 | background:var(--surface);border:1.5px solid var(--ink);border-radius:var(--r-card); |
| 723 | 723 | padding:13px 17px;box-shadow:var(--shadow-off-soft)} |
| 724 | 724 | .sect-title{font-size:19px;margin:36px 0 15px;display:flex;align-items:center;gap:10px;text-transform:uppercase} |
| 725 | −.acc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:14px} | |
| 725 | +.acc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:14px} | |
| 726 | 726 | @media(max-width:640px){.acc-grid{grid-template-columns:1fr}} |
| 727 | −.acc{display:flex;align-items:center;gap:13px;background:var(--surface); | |
| 728 | − border:1.5px solid var(--ink);border-radius:var(--r-card);padding:14px 16px; | |
| 729 | − box-shadow:var(--shadow-off-soft);transition:transform .16s ease,box-shadow .16s ease;min-width:0} | |
| 730 | −.acc:hover{transform:translate(-2px,-2px);box-shadow:var(--shadow-off)} | |
| 727 | +.acc-card{display:flex;flex-direction:column;background:var(--surface); | |
| 728 | + border:1.5px solid var(--ink);border-radius:var(--r-card); | |
| 729 | + box-shadow:var(--shadow-off-soft);transition:transform .16s ease,box-shadow .16s ease; | |
| 730 | + min-width:0;overflow:hidden} | |
| 731 | +.acc-card:hover{transform:translate(-2px,-2px);box-shadow:var(--shadow-off)} | |
| 732 | +.acc{display:flex;align-items:center;gap:13px;padding:14px 16px;min-width:0} | |
| 733 | +/* rangée de stats riches */ | |
| 734 | +.astat-row{display:flex;flex-wrap:wrap;gap:6px;padding:0 16px 10px} | |
| 735 | +.astat{display:flex;flex-direction:column;background:var(--surface-2); | |
| 736 | + border:1px solid var(--line);border-radius:var(--r-ctl);padding:4px 9px;line-height:1.1} | |
| 737 | +.astat b{font-family:var(--font-display);font-size:13px;color:var(--ink);font-weight:700} | |
| 738 | +.astat span{font-family:var(--font-mono);font-size:8.5px;color:var(--ink-3); | |
| 739 | + text-transform:uppercase;letter-spacing:.05em;font-weight:700;margin-top:1px} | |
| 740 | +.abadge-row{display:flex;flex-wrap:wrap;gap:5px;padding:0 16px 12px} | |
| 741 | +.abadge{display:inline-flex;background:var(--lime-soft);color:var(--green-deep); | |
| 742 | + border:1px solid var(--line);border-radius:var(--r-ctl);padding:2px 8px; | |
| 743 | + font-family:var(--font-mono);font-size:9.5px;font-weight:700;letter-spacing:.02em} | |
| 744 | +.abadge.live{background:#ffe3e0;color:#b0201a;border-color:#b0201a} | |
| 745 | +/* bande de contenu récent */ | |
| 746 | +.cstrip{border-top:1px dashed var(--line);padding:11px 0 13px} | |
| 747 | +.cstrip-h{font-family:var(--font-mono);font-size:9.5px;font-weight:700;color:var(--ink-3); | |
| 748 | + text-transform:uppercase;letter-spacing:.07em;padding:0 16px 8px} | |
| 749 | +.cstrip-scroll{display:flex;gap:9px;overflow-x:auto;padding:0 16px 3px;scroll-snap-type:x proximity} | |
| 750 | +.cstrip-scroll::-webkit-scrollbar{height:5px} | |
| 751 | +.cstrip-scroll::-webkit-scrollbar-thumb{background:var(--line);border-radius:3px} | |
| 752 | +.cstrip-item{flex:none;width:120px;scroll-snap-align:start;text-decoration:none;color:inherit; | |
| 753 | + display:flex;flex-direction:column;gap:4px} | |
| 754 | +.cstrip-thumb{position:relative;display:block;width:120px;height:120px;border-radius:9px; | |
| 755 | + background-size:cover;background-position:center;background-color:var(--surface-2); | |
| 756 | + border:1px solid var(--line);overflow:hidden} | |
| 757 | +.cstrip-thumb.noimg{display:flex;align-items:center;justify-content:center} | |
| 758 | +.cstrip-thumb.noimg svg{width:34px;height:34px;opacity:.35} | |
| 759 | +.cstrip-play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%); | |
| 760 | + color:#fff;font-size:20px;text-shadow:0 1px 4px rgba(0,0,0,.6)} | |
| 761 | +.cstrip-dur{position:absolute;right:5px;bottom:5px;background:rgba(0,0,0,.78);color:#fff; | |
| 762 | + font-family:var(--font-mono);font-size:9px;padding:1px 5px;border-radius:5px} | |
| 763 | +.cstrip-cap{font-size:11px;line-height:1.25;color:var(--ink-2);display:-webkit-box; | |
| 764 | + -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden} | |
| 765 | +.cstrip-meta{font-family:var(--font-mono);font-size:9px;color:var(--ink-3);line-height:1.2} | |
| 731 | 766 | .acc .plat{width:44px;height:44px;border-radius:9px;flex:none} |
| 732 | 767 | .acc .plat svg{width:20px;height:20px} |
| 733 | 768 | .acc-mid{min-width:0;flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden} |
@@ -1170,6 +1205,30 @@ async function reload(more){ | ||
| 1170 | 1205 | } |
| 1171 | 1206 | |
| 1172 | 1207 | /* ---------- page créateur ---------- */ |
| 1208 | +/* --- bande de contenu récent par compte (enrichissement Apify) --- */ | |
| 1209 | +const _relTime=ts=>{if(!ts)return"";if(typeof ts==="string"&&!/^\d+$/.test(ts))return esc(ts.slice(0,10)); | |
| 1210 | + const d=Math.floor((Date.now()/1000-Number(ts))/86400); | |
| 1211 | + return d<=0?"aujourd'hui":d===1?"hier":d<30?d+" j":d<365?Math.floor(d/30)+" mois":Math.floor(d/365)+" ans";}; | |
| 1212 | +function contentStrip(a){ | |
| 1213 | + const m=a.metrics||{}; | |
| 1214 | + const items=m.recent_posts||m.recent_videos||m.recent_tweets||[]; | |
| 1215 | + if(!items.length)return""; | |
| 1216 | + const cards=items.slice(0,8).map(it=>{ | |
| 1217 | + const img=it.display_url||it.thumbnail_url||""; | |
| 1218 | + const title=esc((it.caption||it.title||it.text||"").slice(0,90)); | |
| 1219 | + const stats=[ | |
| 1220 | + it.views!=null?fmt.format(it.views)+" vues":null, | |
| 1221 | + it.likes!=null?fmt.format(it.likes)+" ❤":null, | |
| 1222 | + it.comments!=null?fmt.format(it.comments)+" 💬":null, | |
| 1223 | + it.retweets!=null?fmt.format(it.retweets)+" ↻":null, | |
| 1224 | + ].filter(Boolean).join(" · "); | |
| 1225 | + const when=_relTime(it.timestamp||it.published_at||it.published||it.created_at); | |
| 1226 | + return `<a class="cstrip-item" href="${esc(it.url||a.url)}" target="_blank" rel="noopener" onclick="event.stopPropagation()"> | |
| 1227 | + ${img?`<span class="cstrip-thumb" style="background-image:url('${esc(img)}')">${it.type==="video"||it.type==="reel"||it.duration?'<span class="cstrip-play">▶</span>':""}${it.duration?`<span class="cstrip-dur">${esc(it.duration)}</span>`:""}</span>`:`<span class="cstrip-thumb noimg">${icon(a.platform)}</span>`} | |
| 1228 | + ${title?`<span class="cstrip-cap">${title}</span>`:""} | |
| 1229 | + <span class="cstrip-meta">${stats}${when?` · ${when}`:""}</span></a>`}).join(""); | |
| 1230 | + return `<div class="cstrip"><div class="cstrip-h">Contenu récent</div><div class="cstrip-scroll">${cards}</div></div>`; | |
| 1231 | +} | |
| 1173 | 1232 | async function renderCreator(id){ |
| 1174 | 1233 | app.innerHTML=header()+`<div class="container"><div class="spin"></div></div>`+footer()+tabbar("");bindNav(); |
| 1175 | 1234 | let c;try{c=await api("/api/creators/"+encodeURIComponent(id))} |
@@ -1179,18 +1238,43 @@ async function renderCreator(id){ | ||
| 1179 | 1238 | const verified=(c.platforms||[]).some(a=>a.verified); |
| 1180 | 1239 | const niches=(c.niches||[]).map(n=>`<span class="mchip">${NICHE_LBL[n]||n}</span>`).join(""); |
| 1181 | 1240 | const M_LBL={following:"abonnements",posts:"publications",likes:"j'aime", |
| 1182 | − views:"vues",videos:"vidéos",episodes:"épisodes"}; | |
| 1241 | + views:"vues",videos:"vidéos",episodes:"épisodes",images:"photos", | |
| 1242 | + friends:"amis",listed:"listes"}; | |
| 1183 | 1243 | const accs=(c.platforms||[]).map(a=>{const p=PLAT[a.platform]||PLAT.autre; |
| 1184 | 1244 | const conf=(a.confidence||0)>=0.75?["hi","confiance élevée"]:["mid","à confirmer"]; |
| 1185 | − const mx=Object.entries(a.metrics||{}).filter(([k,v])=>M_LBL[k]&&v!=null) | |
| 1245 | + const m=a.metrics||{}; | |
| 1246 | + const mx=Object.entries(m).filter(([k,v])=>M_LBL[k]&&v!=null) | |
| 1186 | 1247 | .map(([k,v])=>`${fmt.format(v)} ${M_LBL[k]}`).join(" · "); |
| 1187 | − return `<a class="acc" href="${esc(a.url)}" target="_blank" rel="noopener"> | |
| 1188 | − <span class="plat" style="background:${p.color}">${icon(a.platform)}</span> | |
| 1189 | − <span class="acc-mid"><span class="acc-name">${p.label}${a.verified?checkSvg:""}</span> | |
| 1190 | − <span class="acc-handle">@${esc(a.handle)}</span> | |
| 1191 | − <span class="acc-handle" style="overflow:visible"><span class="conf ${conf[0]}" title="Score de rattachement ${Math.round((a.confidence||0)*100)} %">${conf[1]}</span>${mx?` <span style="font-size:11px">${mx}</span>`:""}</span></span> | |
| 1192 | − <span class="acc-right">${a.followers?`<b>${fmt.format(a.followers)}</b><span>abonnés</span>`:`<span style="font-size:11px">voir le profil ↗</span>`}</span></a>`}).join(""); | |
| 1193 | − const checked=(c.platforms||[]).map(a=>a.last_checked).filter(Boolean).sort().pop(); | |
| 1248 | + // rangée de statistiques riches (enrichissement Apify multi-plateforme) | |
| 1249 | + const stat=(v,l)=>v==null?"":`<span class="astat"><b>${typeof v==="number"?fmt.format(v):esc(v)}</b><span>${l}</span></span>`; | |
| 1250 | + const stats=[ | |
| 1251 | + stat(m.engagement_rate_pct!=null?m.engagement_rate_pct+" %":null,"engagement"), | |
| 1252 | + stat(m.avg_likes,"j'aime/moy"), | |
| 1253 | + stat(m.avg_views!=null?m.avg_views:m.avg_video_views,"vues/moy"), | |
| 1254 | + stat(m.avg_retweets,"RT/moy"), | |
| 1255 | + stat(m.posts_per_week!=null?m.posts_per_week:m.tweets_per_week,"/semaine"), | |
| 1256 | + ].filter(Boolean).join(""); | |
| 1257 | + const badges=[ | |
| 1258 | + m.is_partner?'<span class="abadge">Partenaire</span>':"", | |
| 1259 | + m.is_affiliate&&!m.is_partner?'<span class="abadge">Affilié</span>':"", | |
| 1260 | + m.is_live_now?'<span class="abadge live">● En direct</span>':"", | |
| 1261 | + m.is_seller?'<span class="abadge">Boutique</span>':"", | |
| 1262 | + m.is_free===true?'<span class="abadge">Gratuit</span>':"", | |
| 1263 | + m.has_story?'<span class="abadge">Story active</span>':"", | |
| 1264 | + (m.recent_games||[]).length?`<span class="abadge">${esc((m.recent_games||[])[0])}</span>`:"", | |
| 1265 | + (m.top_hashtags||[]).slice(0,2).map(h=>`<span class="abadge">#${esc(h)}</span>`).join(""), | |
| 1266 | + ].filter(Boolean).join(""); | |
| 1267 | + return `<div class="acc-card"> | |
| 1268 | + <a class="acc" href="${esc(a.url)}" target="_blank" rel="noopener"> | |
| 1269 | + <span class="plat" style="background:${p.color}">${icon(a.platform)}</span> | |
| 1270 | + <span class="acc-mid"><span class="acc-name">${p.label}${a.verified?checkSvg:""}</span> | |
| 1271 | + <span class="acc-handle">@${esc(a.handle)}</span> | |
| 1272 | + <span class="acc-handle" style="overflow:visible"><span class="conf ${conf[0]}" title="Score de rattachement ${Math.round((a.confidence||0)*100)} %">${conf[1]}</span>${mx?` <span style="font-size:11px">${mx}</span>`:""}</span></span> | |
| 1273 | + <span class="acc-right">${a.followers?`<b>${fmt.format(a.followers)}</b><span>abonnés</span>`:`<span style="font-size:11px">voir le profil ↗</span>`}</span></a> | |
| 1274 | + ${stats?`<div class="astat-row">${stats}</div>`:""} | |
| 1275 | + ${badges?`<div class="abadge-row">${badges}</div>`:""} | |
| 1276 | + ${contentStrip(a)}</div>`}).join(""); | |
| 1277 | + const checked=(c.platforms||[]).map(a=>(a.metrics||{}).instagram_apify_at||a.last_checked).filter(Boolean).sort().pop()||(c.platforms||[]).map(a=>a.last_checked).filter(Boolean).sort().pop(); | |
| 1194 | 1278 | app.innerHTML=header()+` |
| 1195 | 1279 | <div class="container cpage"> |
| 1196 | 1280 | <a class="backlink" href="/" data-nav>← Tous les créateurs</a> |
modified
frontend/src/index.template.html
+98 −14
@@ -264,12 +264,47 @@ select.f.active{background-color:var(--accent-soft);color:var(--ink);border-colo | ||
| 264 | 264 | background:var(--surface);border:1.5px solid var(--ink);border-radius:var(--r-card); |
| 265 | 265 | padding:13px 17px;box-shadow:var(--shadow-off-soft)} |
| 266 | 266 | .sect-title{font-size:19px;margin:36px 0 15px;display:flex;align-items:center;gap:10px;text-transform:uppercase} |
| 267 | −.acc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:14px} | |
| 267 | +.acc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:14px} | |
| 268 | 268 | @media(max-width:640px){.acc-grid{grid-template-columns:1fr}} |
| 269 | −.acc{display:flex;align-items:center;gap:13px;background:var(--surface); | |
| 270 | − border:1.5px solid var(--ink);border-radius:var(--r-card);padding:14px 16px; | |
| 271 | − box-shadow:var(--shadow-off-soft);transition:transform .16s ease,box-shadow .16s ease;min-width:0} | |
| 272 | −.acc:hover{transform:translate(-2px,-2px);box-shadow:var(--shadow-off)} | |
| 269 | +.acc-card{display:flex;flex-direction:column;background:var(--surface); | |
| 270 | + border:1.5px solid var(--ink);border-radius:var(--r-card); | |
| 271 | + box-shadow:var(--shadow-off-soft);transition:transform .16s ease,box-shadow .16s ease; | |
| 272 | + min-width:0;overflow:hidden} | |
| 273 | +.acc-card:hover{transform:translate(-2px,-2px);box-shadow:var(--shadow-off)} | |
| 274 | +.acc{display:flex;align-items:center;gap:13px;padding:14px 16px;min-width:0} | |
| 275 | +/* rangée de stats riches */ | |
| 276 | +.astat-row{display:flex;flex-wrap:wrap;gap:6px;padding:0 16px 10px} | |
| 277 | +.astat{display:flex;flex-direction:column;background:var(--surface-2); | |
| 278 | + border:1px solid var(--line);border-radius:var(--r-ctl);padding:4px 9px;line-height:1.1} | |
| 279 | +.astat b{font-family:var(--font-display);font-size:13px;color:var(--ink);font-weight:700} | |
| 280 | +.astat span{font-family:var(--font-mono);font-size:8.5px;color:var(--ink-3); | |
| 281 | + text-transform:uppercase;letter-spacing:.05em;font-weight:700;margin-top:1px} | |
| 282 | +.abadge-row{display:flex;flex-wrap:wrap;gap:5px;padding:0 16px 12px} | |
| 283 | +.abadge{display:inline-flex;background:var(--lime-soft);color:var(--green-deep); | |
| 284 | + border:1px solid var(--line);border-radius:var(--r-ctl);padding:2px 8px; | |
| 285 | + font-family:var(--font-mono);font-size:9.5px;font-weight:700;letter-spacing:.02em} | |
| 286 | +.abadge.live{background:#ffe3e0;color:#b0201a;border-color:#b0201a} | |
| 287 | +/* bande de contenu récent */ | |
| 288 | +.cstrip{border-top:1px dashed var(--line);padding:11px 0 13px} | |
| 289 | +.cstrip-h{font-family:var(--font-mono);font-size:9.5px;font-weight:700;color:var(--ink-3); | |
| 290 | + text-transform:uppercase;letter-spacing:.07em;padding:0 16px 8px} | |
| 291 | +.cstrip-scroll{display:flex;gap:9px;overflow-x:auto;padding:0 16px 3px;scroll-snap-type:x proximity} | |
| 292 | +.cstrip-scroll::-webkit-scrollbar{height:5px} | |
| 293 | +.cstrip-scroll::-webkit-scrollbar-thumb{background:var(--line);border-radius:3px} | |
| 294 | +.cstrip-item{flex:none;width:120px;scroll-snap-align:start;text-decoration:none;color:inherit; | |
| 295 | + display:flex;flex-direction:column;gap:4px} | |
| 296 | +.cstrip-thumb{position:relative;display:block;width:120px;height:120px;border-radius:9px; | |
| 297 | + background-size:cover;background-position:center;background-color:var(--surface-2); | |
| 298 | + border:1px solid var(--line);overflow:hidden} | |
| 299 | +.cstrip-thumb.noimg{display:flex;align-items:center;justify-content:center} | |
| 300 | +.cstrip-thumb.noimg svg{width:34px;height:34px;opacity:.35} | |
| 301 | +.cstrip-play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%); | |
| 302 | + color:#fff;font-size:20px;text-shadow:0 1px 4px rgba(0,0,0,.6)} | |
| 303 | +.cstrip-dur{position:absolute;right:5px;bottom:5px;background:rgba(0,0,0,.78);color:#fff; | |
| 304 | + font-family:var(--font-mono);font-size:9px;padding:1px 5px;border-radius:5px} | |
| 305 | +.cstrip-cap{font-size:11px;line-height:1.25;color:var(--ink-2);display:-webkit-box; | |
| 306 | + -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden} | |
| 307 | +.cstrip-meta{font-family:var(--font-mono);font-size:9px;color:var(--ink-3);line-height:1.2} | |
| 273 | 308 | .acc .plat{width:44px;height:44px;border-radius:9px;flex:none} |
| 274 | 309 | .acc .plat svg{width:20px;height:20px} |
| 275 | 310 | .acc-mid{min-width:0;flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden} |
@@ -712,6 +747,30 @@ async function reload(more){ | ||
| 712 | 747 | } |
| 713 | 748 | |
| 714 | 749 | /* ---------- page créateur ---------- */ |
| 750 | +/* --- bande de contenu récent par compte (enrichissement Apify) --- */ | |
| 751 | +const _relTime=ts=>{if(!ts)return"";if(typeof ts==="string"&&!/^\d+$/.test(ts))return esc(ts.slice(0,10)); | |
| 752 | + const d=Math.floor((Date.now()/1000-Number(ts))/86400); | |
| 753 | + return d<=0?"aujourd'hui":d===1?"hier":d<30?d+" j":d<365?Math.floor(d/30)+" mois":Math.floor(d/365)+" ans";}; | |
| 754 | +function contentStrip(a){ | |
| 755 | + const m=a.metrics||{}; | |
| 756 | + const items=m.recent_posts||m.recent_videos||m.recent_tweets||[]; | |
| 757 | + if(!items.length)return""; | |
| 758 | + const cards=items.slice(0,8).map(it=>{ | |
| 759 | + const img=it.display_url||it.thumbnail_url||""; | |
| 760 | + const title=esc((it.caption||it.title||it.text||"").slice(0,90)); | |
| 761 | + const stats=[ | |
| 762 | + it.views!=null?fmt.format(it.views)+" vues":null, | |
| 763 | + it.likes!=null?fmt.format(it.likes)+" ❤":null, | |
| 764 | + it.comments!=null?fmt.format(it.comments)+" 💬":null, | |
| 765 | + it.retweets!=null?fmt.format(it.retweets)+" ↻":null, | |
| 766 | + ].filter(Boolean).join(" · "); | |
| 767 | + const when=_relTime(it.timestamp||it.published_at||it.published||it.created_at); | |
| 768 | + return `<a class="cstrip-item" href="${esc(it.url||a.url)}" target="_blank" rel="noopener" onclick="event.stopPropagation()"> | |
| 769 | + ${img?`<span class="cstrip-thumb" style="background-image:url('${esc(img)}')">${it.type==="video"||it.type==="reel"||it.duration?'<span class="cstrip-play">▶</span>':""}${it.duration?`<span class="cstrip-dur">${esc(it.duration)}</span>`:""}</span>`:`<span class="cstrip-thumb noimg">${icon(a.platform)}</span>`} | |
| 770 | + ${title?`<span class="cstrip-cap">${title}</span>`:""} | |
| 771 | + <span class="cstrip-meta">${stats}${when?` · ${when}`:""}</span></a>`}).join(""); | |
| 772 | + return `<div class="cstrip"><div class="cstrip-h">Contenu récent</div><div class="cstrip-scroll">${cards}</div></div>`; | |
| 773 | +} | |
| 715 | 774 | async function renderCreator(id){ |
| 716 | 775 | app.innerHTML=header()+`<div class="container"><div class="spin"></div></div>`+footer()+tabbar("");bindNav(); |
| 717 | 776 | let c;try{c=await api("/api/creators/"+encodeURIComponent(id))} |
@@ -721,18 +780,43 @@ async function renderCreator(id){ | ||
| 721 | 780 | const verified=(c.platforms||[]).some(a=>a.verified); |
| 722 | 781 | const niches=(c.niches||[]).map(n=>`<span class="mchip">${NICHE_LBL[n]||n}</span>`).join(""); |
| 723 | 782 | const M_LBL={following:"abonnements",posts:"publications",likes:"j'aime", |
| 724 | − views:"vues",videos:"vidéos",episodes:"épisodes"}; | |
| 783 | + views:"vues",videos:"vidéos",episodes:"épisodes",images:"photos", | |
| 784 | + friends:"amis",listed:"listes"}; | |
| 725 | 785 | const accs=(c.platforms||[]).map(a=>{const p=PLAT[a.platform]||PLAT.autre; |
| 726 | 786 | const conf=(a.confidence||0)>=0.75?["hi","confiance élevée"]:["mid","à confirmer"]; |
| 727 | − const mx=Object.entries(a.metrics||{}).filter(([k,v])=>M_LBL[k]&&v!=null) | |
| 787 | + const m=a.metrics||{}; | |
| 788 | + const mx=Object.entries(m).filter(([k,v])=>M_LBL[k]&&v!=null) | |
| 728 | 789 | .map(([k,v])=>`${fmt.format(v)} ${M_LBL[k]}`).join(" · "); |
| 729 | − return `<a class="acc" href="${esc(a.url)}" target="_blank" rel="noopener"> | |
| 730 | − <span class="plat" style="background:${p.color}">${icon(a.platform)}</span> | |
| 731 | − <span class="acc-mid"><span class="acc-name">${p.label}${a.verified?checkSvg:""}</span> | |
| 732 | − <span class="acc-handle">@${esc(a.handle)}</span> | |
| 733 | − <span class="acc-handle" style="overflow:visible"><span class="conf ${conf[0]}" title="Score de rattachement ${Math.round((a.confidence||0)*100)} %">${conf[1]}</span>${mx?` <span style="font-size:11px">${mx}</span>`:""}</span></span> | |
| 734 | − <span class="acc-right">${a.followers?`<b>${fmt.format(a.followers)}</b><span>abonnés</span>`:`<span style="font-size:11px">voir le profil ↗</span>`}</span></a>`}).join(""); | |
| 735 | − const checked=(c.platforms||[]).map(a=>a.last_checked).filter(Boolean).sort().pop(); | |
| 790 | + // rangée de statistiques riches (enrichissement Apify multi-plateforme) | |
| 791 | + const stat=(v,l)=>v==null?"":`<span class="astat"><b>${typeof v==="number"?fmt.format(v):esc(v)}</b><span>${l}</span></span>`; | |
| 792 | + const stats=[ | |
| 793 | + stat(m.engagement_rate_pct!=null?m.engagement_rate_pct+" %":null,"engagement"), | |
| 794 | + stat(m.avg_likes,"j'aime/moy"), | |
| 795 | + stat(m.avg_views!=null?m.avg_views:m.avg_video_views,"vues/moy"), | |
| 796 | + stat(m.avg_retweets,"RT/moy"), | |
| 797 | + stat(m.posts_per_week!=null?m.posts_per_week:m.tweets_per_week,"/semaine"), | |
| 798 | + ].filter(Boolean).join(""); | |
| 799 | + const badges=[ | |
| 800 | + m.is_partner?'<span class="abadge">Partenaire</span>':"", | |
| 801 | + m.is_affiliate&&!m.is_partner?'<span class="abadge">Affilié</span>':"", | |
| 802 | + m.is_live_now?'<span class="abadge live">● En direct</span>':"", | |
| 803 | + m.is_seller?'<span class="abadge">Boutique</span>':"", | |
| 804 | + m.is_free===true?'<span class="abadge">Gratuit</span>':"", | |
| 805 | + m.has_story?'<span class="abadge">Story active</span>':"", | |
| 806 | + (m.recent_games||[]).length?`<span class="abadge">${esc((m.recent_games||[])[0])}</span>`:"", | |
| 807 | + (m.top_hashtags||[]).slice(0,2).map(h=>`<span class="abadge">#${esc(h)}</span>`).join(""), | |
| 808 | + ].filter(Boolean).join(""); | |
| 809 | + return `<div class="acc-card"> | |
| 810 | + <a class="acc" href="${esc(a.url)}" target="_blank" rel="noopener"> | |
| 811 | + <span class="plat" style="background:${p.color}">${icon(a.platform)}</span> | |
| 812 | + <span class="acc-mid"><span class="acc-name">${p.label}${a.verified?checkSvg:""}</span> | |
| 813 | + <span class="acc-handle">@${esc(a.handle)}</span> | |
| 814 | + <span class="acc-handle" style="overflow:visible"><span class="conf ${conf[0]}" title="Score de rattachement ${Math.round((a.confidence||0)*100)} %">${conf[1]}</span>${mx?` <span style="font-size:11px">${mx}</span>`:""}</span></span> | |
| 815 | + <span class="acc-right">${a.followers?`<b>${fmt.format(a.followers)}</b><span>abonnés</span>`:`<span style="font-size:11px">voir le profil ↗</span>`}</span></a> | |
| 816 | + ${stats?`<div class="astat-row">${stats}</div>`:""} | |
| 817 | + ${badges?`<div class="abadge-row">${badges}</div>`:""} | |
| 818 | + ${contentStrip(a)}</div>`}).join(""); | |
| 819 | + const checked=(c.platforms||[]).map(a=>(a.metrics||{}).instagram_apify_at||a.last_checked).filter(Boolean).sort().pop()||(c.platforms||[]).map(a=>a.last_checked).filter(Boolean).sort().pop(); | |
| 736 | 820 | app.innerHTML=header()+` |
| 737 | 821 | <div class="container cpage"> |
| 738 | 822 | <a class="backlink" href="/" data-nav>← Tous les créateurs</a> |
| 739 | 823 | |