%s
%s%s
- %s
# -*- coding: utf-8 -*- """Génère les blocs HTML à coller dans cmonsite. Une seule source de données (DATA) -> toutes les pages.""" import json, os, pathlib OUT = pathlib.Path("/mnt/user-data/outputs") OUT.mkdir(parents=True, exist_ok=True) EMAIL = "meltzolivier88150@gmail.com" BASE = "https://meltzolivier88150.cmonsite.fr" U_ACCUEIL = BASE + "/" U_COMPARATEUR = BASE + "/comparateur-p404468.html" U_PLAT = BASE + "/plateformes-p404469.html" U_INDE = BASE + "/independants-p404470.html" U_GRAT = BASE + "/gratuite-p404471.html" U_CHOI = BASE + "/comment-choisir-p404472.html" U_METH = BASE + "/methodologie-p404473.html" # page « Build » créée par erreur (p404474), à renommer en Mentions légales U_MENTIONS = BASE + "/mentions-legales-p404474.html" # ---------------------------------------------------------------- DONNÉES # cout15 = ce que coûte un échange de 15 minutes, ou None si le montant # ne peut pas être connu avant l'appel. base = comment il est calculé. DATA = [ # ---------------- PLATEFORMES ---------------- dict(nom="Spiriteo", type="plateforme", public=True, modes=["téléphone","tchat","e-mail"], affiche="à partir de 1,65 €/min", cout15=24.75, base="1,65 €/min × 15 min", desc="Plateforme généraliste annonçant plus de 400 experts. Compte prépayé rechargeable.", lignes=[("Téléphone","à partir de 1,65 €/min, selon le voyant choisi"), ("Tchat","facturé à la seconde sur le solde prépayé"), ("Voyance par mail","900 crédits, soit 29,50 € par e-mail"), ("Offres","minutes offertes et bonus de recharge, variables selon la période")], src="spiriteo.com, page tarifs", url="https://www.spiriteo.com", date="20/07/2026"), dict(nom="Kanditel", type="plateforme", public=True, modes=["téléphone","tchat","audiotel"], affiche="1,99 à 2,99 €/min", cout15=29.85, base="1,99 €/min × 15 min", desc="En activité depuis 2015. Chaque voyant affiche son tarif sur sa fiche, service audiotel en parallèle.", lignes=[("Téléphone","1,99 à 2,99 €/min selon le voyant"), ("Tchat","à partir de 1,50 €/min"), ("Audiotel sans CB","0,60 €/min + prix de l'appel"), ("Crédit d'entrée","à partir de 20 € · 10 € offerts à l'inscription")], src="kanditel.com", url="https://www.kanditel.com", date="20/07/2026"), dict(nom="E-space voyance", type="plateforme", public=True, modes=["téléphone","tchat","SMS","e-mail"], affiche="1,10 à 2,50 €/min", cout15=16.50, base="1,10 €/min × 15 min", desc="Plateforme française active depuis 2014. Le tarif de chaque voyant est affiché sans créer de compte.", lignes=[("Téléphone","1,10 à 2,50 €/min selon le voyant"), ("Entrée de gamme","consultations annoncées à partir de 10 €"), ("Mail","réponse annoncée sous 6 h maximum")], src="e-spacevoyance.fr", url="https://www.e-spacevoyance.fr", date="20/07/2026"), dict(nom="Viversum", type="plateforme", public=True, modes=["téléphone","tchat"], affiche="1,90 €/min", cout15=28.50, base="1,90 €/min × 15 min", desc="Consultations par téléphone et tchat. Le tarif applicable après l'offre de bienvenue est annoncé en page d'accueil.", lignes=[("Téléphone","1,90 €/min après l'offre de bienvenue"), ("Offre de bienvenue","10 € de crédit, soit environ 5 minutes"), ("Fonctionnement","la consultation se coupe quand le crédit est épuisé"), ("Éditeur","Ingenio, également éditeur de Kang")], src="viversum.fr", url="https://www.viversum.fr", date="20/07/2026"), dict(nom="Paris Médium", type="plateforme", public=True, modes=["téléphone","audiotel"], affiche="15 € les 10 min, puis 3,90 à 4,90 €/min", cout15=34.50, base="15 € les 10 min + 5 min à 3,90 €/min", desc="Formule d'entrée à durée limitée, puis facturation à la minute nettement plus élevée.", lignes=[("Voyance privée","15 € les 10 min"), ("Au-delà de 10 min","3,90 à 4,90 €/min selon le voyant"), ("Audiotel","numéro sans carte bancaire")], src="parismedium.fr", url="https://www.parismedium.fr", date="20/07/2026"), dict(nom="Malingo", type="plateforme", public=True, modes=["téléphone","audiotel"], affiche="32 € les 15 min", cout15=32.00, base="forfait bloqué de 15 min", desc="Forfait prépayé bloqué : la durée est achetée à l'avance et ne peut pas être dépassée.", lignes=[("Forfaits","22 € les 10 min · 32 € les 15 min · 40 € les 20 min · 56 € les 30 min"), ("Formats longs","100 € l'heure · 190 € les 2 h · 269 € les 3 h"), ("Audiotel sans CB","0,40 €/min, tarif fixe annoncé"), ("Fonctionnement","forfait bloqué, aucun dépassement possible")], src="malingo.fr, page tarifs", url="https://www.malingo.fr", date="20/07/2026"), dict(nom="Esteban Frederic", type="plateforme", public=True, modes=["téléphone","tchat","e-mail","SMS","audiotel"], affiche="29,90 € les 15 min", cout15=29.90, base="forfait téléphonique de 15 min", desc="Cabinet médiatisé doublé d'une plateforme de voyants, avec forfaits téléphoniques bloqués.", lignes=[("Forfaits téléphone","29,90 € les 15 min · 39 € les 20 min · 58 € les 30 min · 77 € les 40 min"), ("Avec Esteban Frederic","150 € (30 min maximum) · 49,90 € la question par mail"), ("Audiotel","0,60 €/min · SMS 0,99 €/SMS + prix d'un SMS"), ("Offre","5 minutes offertes sur la première consultation")], src="esteban-frederic.fr", url="https://www.esteban-frederic.fr", date="21/07/2026"), dict(nom="Voyantissime", type="plateforme", public=True, modes=["téléphone","audiotel","e-mail"], affiche="à partir de 15 € les 10 min, puis minute supplémentaire", cout15=None, base="la minute supplémentaire dépend du voyant : le total de 15 min n'est pas annonçable", desc="Cabinet de voyance par téléphone actif depuis 2005, en privé par CB ou en audiotel sans CB.", lignes=[("Privé (CB)","à partir de 15 € les 10 premières minutes, puis minute supplémentaire selon le voyant"), ("Audiotel sans CB","numéro surtaxé, prélevé sur la facture téléphonique"), ("Mail","demande de voyance par formulaire")], src="voyantissime.com", url="https://www.voyantissime.com", date="21/07/2026"), dict(nom="Jimini", type="plateforme", public=False, modes=["téléphone","tchat","e-mail"], affiche="tarif propre à chaque voyant", cout15=None, base="aucune grille à l'échelle du site : le prix figure sur la fiche de chaque voyant", desc="Active depuis 2015. Aucune grille à l'échelle du site.", lignes=[("Téléphone, tchat, mail","tarif propre à chaque voyant, consultable sur son profil"), ("Offre de bienvenue","15 minutes réparties sur 3 conseillers, sans carte bancaire")], src="jimini.fr", url="https://www.jimini.fr", date="20/07/2026"), dict(nom="Kang", type="plateforme", public=False, modes=["téléphone","tchat"], affiche="tarif propre à chaque intervenant", cout15=None, base="inscription requise pour consulter les prix", desc="Voyance, coaching et consultations juridiques par téléphone et tchat.", lignes=[("Téléphone et tchat","tarif propre à chaque intervenant"), ("Accès","inscription requise pour consulter les prix"), ("Périmètre","voyance, coaching, avocats sur la même plateforme")], src="kang.fr", url="https://www.kang.fr", date="20/07/2026"), dict(nom="Avigora", type="plateforme", public=False, modes=["téléphone","tchat"], affiche="tarif fixé par chaque conseiller", cout15=None, base="annoncé avant la mise en relation, mais pas publié à l'échelle du site", desc="En activité depuis 2006. Le tarif est annoncé avant la mise en relation.", lignes=[("Téléphone et tchat","tarif propre à chaque conseiller, affiché avant la consultation"), ("Forfaits","formules 10 et 30 minutes, puis ajustement à la durée"), ("Offre de bienvenue","50 € en 5 chèques de 10 €, un par conseiller")], src="voyance.avigora.fr", url="https://voyance.avigora.fr", date="20/07/2026"), dict(nom="Wengo", type="plateforme", public=False, modes=["téléphone","tchat","e-mail","visio"], affiche="tarif propre à chaque expert", cout15=None, base="aucune grille à l'échelle du site", desc="Grande plateforme généraliste éditée par MyBestPro, annonçant près de 1 500 experts.", lignes=[("Modes","téléphone, tchat, mail, visio"), ("Tarif","propre à chaque expert, indiqué sur sa fiche"), ("Périmètre","voyance, psychologie, bien-être et avocats")], src="wengo.fr", url="https://www.wengo.fr", date="20/07/2026"), dict(nom="IdealVoyance", type="plateforme", public=False, modes=["téléphone","tchat","visio","écrit"], affiche="packs de minutes, prix en espace client", cout15=None, base="le détail des packs n'apparaît qu'après connexion", desc="Plateforme européenne présente depuis plus de quinze ans, en plusieurs langues.", lignes=[("Modes","téléphone, tchat, vidéo, écrit"), ("Tarif","packs de minutes, prix visibles en espace client"), ("Offre","cashback annoncé sur le premier achat")], src="idealvoyance.com", url="https://www.idealvoyance.com", date="20/07/2026"), dict(nom="Wooskill", type="plateforme", public=False, modes=["visio"], affiche="tarif propre à chaque praticien · moyenne annoncée 25 €", cout15=None, base="séance réservée à l'unité, prix fixé par chaque praticien", desc="Plateforme généraliste de séances en visio, plus de 200 praticiens en voyance.", lignes=[("Tarif","propre à chaque praticien · coût moyen annoncé 25 €"), ("Fonctionnement","réservation de séance en visio, sans abonnement"), ("Garanties annoncées","annulation gratuite jusqu'à 24 h avant · satisfait ou remboursé")], src="wooskill.com", url="https://www.wooskill.com", date="21/07/2026"), # ---------------- INDÉPENDANTS ---------------- dict(nom="Olivier Meltz", type="independant", public=True, zone="Thaon-les-Vosges (88)", modes=["cabinet","téléphone","e-mail","SMS"], editeur=True, affiche="15 € la consultation par domaine", cout15=15.00, base="voyance par domaine, 15 €", desc="Médium à Thaon-les-Vosges, à dix minutes d'Épinal. Cabinet sur rendez-vous et consultations à distance.", lignes=[("Réponse à une question","5 € (SMS ou e-mail, sous 24 h)"), ("Voyance par domaine","15 € (amour, travail, finances)"), ("Analyse complète","30 € (écrit, à distance)")], src="voyancedelatrinite.fr", url="https://www.voyancedelatrinite.fr", date="20/07/2026"), dict(nom="Wilfried Girard", type="independant", public=True, zone="Montchanin (71)", modes=["cabinet","téléphone","e-mail","tchat"], affiche="18 € la question", cout15=18.00, base="une question, 18 €", desc="Voyant indépendant depuis 2012, cabinet en Saône-et-Loire et consultations à distance. SIRET publié.", lignes=[("Une question","18 € (téléphone, mail ou cabinet) · 20 € par tchat"), ("Un domaine","40 € (~40 min) · 30 € par mail · 45 € par tchat"), ("Consultation générale","60 € (~60 min) · étude complète par mail 55 €")], src="wilfried-medium.fr", url="https://www.wilfried-medium.fr", date="20/07/2026"), dict(nom="Brigitte Jarguel", type="independant", public=True, zone="Caluire-et-Cuire (69)", modes=["cabinet","téléphone","WhatsApp"], affiche="20 € les 15 min", cout15=20.00, base="forfait de 15 min", desc="Voyante, tarologue et numérologue dans la métropole lyonnaise. Grille au temps, sans dépassement.", lignes=[("15 minutes","20 €"),("30 minutes","40 €"),("60 minutes","60 €")], src="brigitte-tarologue.fr", url="https://www.brigitte-tarologue.fr", date="20/07/2026"), dict(nom="France Terme", type="independant", public=True, zone="Villefranche-de-Rouergue (12)", modes=["cabinet","téléphone"], affiche="à partir de 25 €", cout15=25.00, base="entrée de gamme annoncée", desc="Cabinet privé en Aveyron. Voyance sans support et coaching intuitif. Pas de consultation par e-mail.", lignes=[("Entrée de gamme","à partir de 25 €"), ("Déplacement en région","70 € / 60 min, frais inclus, acompte de 30 %"), ("Paiement","PayPal ou CB")], src="france-terme-voyance.com", url="https://www.france-terme-voyance.com", date="20/07/2026"), dict(nom="Esmé Lou", type="independant", public=True, zone="À distance", modes=["téléphone"], affiche="25 € les 15 min", cout15=25.00, base="forfait de 15 min", desc="Consultations de voyance et coaching, grille au temps avec formules longues et suivi mensuel.", lignes=[("Consultations","25 € les 15 min · 60 € les 30 min · 90 € les 45 min"), ("Formules longues","150 € les 90 min · coaching 130 € l'heure"), ("Suivi","abonnement mensuel 350 €")], src="esmelouvoyance.fr", url="https://www.esmelouvoyance.fr", date="20/07/2026"), dict(nom="Clémy", type="independant", public=True, zone="À distance", modes=["téléphone"], affiche="28 € le forfait court", cout15=28.00, base="forfait court", desc="Voyante indépendante, plus de trente ans de pratique. Deux forfaits fixes, sans minute supplémentaire.", lignes=[("Forfait court","28 €"),("Forfait long","49 €"), ("Disponibilité","du lundi au samedi")], src="clemy-voyance.fr", url="https://www.clemy-voyance.fr", date="20/07/2026"), dict(nom="Cabinet Brigitte", type="independant", public=True, zone="Région lyonnaise (69)", modes=["téléphone","SMS","e-mail"], affiche="30 € le forfait par domaine", cout15=30.00, base="forfait un domaine", desc="Voyante en exercice depuis une trentaine d'années. Forfait sans durée imposée.", lignes=[("Forfait un domaine","30 € (également par SMS ou mail)"), ("Voyance générale","50 € (30 à 40 min environ)"), ("Réservation","en ligne, CB ou PayPal")], src="cabinetbrigitte.com", url="https://www.cabinetbrigitte.com", date="20/07/2026"), dict(nom="Sylvie Medium", type="independant", public=True, zone="Toulouse / Agen", modes=["cabinet","téléphone"], affiche="30 € les 20 min", cout15=30.00, base="forfait de 20 min, la formule la plus courte couvrant 15 min", desc="Vingt ans de pratique. Consultations téléphoniques payées d'avance puis rappel. Cabinet également.", lignes=[("Téléphone","18 € les 10 min · 30 € les 20 min · 38 € les 30 min · 55 € les 45 min"), ("Cabinet","68 € (environ 45 min, tous thèmes)"), ("Magnétisme avec photo","46 €"), ("À noter","les tarifs 10 et 30 min relevés étaient en offre anniversaire, donc temporaires")], src="sylviemedium.fr", url="https://www.sylviemedium.fr", date="20/07/2026"), dict(nom="Philippe De Verduron", type="independant", public=True, zone="Strasbourg (67)", modes=["téléphone","visio"], affiche="35 € la consultation ciblée", cout15=35.00, base="consultation ciblée sur un domaine", desc="Voyant médium en exercice depuis 1995, en profession libérale. Pas de facturation à la minute.", lignes=[("Consultation ciblée","35 € (un domaine précis)"), ("Consultation générale","65 € (complète)"), ("Paiement","CB ou PayPal")], src="philippe-tarologue.com", url="https://www.philippe-tarologue.com", date="20/07/2026"), dict(nom="Nathalie Suteau", type="independant", public=True, zone="À distance", modes=["téléphone"], affiche="35 € les 15 min", cout15=35.00, base="forfait de 15 min", desc="Voyante depuis vingt-cinq ans, tous les jours de 13 h à 23 h. Exclut les questions de santé et les mineurs.", lignes=[("15 minutes","35 € (une seule question)"), ("30 minutes","59 € (plusieurs thèmes)"), ("60 minutes","99 € (approfondissement)")], src="nathalie-voyance.com", url="https://www.nathalie-voyance.com", date="20/07/2026"), dict(nom="Christopher", type="independant", public=True, zone="Lyon (69)", modes=["téléphone"], affiche="37 € un domaine", cout15=37.00, base="forfait un domaine, sans limite de durée", desc="Voyant médium à Lyon depuis 1994. Forfaits sans limite de durée, ligne non surtaxée.", lignes=[("Un domaine","37 €"),("Deux domaines","59 €"), ("Tous les domaines","79 € (vies antérieures : 79 €)")], src="christophervoyance.com", url="https://www.christophervoyance.com", date="20/07/2026"), dict(nom="Laurent Clair", type="independant", public=True, zone="Saint-Dié-des-Vosges (88)", modes=["cabinet","téléphone","courrier"], affiche="40 € les 30 min", cout15=40.00, base="séance de 30 min, la plus courte proposée", desc="Voyant médium et parapsychologue. Séances sur rendez-vous, enregistrement audio remis sans supplément. SIRET publié.", lignes=[("Séance de 30 min","40 €"),("Séance d'une heure","70 € (tous thèmes)"), ("Paiement","espèces, chèque ou CB")], src="saintdie-voyance.fr", url="https://www.saintdie-voyance.fr", date="20/07/2026"), dict(nom="Julhia", type="independant", public=True, zone="Paris (75)", modes=["cabinet","téléphone","e-mail"], affiche="40 € les 20 min", cout15=40.00, base="forfait de 20 min, la formule la plus courte couvrant 15 min", desc="Voyante et tarologue à Paris depuis une trentaine d'années. Sur rendez-vous, paiement avant la consultation.", lignes=[("Voyance par mail","22 € (1 question) · 33 € (2 questions)"), ("Cabinet ou téléphone","40 € / 20 min · 60 € / 30 min · 80 € / 1 h"), ("Autres prestations","interprétation de rêves 45 € · numérologie 90 €")], src="julhia.com", url="https://www.julhia.com", date="20/07/2026"), dict(nom="Carla", type="independant", public=True, zone="À distance", modes=["téléphone"], affiche="49 € la formule unique", cout15=49.00, base="formule unique de 50 min", desc="Voyante indépendante, consultations privées par téléphone sur un forfait unique. Travaille seule.", lignes=[("Formule unique","49 € (40 min + 10 min offertes)"), ("Durée","50 min au total"),("Paiement","PayPal sécurisé")], src="carla-alex.com", url="https://www.carla-alex.com", date="20/07/2026"), dict(nom="Dominique Lehmann", type="independant", public=True, zone="Paris 16e / Boulogne (92)", modes=["cabinet","téléphone","e-mail"], affiche="65 € les 20 min", cout15=65.00, base="forfait de 20 min, la formule la plus courte couvrant 15 min", desc="Médium depuis plus de quarante ans, cabinet à Paris, consultations par téléphone ou e-mail.", lignes=[("Consultation courte","35 € les 10 min · 65 € les 20 min"), ("Consultation moyenne","95 € les 30 min"), ("Consultation complète","140 € l'heure, par téléphone ou en cabinet")], src="dominique-lehmann.fr", url="https://www.dominique-lehmann.fr", date="20/07/2026"), dict(nom="Barbara Tobolosky", type="independant", public=True, zone="À distance", modes=["téléphone"], affiche="65 € les 20 min", cout15=65.00, base="forfait de 20 min, la formule la plus courte couvrant 15 min", desc="Cartomancienne, consultations par téléphone à prix fixe. Annonce ne pas décompter les minutes dépassées.", lignes=[("Consultation courte","65 € les 20 min"), ("Consultation moyenne","110 € les 45 min"), ("Consultation longue","150 € pour 1 h 15")], src="voyanceserieuse.com et consultationvoyance.com (mêmes tarifs)", url="https://www.voyanceserieuse.com", date="20/07/2026"), dict(nom="Catherine Gé", type="independant", public=True, zone="À distance", modes=["téléphone"], affiche="70 € les 30 min", cout15=70.00, base="pure voyance, 30 min, la formule la plus courte", desc="Voyante tarologue, trois formules par téléphone. Règlement à la prise de rendez-vous.", lignes=[("Pure voyance","70 € (30 min)"),("Voyance et guidance","85 € (45 min)"), ("Voyance complète","100 € (1 h)")], src="catherinege-voyance.com", url="https://www.catherinege-voyance.com", date="20/07/2026"), dict(nom="Romain Magra", type="independant", public=True, zone="À distance", modes=["téléphone"], affiche="100 € les 25 min", cout15=100.00, base="forfait starter, 25 min, la formule la plus courte", desc="Médium, plus de vingt ans de pratique, du lundi au samedi de 11 h à 20 h. Forfaits à durée fixe.", lignes=[("Forfait starter","100 € les 25 min"),("Forfait silver","200 € les 70 min"), ("À noter","renvoie aussi vers une équipe partenaire facturée 15 € les 10 min, puis 7,50 € la minute supplémentaire")], src="canal-voyance.com", url="https://www.canal-voyance.com", date="20/07/2026"), ] PLAT = [d for d in DATA if d["type"] == "plateforme"] INDE = [d for d in DATA if d["type"] == "independant"] CHIFFRABLES = [d for d in DATA if d["cout15"] is not None] MIN_D = min(CHIFFRABLES, key=lambda d: d["cout15"]) MAX_D = max(CHIFFRABLES, key=lambda d: d["cout15"]) _s = sorted(d["cout15"] for d in CHIFFRABLES) MEDIANE = _s[len(_s)//2] if len(_s) % 2 else (_s[len(_s)//2 - 1] + _s[len(_s)//2]) / 2 NB_OPAQUES = len(DATA) - len(CHIFFRABLES) def eur(v): return ("%.2f" % v).replace(".", ",").rstrip("0").rstrip(",") + " €" # ---------------------------------------------------------------- CSS CSS = """
""" def nav(cur): items = [("Accueil", U_ACCUEIL, "accueil"), ("Comparateur", U_COMPARATEUR, "comparateur"), ("Plateformes", U_PLAT, "plateformes"), ("Indépendants", U_INDE, "independants"), ("Gratuite ?", U_GRAT, "gratuite"), ("Comment choisir", U_CHOI, "choisir"), ("Méthodologie", U_METH, "methodologie")] li = "".join('
' % (u, ' aria-current="page"' if k == cur else "", t) for t, u, k in items) return '
' % li FOOT = """
""" % (U_METH, U_MENTIONS, EMAIL, U_METH) HEADER = """
""" % EMAIL def page(cur, eyebrow, h1, lede, body): return "\n".join([HEADER, '
%s
%s
' % lede if lede else ""), '', body, '', FOOT, '']) def next_links(items): return '
' % "".join( '%s%s' % (u, k, t) for k, t, u in items) def fiche(d): if d.get("editeur"): badge = 'Éditeur de l\'annuaire' elif d["public"]: badge = 'Tarif public' else: badge = 'Tarif sur profil' dl = "".join("%s%s" % (k, v) for k, v in d["lignes"]) src = ('
' % (d["url"], d["src"], d["date"], U_COMPARATEUR, slug(d["nom"]))) zone = '
' % d["zone"] if d.get("zone") else "" return ('
%s
' % (slug(d["nom"]), badge, d["nom"], zone, d["desc"], dl, src)) def slug(n): import unicodedata, re n = unicodedata.normalize("NFKD", n).encode("ascii", "ignore").decode() return "f-" + re.sub(r"[^a-z0-9]+", "-", n.lower()).strip("-") def ldjson(obj): return '
' % json.dumps(obj, ensure_ascii=False) # ---------------------------------------------------------------- JS DATA JS_DATA = "const VC_DATA=" + json.dumps( [dict(nom=d["nom"], type=d["type"], public=d["public"], modes=d["modes"], affiche=d["affiche"], cout15=d["cout15"], base=d["base"], zone=d.get("zone", "En ligne"), editeur=d.get("editeur", False), anchor=slug(d["nom"]), fiche=(U_PLAT if d["type"] == "plateforme" else U_INDE) + "#" + slug(d["nom"]), src=d["src"], url=d["url"], date=d["date"]) for d in DATA], ensure_ascii=False) + ";" # ================================================================ ACCUEIL tableau_modeles = """
| Type d'offre | Affichage du prix | Échange de 15 min | Montant connu avant ? |
|---|---|---|---|
| Plateforme à la minute, entrée de gamme | 1,10 €/min | 16,50 € | Non |
| Plateforme à la minute, haut de grille | 2,99 €/min | 44,85 € | Non |
| Plateforme au forfait bloqué | 32 € les 15 min | 32 € | Oui |
| Indépendant, question écrite | 5 à 22 € | sans objet | Oui |
| Indépendant, séance courte | 15 à 100 € | 15 à 100 € | Oui |
""" accueil_body = """
Trois chiffres, tirés des {n} offres relevées et recalculés à chaque mise à jour. Ils portent tous sur la même chose : un échange d'un quart d'heure.
Le prix à la minute d'un côté, le montant annoncé pour une prestation de l'autre. Même besoin, deux logiques qui n'aboutissent pas au même relevé bancaire.
{tab}Les montants à la minute sont multipliés par quinze. Les montants au forfait sont ceux de la formule la plus courte couvrant un quart d'heure.
""".format( n=len(DATA), nc=len(CHIFFRABLES), no=NB_OPAQUES, mn=eur(MIN_D["cout15"]), mnn=MIN_D["nom"], mx=eur(MAX_D["cout15"]), mxn=MAX_D["nom"], md=eur(MEDIANE), tab=tableau_modeles, uc=U_COMPARATEUR, next=next_links([("Tableau", "Comparer les %d offres" % len(DATA), U_COMPARATEUR), ("Dossier", "Ce que paie une voyance gratuite", U_GRAT), ("Transparence", "Comment ces prix sont relevés", U_METH)])) accueil = page("accueil", "Annuaire · France · 2026", "Combien coûte une voyance ? Le relevé, pas l'estimation.", "Cet annuaire compare ce qui est réellement facturé par %d prestataires : %d plateformes à la minute et %d praticiens indépendants. Chaque montant vient du site officiel du prestataire et porte sa date de relevé." % (len(DATA), len(PLAT), len(INDE)), accueil_body) + "\n" + ldjson({ "@context": "https://schema.org", "@type": "WebSite", "name": "Annuaire des tarifs de voyance en France", "inLanguage": "fr-FR", "url": U_ACCUEIL, "description": "Comparatif des tarifs de voyance en France : %d prestataires, prix relevés sur leurs sites officiels et datés." % len(DATA)}) # ================================================================ COMPARATEUR comp_js = """
""" % JS_DATA comp_body = """
Trié par ce que coûte un échange de quinze minutes, du moins cher au plus cher. Les offres dont le montant ne peut pas être connu avant l'appel sont regroupées en bas : ce n'est pas une sanction, c'est leur mode de facturation.
| Prestataire | Type et modes | Prix affiché | Échange de 15 min ↕ | Source |
|---|
L'éditeur de cet annuaire est lui-même praticien et figure dans ce tableau, signalé par une pastille. Le tri est calculé automatiquement à partir des tarifs relevés ; aucune position n'est attribuée à la main. La méthodologie détaille le procédé.
""".format( n=len(DATA), um=U_METH, modes="".join('%s' % (m, m) for m in sorted({m for d in DATA for m in d["modes"]}, key=str.lower)), next=next_links([("Catégorie", "Les plateformes à la minute", U_PLAT), ("Catégorie", "Les praticiens indépendants", U_INDE), ("Guide", "Choisir sa consultation", U_CHOI)])) comparateur = page("comparateur", "Tableau comparatif", "Les {n} tarifs, dans un seul tableau.".format(n=len(DATA)), "Plateformes et indépendants mélangés, triés par ce que coûte réellement un échange de quinze minutes. Filtrez par budget, par mode de consultation, ou n'affichez que les prestataires dont le tarif est consultable sans créer de compte.", comp_body) + "\n" + comp_js + "\n" + ldjson({ "@context": "https://schema.org", "@type": "ItemList", "name": "Tarifs de voyance relevés en France", "numberOfItems": len(DATA), "itemListOrder": "https://schema.org/ItemListOrderAscending", "itemListElement": [ {"@type": "ListItem", "position": i + 1, "item": {"@type": "Service", "name": d["nom"], "serviceType": "Consultation de voyance", "provider": {"@type": "Organization", "name": d["nom"], "url": d["url"]}, "offers": {"@type": "Offer", "priceCurrency": "EUR", "price": d["cout15"], "description": "Échange de 15 minutes — %s" % d["base"], "priceValidUntil": "2026-12-31"}}} for i, d in enumerate(sorted(CHIFFRABLES, key=lambda x: x["cout15"]))]}) # ================================================================ PLATEFORMES nb_pub = len([d for d in PLAT if d["public"]]) plat_body = """
{p} publient un tarif consultable sans créer de compte ; {o} renvoient à la fiche de chaque voyant ou à l'espace client. Les tarifs publics d'abord, puis les autres. Chaque fiche porte sa date de relevé.
Une plateforme manque, ou son tarif a changé ? Écrivez-nous avec le lien de la page publique qui l'affiche.
""".format( n=len(PLAT), p=nb_pub, o=len(PLAT) - nb_pub, mail=EMAIL, fpub="".join(fiche(d) for d in PLAT if d["public"]), fopq="".join(fiche(d) for d in PLAT if not d["public"]), next=next_links([("Tableau", "Comparer les %d offres" % len(DATA), U_COMPARATEUR), ("Catégorie", "Les praticiens indépendants", U_INDE), ("Transparence", "Comment ces prix sont relevés", U_METH)])) plateformes = page("plateformes", "Catégorie · Facturation à la minute", "Plateformes à la minute.", "Un standard met en relation avec le consultant disponible. Le prix est affiché par minute, parfois par palier selon l'ancienneté du médium. Le montant final dépend entièrement de la durée de l'appel.", plat_body) + "\n" + ldjson({ "@context": "https://schema.org", "@type": "ItemList", "name": "Plateformes de voyance et leurs tarifs", "numberOfItems": len(PLAT), "itemListElement": [{"@type": "ListItem", "position": i + 1, "name": d["nom"], "url": d["url"]} for i, d in enumerate(PLAT)]}) # ================================================================ INDÉPENDANTS inde_body = """
Classés par prix croissant pour un échange d'un quart d'heure, du moins cher au plus cher. Chaque montant provient du site officiel du professionnel et porte sa date de relevé. Aucun d'entre eux ne paie pour figurer ici. Les praticiens qui ne communiquent leur tarif que sur demande ne sont pas repris : sans montant public, la comparaison n'a pas de sens.
Praticien indépendant affichant publiquement ses tarifs ? Demandez votre inscription. Elle est gratuite.
""".format( n=len(INDE), mail=EMAIL, f="".join(fiche(d) for d in sorted(INDE, key=lambda d: (d["cout15"] is None, d["cout15"] or 0))), next=next_links([("Tableau", "Comparer les %d offres" % len(DATA), U_COMPARATEUR), ("Guide", "Choisir sa consultation", U_CHOI), ("Catégorie", "Les plateformes à la minute", U_PLAT)])) independants = page("independants", "Catégorie · Prix annoncé à l'avance", "Praticiens indépendants.", "Un professionnel identifié, joignable directement, qui annonce un montant pour une prestation et une durée données. C'est le mode de facturation le plus simple à comparer d'un praticien à l'autre.", inde_body) + "\n" + ldjson({ "@context": "https://schema.org", "@type": "ItemList", "name": "Voyants indépendants et leurs tarifs", "numberOfItems": len(INDE), "itemListElement": [{"@type": "ListItem", "position": i + 1, "name": d["nom"], "url": d["url"]} for i, d in enumerate(sorted(INDE, key=lambda d: d["cout15"]))]}) # ================================================================ GRATUITE grat_body = """
| Formule | Ce qui est offert | Ce qui est facturé ensuite |
|---|---|---|
| Minutes offertes | 3 à 10 min au premier appel | Le tarif à la minute dès la minute suivante |
| Tirage automatique | Un tirage généré par un script | L'interprétation détaillée, payante |
| Réponse par e-mail | Une réponse courte | Des relances commerciales, puis une offre payante |
| Numéro d'appel gratuit | La mise en relation | Un numéro surtaxé ou un paiement par carte |
""" % next_links( [("Guide", "Choisir sa consultation", U_CHOI), ("Tableau", "Comparer les %d offres" % len(DATA), U_COMPARATEUR), ("Transparence", "Comment ces prix sont relevés", U_METH)]) gratuite = page("gratuite", "Dossier", "La voyance dite gratuite.", "Aucune offre gratuite ne l'est jusqu'au bout : elle est financée autrement. Comprendre par quoi permet de savoir à quel moment le compteur démarre.", grat_body) # ================================================================ COMMENT CHOISIR QA = [ ("Quel est mon besoin réel ?", "Une question fermée sur une date ou une décision se traite en quelques minutes et par écrit. Un bilan de situation demande une séance complète. Payer un format long pour une question courte est la dépense la plus fréquente et la plus évitable.", "Une question fermée se traite en quelques minutes et par écrit ; un bilan de situation demande une séance complète. Payer un format long pour une question courte est la dépense la plus fréquente et la plus évitable."), ("Quel budget je fixe avant de commencer ?", "Déterminez un montant maximum avant le premier contact. Avec un prix annoncé à l'avance, le respect du budget est automatique. Avec une facturation à la minute, il faut une alarme et la discipline de raccrocher.", "Déterminez un montant maximum avant le premier contact. Avec un prix annoncé à l'avance, le budget se tient tout seul ; avec une facturation à la minute, il faut une alarme et la discipline de raccrocher."), ("Puis-je identifier la personne ?", "Un nom, une commune, un SIRET consultable, un moyen de contact direct. Ces éléments ne garantissent pas la qualité d'une consultation, mais ils garantissent un interlocuteur en cas de problème — ce qu'un pseudonyme sur un standard ne permet pas.", "Un nom, une commune, un SIRET consultable, un moyen de contact direct. Cela ne garantit pas la qualité de la consultation, mais cela garantit un interlocuteur en cas de problème."), ("Le discours reste-t-il à sa place ?", "Un professionnel sérieux ne promet pas de résultat, ne fixe pas de dates certaines, n'entretient pas la peur, et renvoie vers un médecin, un avocat ou un conseiller quand le sujet leur appartient. Toute demande de paiement pour lever un sort doit mettre fin à l'échange.", "Un professionnel sérieux ne promet pas de résultat, ne fixe pas de dates certaines, n'entretient pas la peur et renvoie vers un médecin, un avocat ou un conseiller quand le sujet leur appartient. Toute demande de paiement pour lever un sort doit mettre fin à l'échange."), ] choisir_js = """
""" % JS_DATA choisir_body = ('
Elles écartent la plupart des mauvaises surprises, quel que soit le professionnel retenu.
' '%02d
%s
' '
Entrez le montant que vous êtes prêt à dépenser. Le calcul se fait sur les tarifs relevés dans cet annuaire.
' '' '
' % next_links([("Tableau", "Comparer les %d offres" % len(DATA), U_COMPARATEUR), ("Dossier", "Ce que paie une voyance gratuite", U_GRAT), ("Catégorie", "Les praticiens indépendants", U_INDE)])) choisir = page("choisir", "Guide", "Choisir sa consultation.", "Quatre questions à se poser avant le premier contact, et un calcul pour savoir ce que votre budget paie réellement.", choisir_body) + "\n" + choisir_js + "\n" + ldjson({ "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": q.replace(" ", " "), "acceptedAnswer": {"@type": "Answer", "text": short}} for q, _, short in QA]}) # ================================================================ MÉTHODOLOGIE meth_body = """
Le fait qu'un praticien édite un comparateur où il apparaît est un conflit d'intérêts. Il ne se règle pas en le taisant, mais en rendant le procédé vérifiable : c'est l'objet de cette page.
Toutes les offres sont ramenées à la même question : combien coûte un échange d'un quart d'heure ?
Le détail du calcul retenu est affiché sous chaque montant dans le tableau comparatif.
Il ne note pas la qualité des consultations : elle n'est pas mesurable objectivement et ne se déduit pas d'un prix. Il ne recense pas l'intégralité du marché. Il ne vérifie pas les avis clients publiés ailleurs. Il ne se prononce sur aucune capacité divinatoire — le sujet de ces pages est le prix et sa lisibilité, rien d'autre.
Écrivez à {mail}. Toute correction appuyée sur un tarif public vérifiable est appliquée, et la date de relevé mise à jour. Une inscription est gratuite ; la seule condition est que vos tarifs soient consultables sur votre site.
| Date | Fiches concernées | Modification |
|---|---|---|
| Juillet 2026 | {n} fiches | Premier relevé complet, sources datées et liens de vérification ajoutés. |
Ajoutez une ligne à ce tableau à chaque correction de tarif.
""".format( mail=EMAIL, n=len(DATA), next=next_links([("Tableau", "Comparer les %d offres" % len(DATA), U_COMPARATEUR), ("Catégorie", "Les plateformes à la minute", U_PLAT), ("Catégorie", "Les praticiens indépendants", U_INDE)])) methodologie = page("methodologie", "Transparence", "Méthodologie et limites.", "Un comparateur ne vaut que par la façon dont il collecte ses chiffres, et par ce qu'il dit de lui-même. Voici les deux.", meth_body) # ================================================================ MENTIONS ment_body = """
Ce site est hébergé par CmonSite. Coordonnées complètes de l'hébergeur : HEBERGEUR-RAISON-SOCIALE-ADRESSE-A-REMPLACER.
Ce site n'ouvre aucun compte et ne collecte aucune donnée saisie par les visiteurs. Une mesure d'audience est effectuée par l'hébergeur au moyen de l'outil Matomo, à des fins statistiques.
Conformément au règlement général sur la protection des données, vous pouvez demander l'accès, la rectification ou l'effacement des données vous concernant en écrivant à {mail}. Vous pouvez également introduire une réclamation auprès de la CNIL.
Les textes et la mise en forme de ce site sont la propriété de son éditeur. Les tarifs cités appartiennent aux prestataires concernés et sont reproduits à titre d'information, avec leur date de relevé et un lien vers la page publique dont ils proviennent.
Les tarifs évoluent sans préavis. Ils sont indiqués sous réserve d'erreur ou de modification depuis la date de relevé, et doivent être vérifiés auprès du professionnel avant toute consultation. Aucune consultation de voyance ne constitue un avis médical, juridique ou financier.
Pour signaler une erreur : {mail}. Voir aussi la méthodologie.
""".format(mail=EMAIL, um=U_METH) mentions = page("mentions", "Informations légales", "Mentions légales.", "", ment_body) # ---------------------------------------------------------------- ÉCRITURE FILES = { "1-accueil.html": accueil, "2-comparateur.html": comparateur, "3-plateformes.html": plateformes, "4-independants.html": independants, "5-voyance-gratuite.html": gratuite, "6-comment-choisir.html": choisir, "7-methodologie.html": methodologie, "8-mentions-legales.html": mentions, } for name, content in FILES.items(): (OUT / name).write_text(content, encoding="utf-8") print("Offres :", len(DATA), "| plateformes :", len(PLAT), "| indépendants :", len(INDE)) print("Chiffrables :", len(CHIFFRABLES), "| non chiffrables :", NB_OPAQUES) print("Min :", MIN_D["nom"], eur(MIN_D["cout15"]), "| médiane :", eur(MEDIANE), "| max :", MAX_D["nom"], eur(MAX_D["cout15"])) for n in FILES: print(n, os.path.getsize(OUT / n), "octets")