SPB Git forge

spb/resto-ka

Public

Resto·Ka — tous les restaurants du Québec, menus complets et prix réels (famille ·Ka)

52commits 1branches 0releases
11.6 MBsize
maindefault branch
19 days agolast push
Python 69.3% TypeScript 16.7% CSS 7.9% JavaScript 4.7% HTML 1.4%
24.2 KB · 430 lines json
Raw Blame History
1{2  "_comment": "Resto·Ka — Registre des sources (restaurants du Québec, menus & prix). Auteur : Simon-Pierre Boucher — contact@spboucher.ai. Vérifier ce registre AVANT d'ajouter une source ou un resto (CLAUDE.md §0.4).",3  "sources": [4    {5      "id": "ueat",6      "name": "UEAT (commande en ligne)",7      "url": "https://ueat.io",8      "platform": "ueat",9      "connector": "ueat",10      "tier": 1,11      "price_context": "takeout",12      "extraction": "API GraphQL interne (api.ueat.io/graphql), auth anonyme par GUID d'intégration — la même API que le widget officiel de commande",13      "acces_legal": "Source de première partie : plateforme de commande des restos eux-mêmes, prix réels non majorés (CLAUDE.md §9 Palier 1, §15). API anonyme publique, throttling poli 0,35 s, User-Agent identifiable RestoKaBot.",14      "cadence": "hebdomadaire",15      "status": "actif",16      "integrations": [17        {18          "key": "4268100d-6470-40b9-a755-e11342c91d6d",19          "label": "Poulet Rouge (chaîne)"20        },21        {22          "key": "01d1c391-59cf-45a3-b051-7b2f9a623858",23          "label": "Fairmont Le Château Frontenac (Québec)"24        },25        {26          "key": "b7282ce3-95cc-43ff-80b5-0cca8a7e4778",27          "label": "Allô mon Coco (chaîne, déjeuner-brunch)"28        },29        {30          "key": "b1c2c004-bcff-4eb0-b3b9-d3bc5c8799a3",31          "label": "Restaurant Impérial (Brossard, Pointe-Claire)"32        },33        {34          "key": "2f51961a-f378-4812-a31a-a0b45da3f87e",35          "label": "Pizza Mia (Laval)"36        },37        {38          "key": "1b432c57-98d6-4681-a560-d1b7bfafdd6f",39          "label": "Station W (Montréal, café)"40        },41        {42          "key": "ff376cab-30e2-4cce-9999-ed755583c7f5",43          "label": "Chocolats Favoris (chaîne, dessert)"44        },45        {46          "key": "c5548a05-1776-49ac-9c9f-2ac8c998eed4",47          "label": "Le Super Qualité (Montréal, indien)"48        },49        {50          "key": "d84801b5-66f5-44b3-b0dc-52c0365f571c",51          "label": "Ryu Sushi (Montréal)"52        },53        {54          "key": "87c690ed-be3c-4a5d-b58b-676235faa9c1",55          "label": "Panda Boba-T (chaîne, bubble tea)"56        },57        {58          "key": "970d8e90-55ca-4655-9631-a8f9af08f4b7",59          "label": "Chez Ashton (23 succ., poutine)"60        },61        {62          "key": "e473d88d-b405-41ee-9ee8-2aa628eee604",63          "label": "Thaïzone (26 succ. QC)"64        },65        {66          "key": "f89d74e1-c2ab-4ace-8bce-39069900f5b4",67          "label": "Normandin (44 succ., familial)"68        },69        {70          "key": "e15b2545-2f2a-4e5f-baa6-00ab849cfa16",71          "label": "Valentine (76 succ. QC, casse-croûte)"72        },73        {74          "key": "657f8ce3-d288-4245-aecf-7ca017364b8e",75          "label": "Tutti Frutti (9 succ. QC, déjeuner)"76        },77        {78          "key": "00f8d52b-7aaf-4bcf-8722-6d538aad5a9a",79          "label": "Pacini (20 succ. QC, italien)"80        },81        {82          "key": "d679a49f-0a25-4694-82f2-56073a8b8790",83          "label": "Scores (25 succ., rôtisserie)"84        },85        {86          "key": "1696ecd3-d4ea-4224-9f98-9299ebcb339c",87          "label": "Mandy's (9 succ. QC, salades)"88        },89        {90          "key": "dce3e009-8038-47bc-8d5e-f336458e573f",91          "label": "Sushi Shop (141 succ. QC)"92        },93        {94          "key": "a0dac11c-e43c-4ae2-a37c-22d8542872e0",95          "label": "Ben & Florentine (54 succ. QC, déjeuner)"96        },97        {98          "key": "f0ac233f-df24-47a8-9e3a-a64520738ff2",99          "label": "Boustan (65 succ. QC, libanais)"100        },101        {102          "key": "45c52d27-bf8c-4995-9c4e-a0a2754101fb",103          "label": "Pizzéria NO.900 (32 succ. QC)"104        },105        {106          "key": "e3ca524e-57bb-4d8e-ad2f-53a35731c802",107          "label": "Sushi Taxi (30 succ. QC)"108        },109        {110          "key": "031978fa-09a0-493b-86d9-65aca8b3bef0",111          "label": "Cochon Dingue (7 succ., Québec)"112        },113        {114          "key": "d6a20802-625c-4970-920b-1b82c6867e9d",115          "label": "Salvatoré (3 succ. QC, pizza)"116        },117        {118          "key": "a23e2d27-6871-4d2f-be29-610426c251a2",119          "label": "La Belle Province — Montréal (2 succ.)"120        },121        {122          "key": "48c08050-9f8a-4ab9-a8a2-d58c9602df56",123          "label": "Madisons (2 succ. QC)"124        },125        {126          "key": "fd9eb8cb-4536-4bb6-bb19-6fb3be67808f",127          "label": "Freddy Pizzeria (Sherbrooke)"128        },129        {130          "key": "e8015de3-09ac-4cd2-a18d-0820dbe356ed",131          "label": "(intégration retirée chez UEAT)",132          "status": "inactif"133        },134        {135          "key": "dfde098b-ee0f-46a3-b1ad-09ec2acb54b9",136          "label": "(intégration retirée chez UEAT)",137          "status": "inactif"138        },139        {140          "key": "e4c3af4f-c5ff-4fe7-a8e9-a8750ae532a8",141          "label": "Morena Epicerie Traiteur (découvert via morena-food.com)"142        },143        {144          "key": "66ee81af-c10a-49b6-9faa-3e3b485a548e",145          "label": "India Rosa (découvert via indiarosa.com)"146        },147        {148          "key": "b46660d2-389f-42d5-b161-d31b48ad80bf",149          "label": "Restaurant Au Vieux Duluth (découvert via auvieuxduluth.com)"150        },151        {152          "key": "d6843f2a-5809-4d43-be8e-392e65a4a91c",153          "label": "Aux Vivres (découvert via auxvivres.com)"154        },155        {156          "key": "c164671b-95fe-4f6f-8944-67eac68ad8c0",157          "label": "Casa Grecque (découvert via casagrecque.ca)"158        },159        {160          "key": "36be39f4-3bfb-4d76-ab9b-bbb1985883ea",161          "label": "Pizza Welldun (découvert via welldunpizza.ca)"162        },163        {164          "key": "e39d77ff-8183-4d75-9211-ed356dc857ea",165          "label": "Bottega (découvert via bottega.ca)"166        },167        {168          "key": "55a3f719-d59a-4487-a0e2-b7aad293b247",169          "label": "Sandhu (découvert via restaurantsandhu.ca)"170        },171        {172          "key": "627749b8-894b-4f13-a68b-c90b2ffd1702",173          "label": "Rockaberry (découvert via rockaberry.ca)"174        },175        {176          "key": "4442c3e2-66b3-41ac-8cbf-a00a2a420320",177          "label": "Maiko Sushi (découvert via maiko-sushi.com)"178        },179        {180          "key": "fc3bf368-dfcc-4a0b-8eb7-93aaeef67bcf",181          "label": "Juliette & Chocolat (découvert via julietteetchocolat.com)"182        },183        {184          "key": "52f4a11d-75c9-4710-8f9c-15997aabf7bd",185          "label": "Poivre Noir (découvert via poivrenoir.com)"186        },187        {188          "key": "1d596d77-a96f-46da-8192-785cd3766c58",189          "label": "Pizzeria 67 (découvert via pizzeria67.com)"190        },191        {192          "key": "b0cbbf13-6f88-46a3-ad14-0c3bc85069f7",193          "label": "Bistro-Bar le Brise-Bise (découvert via brisebise.ca)"194        },195        {196          "key": "77df4865-59bb-435e-818c-e743a4ca2751",197          "label": "Pizza Fina (découvert via pizzafina.ca)"198        },199        {200          "key": "94652e5f-d4cc-47ac-81a3-ad9b1e31b826",201          "label": "Sesame (découvert via sesamerestaurant.ca)"202        },203        {204          "key": "5f664929-18f2-4b2f-955d-b9f542312180",205          "label": "Venice (découvert via venicemtl.com)"206        },207        {208          "key": "d25f3505-1acc-4422-a5c0-b83940b3f576",209          "label": "Onigiri Shop (découvert via onigirishop.com)"210        },211        {212          "key": "ac77a7cf-e62b-40be-964b-497666c07c06",213          "label": "Escondite (découvert via escondite.ca)"214        },215        {216          "key": "e4de92c1-12d0-49db-bb59-7baf0202faf8",217          "label": "Nora Gray (découvert via noragray.com)"218        }219      ]220    },221    {222      "id": "osm",223      "name": "OpenStreetMap (découverte)",224      "url": "https://www.openstreetmap.org",225      "platform": "overpass",226      "connector": "osm",227      "tier": 4,228      "price_context": null,229      "extraction": "API Overpass (aire administrative Québec), nœuds + chemins : restaurant, fast_food, cafe, bar, pub, ice_cream, food_court, bakery, pastry — nom, adresse, GPS, cuisine, horaires, contact. Pas de menus (couche d'exhaustivité, les connecteurs de menus s'y greffent par déduplication).",230      "acces_legal": "Données © contributeurs OpenStreetMap, licence ODbL — attribution affichée (pages Sources et pied de page). API Overpass publique, requêtes espacées, miroirs en rotation.",231      "cadence": "mensuel",232      "status": "actif"233    },234    {235      "id": "site-resto",236      "name": "Sites web des restos (menus maison)",237      "url": "https://www.resto-ka.com/sources",238      "platform": "sites-web",239      "connector": "site-resto",240      "tier": 3,241      "price_context": "dine-in",242      "extraction": "Crawl des sites web publiés par les restos découverts via OSM : détection de plateforme (UEAT → GUID consigné dans ueat-discovered.json), sinon page menu HTML (requests, Firecrawl en secours pour le JS) ou PDF → structuration par Claude Haiku 4.5 (sorties structurées JSON) → validation stricte des prix (≥5 plats avec prix, ≥40 % des items, 0,50–500 $). Budget de 250 sites/passage, re-crawl mensuel.",243      "acces_legal": "Sites publics de première partie (le menu affiché par le resto lui-même — la voie la plus légitime, CLAUDE.md §15). UA identifiable RestoKaBot, 1 req/s, aucun contournement.",244      "cadence": "hebdomadaire (batch incrémental), re-crawl mensuel",245      "status": "actif"246    },247    {248      "id": "sthubert",249      "name": "St-Hubert (commande en ligne)",250      "url": "https://commande.st-hubert.com",251      "platform": "st-hubert",252      "connector": null,253      "tier": 6,254      "price_context": "takeout",255      "extraction": "À déterminer — Akamai anti-bot sur st-hubert.com ; commande.st-hubert.com rend une page vide même via Scrapfly ASP (flux JS multi-étapes, sélection de succursale requise). Prochain essai : rejouer les XHR internes après sélection d'une succursale (js_scenario Scrapfly).",256      "acces_legal": "Site de commande de la chaîne elle-même (prix réels). À industrialiser prudemment (CLAUDE.md §15).",257      "cadence": "hebdomadaire (visé)",258      "status": "à faire"259    },260    {261      "id": "mapaq",262      "name": "MAPAQ — Inspections alimentaires (condamnations)",263      "url": "https://www.donneesquebec.ca/recherche/dataset/condamnations-des-etablissements-alimentaires-et-condamnations-concernant-le-bien-etre-des-anim",264      "platform": "donnees-quebec",265      "connector": "inspections (module d'enrichissement, pas de fiches)",266      "tier": 5,267      "price_context": "aucun",268      "extraction": "CSV ouvert listecondamnation.csv (Données Québec) -> table liée `inspections` + croisement CONSERVATEUR avec les restaurants (nom normalisé + ville/code postal, ou code postal + civique + similarité de nom). Résumé conformité dans details.mapaq, endpoint GET /api/restaurants/{uid}/inspections.",269      "acces_legal": "Données ouvertes du gouvernement du Québec, licence CC-BY 4.0 — attribution MAPAQ/Données Québec affichée avec les inspections.",270      "cadence": "hebdomadaire (guard 6 jours dans ingest.enrich)",271      "status": "actif"272    },273    {274      "id": "yelp",275      "name": "Yelp Fusion (avis et notes)",276      "url": "https://www.yelp.com/developers",277      "platform": "yelp",278      "connector": "yelp",279      "tier": 5,280      "price_context": "aucun",281      "extraction": "API officielle Yelp Fusion (gratuit, 500 req/jour) : rating, review_count, price, categories, phone -> details.yelp. Croisement conservateur par téléphone (/businesses/search/phone, GPS <300 m si ambigu) puis nom+adresse+GPS (/businesses/matches). N'émet aucune fiche.",282      "acces_legal": "API officielle avec clé, Display Requirements Yelp : attribution affichée avec la note.",283      "cadence": "hebdomadaire, re-vérification 30 jours",284      "status": "clé requise (YELP_API_KEY absente de .env — connecteur livré, SkipSource)"285    },286    {287      "id": "yelp-scrape",288      "name": "Yelp (avis et notes, sans clé)",289      "url": "https://www.yelp.ca",290      "platform": "yelp",291      "connector": "yelp-scrape",292      "tier": 5,293      "price_context": "aucun",294      "extraction": "Une page de RECHERCHE yelp.ca par resto (find_desc=nom&find_loc=ville) via Scrapfly ASP : le cache Apollo embarqué (scripts data-apollo-state) expose alias, note, nb d'avis, fourchette de prix, catégories, ville et civique par commerce -> details.yelp (mêmes clés que Yelp Fusion). Croisement conservateur : nom similaire + même numéro civique + ville compatible ; ambigu = ignoré. Budget YELP_SCRAPE_BUDGET (80 pages/cycle), re-visite 30 j (hit comme miss), priorité aux restos avec menu. N'émet aucune fiche. Le connecteur `yelp` (API Fusion) reprend la main dès qu'une YELP_API_KEY existe.",295      "acces_legal": "Pages publiques yelp.ca, extraction minimale (note agrégée + lien fiche), attribution Yelp affichée avec la note (mêmes conditions d'affichage que Fusion). Anti-bot réel : Scrapfly ASP, ~30 crédits/page — budget serré. À remplacer par l'API Fusion (clé gratuite) dès que possible (CLAUDE.md §15).",296      "cadence": "quotidien par petits lots (80 pages), re-vérification 30 jours",297      "status": "actif"298    },299    {300      "id": "site-finder",301      "name": "Découverte des sites web (fiches Google Maps)",302      "url": "https://serper.dev",303      "platform": "serper",304      "connector": "site-finder",305      "tier": 4,306      "price_context": "aucun",307      "extraction": "Une requête API Serper /maps par resto OSM sans site web (q = nom, ll = @lat,lng,15z centrée sur la fiche — décisif pour les chaînes multi-succursales) : la fiche Google Maps expose website, téléphone, GPS et cid. Croisement conservateur : nom similaire + distance GPS <= 400 m, ambigu = ignoré. Domaines sociaux/agrégateurs/livraison REJETÉS (un lien Uber Eats n'est pas le site du resto), plateformes de réservation -> details.reservation_url, sinon -> colonne website (+ phone si vide) et details.site_finder (ré-appliqué si un sync OSM ré-écrase la colonne). N'émet aucune fiche : il DÉBLOQUE le connecteur site-resto (menus maison dine-in) pour les ~10 600 restos OSM sans site connu. Budget SITE_FINDER_BUDGET (3000 requêtes/cycle), échecs re-sondés 180 j.",308      "acces_legal": "API commerciale Serper (compte payant, quota contractuel) — aucune requête vers Google ni scraping direct. Seul le site web officiel et le téléphone publiés par le commerce lui-même sont conservés ; le crawl du menu se fait ensuite sur le site du resto (première partie, CLAUDE.md §15) par site-resto.",309      "cadence": "hebdomadaire par lots (3000 requêtes), échecs re-sondés 180 jours",310      "status": "actif"311    },312    {313      "id": "ubereats",314      "name": "Uber Eats (menus livraison + notes)",315      "url": "https://www.ubereats.com",316      "platform": "ubereats",317      "connector": "ubereats",318      "tier": 2,319      "price_context": "delivery",320      "extraction": "Découverte par sitemaps publics (robots.txt -> sitemap-store-*.xml.gz, URLs /ca/store/, index local data/ubereats-stores.json rafraîchi 30 j). Chaque page resto embarque __REACT_QUERY_STATE__ (getStoreV1) : menu complet (sections/items/prix en cents), note, adresse, téléphone, GPS. Croisement conservateur avec un resto EXISTANT (téléphone identique OU postal+civique OU GPS<120 m + nom similaire) — n'émet aucune fiche. Menu -> table menus en price_context delivery (prix majorés ~25-30 %), note -> details.ubereats. Budget UBEREATS_BUDGET (60 pages/cycle), verdicts en cache, re-visite 30 j.",321      "acces_legal": "Palier 2 (CLAUDE.md §9, §15) : CGU restrictives, Cloudflare — Scrapfly ASP (~1 crédit/page constaté). Usage d'appoint minimal : menus pour restos sans source dine-in/takeout, prix TOUJOURS étiquetés delivery, lien vers la fiche source conservé. Préférer UEAT/site du resto dès que disponible.",322      "cadence": "quotidien par petits lots (60 pages), re-vérification 30 jours",323      "status": "actif"324    },325    {326      "id": "racj",327      "name": "RACJ — Permis d'alcool en vigueur",328      "url": "https://www.donneesquebec.ca/recherche/dataset/racj-alcool-detaillant",329      "platform": "donnees-quebec",330      "connector": "permits (module d'enrichissement, pas de fiches)",331      "tier": 5,332      "price_context": "aucun",333      "extraction": "CSV ouvert racj-alcool-detaillant.csv (Données Québec, registre des permis de détaillant d'alcool en vigueur) : regroupement par établissement (NoEtablissement) puis croisement CONSERVATEUR avec les restaurants (nom normalisé + code postal/ville+civique, ou postal + civique + similarité de nom — mêmes règles que MAPAQ). Catégories de permis (Bar, Restaurant pour vendre/servir…), capacité et titulaire -> details.permis_alcool.",334      "acces_legal": "Données ouvertes du gouvernement du Québec (RACJ), licence CC-BY 4.0 — attribution RACJ/Données Québec affichée avec l'information de permis.",335      "cadence": "hebdomadaire (guard 6 jours dans ingest.enrich)",336      "status": "actif"337    },338    {339      "id": "mtl-alim",340      "name": "Montréal — Établissements alimentaires (données ouvertes)",341      "url": "https://donnees.montreal.ca/dataset/etablissements-alimentaires",342      "platform": "donnees-montreal",343      "connector": "mtl-alim",344      "tier": 4,345      "price_context": null,346      "extraction": "CSV ouvert businesses.csv (donnees.montreal.ca, ~54 000 lignes) : whitelist de 12 types d'établissements où l'on mange (Restaurant, service rapide, casse-croûte, bar, boulangerie-pâtisserie, traiteur, camion-cuisine…), statut Ouvert seulement, GPS bornés à l'île de Montréal. Nom, adresse, ville, GPS, type -> fiches de découverte SANS menu (les connecteurs de menus s'y greffent par déduplication). ~7 500 fiches.",347      "acces_legal": "Données ouvertes de la Ville de Montréal, licence CC-BY 4.0 — attribution affichée (page Sources). Un seul téléchargement CSV par cycle, UA identifiable.",348      "cadence": "mensuel",349      "status": "actif"350    },351    {352      "id": "tastet",353      "name": "Tastet (média food — découverte éditoriale)",354      "url": "https://tastet.ca",355      "platform": "tastet",356      "connector": "tastet",357      "tier": 4,358      "price_context": null,359      "extraction": "Sitemaps Yoast reviews-sitemap*.xml -> pages critiques ; chaque page embarque un lien Google Maps (nom + adresse complète) et un lien tel:. Fiches de découverte SANS menu (nom, adresse, ville, postal, téléphone, photo og:image, lien critique) ; la déduplication fusionne avec OSM/UEAT et la fiche canonique gagne le lien éditorial. Cache BD par page (clé lastmod), budget TASTET_BUDGET (80 pages/cycle), corpus incrémental.",360      "acces_legal": "Média public québécois, découverte minimale (coordonnées + lien sortant vers la critique = attribution). Politesse 1,2 s, UA identifiable, pas d'anti-bot à contourner (CLAUDE.md §15).",361      "cadence": "hebdomadaire par lots (80 pages), re-crawl si lastmod change",362      "status": "actif"363    },364    {365      "id": "chownow",366      "name": "ChowNow (commande en ligne)",367      "url": "https://www.chownow.com",368      "platform": "chownow",369      "connector": "chownow",370      "tier": 1,371      "price_context": "takeout",372      "extraction": "API JSON publique non authentifiée : api.chownow.com/api/restaurant/<id> (fiche complète : nom, adresse, téléphone, GPS, site) + /<id>/menu (menu_categories + graphe complet des modificateurs -> options §5.2). 2 requêtes/resto, politesse 0,8 s. Émet des fiches complètes avec menu takeout ; filtre state == QC. Intégrations découvertes automatiquement par site-resto (liens direct.chownow.com sur les sites des restos -> data/chownow-discovered.json).",373      "acces_legal": "Source de première partie (plateforme de commande du resto lui-même, prix réels non majorés — CLAUDE.md §9 Palier 1, §15). API ouverte, extraction minimale, lien de commande conservé.",374      "cadence": "hebdomadaire",375      "status": "dormant (aucune intégration découverte encore — SkipSource)"376    },377    {378      "id": "gloriafood",379      "name": "GloriaFood / Oracle (widget de commande)",380      "url": "https://www.gloriafood.com",381      "platform": "gloriafood",382      "connector": "gloriafood",383      "tier": 1,384      "price_context": "takeout",385      "extraction": "API publique du widget : GET pos.globalfoodsoft.com/pos/menu (Authorization: <ruid>, Glf-Api-Version: 2) -> categories[].items[] {name, description, price, sizes}. ENRICHISSEMENT PUR : le menu est posé sur le resto porteur (uid consigné par site-resto avec les data-glf-cuid/ruid détectés dans le HTML -> data/gloriafood-discovered.json). Re-visite 14 j, refus 403 défensifs.",386      "acces_legal": "API du widget de commande du resto lui-même (première partie, prix réels — CLAUDE.md §9 Palier 1, §15). Extraction minimale, lien conservé.",387      "cadence": "hebdomadaire, re-visite 14 jours",388      "status": "dormant (aucune intégration découverte encore — SkipSource)"389    },390    {391      "id": "square",392      "name": "Square Online (boutiques de commande)",393      "url": "https://squareup.com/ca/fr/online-store",394      "platform": "square-online",395      "connector": "square",396      "tier": 1,397      "price_context": "takeout",398      "extraction": "Boutiques <sous-domaine>.square.site détectées par site-resto (lien de commande sur le site du resto -> data/square-discovered.json avec l'uid porteur). SPA sans JSON-LD ni prix inline : page /s/order rendue en JS via Scrapfly puis texte structuré par Claude Haiku (menullm, validation stricte des prix). ENRICHISSEMENT PUR : menu takeout posé sur le resto porteur + details.square. Budget SQUARE_BUDGET (15 rendus/cycle), re-visite 30 j.",399      "acces_legal": "Boutique de commande du resto lui-même (première partie, prix réels — CLAUDE.md §9 Palier 1, §15). Extraction minimale, lien source conservé.",400      "cadence": "hebdomadaire par petits lots (15 rendus), re-visite 30 jours",401      "status": "dormant (aucune boutique découverte encore — SkipSource)"402    },403    {404      "id": "doordash",405      "name": "DoorDash (menus livraison + notes)",406      "url": "https://www.doordash.com",407      "platform": "doordash",408      "connector": "doordash",409      "tier": 2,410      "price_context": "delivery",411      "extraction": "Découverte par le sitemap public QC (sitemap-doordash-qc-stores.xml, ~11 700 URLs /en-CA/store/, index local data/doordash-stores.json rafraîchi 30 j). Chaque page resto embarque du JSON-LD schema.org (Restaurant + Menu -> sections/items/prix, note, adresse, GPS). Croisement conservateur avec un resto EXISTANT (GPS<120 m + nom similaire OU civique+ville+nom) — n'émet aucune fiche. Menu -> table menus en price_context delivery (prix majorés ~25-30 %), note -> details.doordash. Budget DOORDASH_BUDGET (40 pages/cycle), verdicts en cache, re-visite 30 j.",412      "acces_legal": "Palier 2 (CLAUDE.md §9, §15) : CGU restrictives, anti-bot — Scrapfly ASP. Usage d'appoint minimal : menus pour restos sans source dine-in/takeout, prix TOUJOURS étiquetés delivery, lien vers la fiche source conservé. Préférer UEAT/site du resto dès que disponible.",413      "cadence": "quotidien par petits lots (40 pages), re-vérification 30 jours",414      "status": "actif"415    },416    {417      "id": "skip",418      "name": "SkipTheDishes (menus livraison)",419      "url": "https://www.skipthedishes.com",420      "platform": "skip",421      "connector": "skip",422      "tier": 2,423      "price_context": "delivery",424      "extraction": "Découverte par sitemaps publics (sitemap2..7.xml, URLs partenaires), index local data/skip-partners.json rafraîchi 30 j. Chaque page partenaire embarque __NEXT_DATA__ (menu complet en cents, téléphone dans les disclaimers, ville/province/postal). Croisement conservateur avec un resto EXISTANT (téléphone identique OU postal+civique), rejet hors-QC — n'émet aucune fiche. Menu -> table menus en price_context delivery, note -> details.skip. Budget SKIP_BUDGET (40 pages/cycle), verdicts en cache, re-visite 30 j.",425      "acces_legal": "Palier 2 (CLAUDE.md §9, §15) : CGU restrictives, anti-bot — Scrapfly ASP. Usage d'appoint minimal : menus pour restos sans source dine-in/takeout, prix TOUJOURS étiquetés delivery, lien vers la fiche source conservé.",426      "cadence": "quotidien par petits lots (40 pages), re-vérification 30 jours",427      "status": "actif"428    }429  ]430}