Scrap (Google Maps)
Module source qui extrait des fiches Google Maps pour un ensemble de requêtes sur une ou plusieurs zones géographiques, dans l'un des ~199 pays.
Purpose
Module source : exécute chaque requête sur chaque point de grille couvrant les zones demandées et retourne un CSV à plat d'établissements Google Maps (nom, contact, localisation, note).
Inputs
| Field | Type | Required | Description |
|---|---|---|---|
queries |
string[] (1–20) |
yes | Termes recherchés sur Google Maps. Chaque requête est trimée et plafonnée à 200 caractères. |
country |
string (ISO3) |
no | Pays ciblé, code ISO-3166 alpha-3 (ex. FRA, USA, DEU). Défaut "FRA". Détermine à la fois la grille GPS et la façon dont les zones sont résolues. |
zones |
string[] (1–50) |
yes | Zones géographiques exprimées dans country : un état/une région (adm1), un comté/département (adm2), une ville avec rayon optionnel ("Austin 30km"), ou le nom du pays pour scraper le pays entier. Pour la France, les codes INSEE, codes département et codes postaux restent valides. Chaque zone est résolue en grille de points côté serveur. |
include_reviews |
bool |
no | Conservé pour compatibilité ascendante. Ne chaîne pas un job reviews — utiliser le module reviews à la place. Défaut false. |
max_per_phone |
int (0–10) |
no | Fiches maximum gardées par numéro de téléphone. 0 (défaut) = aucune limite ; 1 = un seul contact par numéro. Les fiches sans numéro ne sont jamais écartées. Une même fiche n'apparaît jamais deux fois, quoi qu'il arrive. Voir Doublons. |
Corps de requête :
{
"queries": ["plombier", "chauffagiste"],
"country": "FRA",
"zones": ["75", "92"],
"include_reviews": false
}
Cibler un autre pays — les zones s'expriment alors dans ce pays :
{
"queries": ["plumber", "hvac"],
"country": "USA",
"zones": ["Texas", "Austin 30km"]
}
Colonnes optionnelles
departement/region: en France, dérivées du code postal ; dans tout autre pays, dérivées du GPS de l'établissement par reverse-geo mondial (adm2/adm1).
Requêtes Google Maps effectives = len(queries) × grid_points(zones). Rejeté à la soumission si coût supérieur au plafond per-job EF.
Outputs
Fichier résultat : CSV UTF-8, séparateur point-virgule, BOM (compatible Excel). Même jeu de données disponible en trois formats via l'endpoint de téléchargement.
| Column | Type | Description |
|---|---|---|
nom |
string | Nom de l'établissement affiché sur Google Maps. |
site_web |
string | URL du site web public si renseignée. |
telephone |
string | Numéro de téléphone tel que listé. |
adresse |
string | Adresse postale. |
rating |
float | Note moyenne (0.0–5.0). |
reviews_count |
int | Nombre d'avis publics. |
category |
string | Catégorie principale Google Maps. |
lien_google_maps |
string | URL canonique Google Maps de la fiche. |
aggregator_flag |
bool | Vrai si la fiche ressemble à un annuaire/agrégateur plutôt qu'à un établissement final. |
query |
string | Requête source qui a produit la ligne. |
lat, lon |
float | Point de grille auquel la ligne a été collectée. |
Doublons
Une fiche = une ligne. Toujours, sans réglage pour le désactiver. Un établissement peut être à portée de plusieurs points de grille GPS et correspondre à plusieurs de vos requêtes, et l'URL Google de la fiche n'est pas une identité stable — elle encode aussi le contexte de recherche, donc deux captures du même lieu reviennent avec des URL différentes. Les lignes sont donc dédoublonnées sur le feature id 0x…:0x… que Google porte dans cette URL (repli sur nom + adresse normalisés s'il est absent). C'est une garantie de justesse, pas une préférence.
max_per_phone — le seul réglage. Des fiches différentes partagent parfois un numéro : un standard commun, un gérant multi-établissements, ou un réseau de fiches locales quasi identiques pointant vers un seul centre d'appel. Pour une chaîne ce sont de vrais établissements distincts ; pour de la prospection c'est un seul contact. L'arbitrage vous revient :
| Valeur | Comportement |
|---|---|
0 (défaut) |
Aucune limite — toutes les fiches sont gardées, quel que soit le numéro affiché. |
1 |
Une seule fiche par numéro ; la première trouvée gagne. |
2, 3, … (max 10) |
Jusqu'à N fiches par numéro. |
Les numéros sont comparés en E.164, donc +33 1 87 58 88 84 et 01 87 58 88 84 sont le même numéro ; le country du job fixe la région servant à parser les formats nationaux. Les fiches sans numéro exploitable ne sont jamais écartées par ce réglage.
Le quota s'applique sur tout le job, requêtes et zones confondues, et est conservé lors de la reprise d'un job annulé. Le dédoublonnage ne change pas les points de grille scrapés : aucun effet sur le coût EF ni sur la durée.
Formats : csv (original), json, xlsx. Choisi via ?format= sur l'endpoint de téléchargement.
Lifecycle
Cycle de vie standard : voir Jobs & lifecycle. Pendant l'exécution, l'événement SSE status transporte une charge query_stats de forme { "<query>": { "tiles": int, "with_results": int } }, mise à jour en temps réel pour exposer le taux de succès par requête.
Pipeline
| Field | Value |
|---|---|
needs |
null (module source — aucun CSV d'entrée requis) |
produces |
poi_list |
Modules typiques chaînés en aval d'un scrap :
emails— recherche les emails pro et personnels depuissite_web.socials— extrait les comptes réseaux sociaux depuissite_web.legal_ids— extrait SIREN/SIRET depuis le site de l'établissement (page mentions légales).reviews— collecte les fils d'avis complets depuislien_google_maps.techstack,dead_check,brand_assets,ads_intelligence— enrichissements au niveau site web, indexés sursite_web.
Endpoints
Endpoint dédié :
POST /api/jobs
Content-Type: application/json
{
"queries": ["plombier"],
"zones": ["75"],
"include_reviews": false
}
Endpoint générique (équivalent — même payload, job_type déduit de la forme) :
POST /api/jobs
Content-Type: application/json
{
"job_type": "scrap",
"queries": ["plombier"],
"zones": ["75"]
}
Les deux réponses retournent l'objet JobPublic créé, incluant id, status, grid_points_count, ef_cost et output_filename.
Téléchargement :
GET /api/jobs/{job_id}/download?format=csv|json|xlsx
Limits
Quotas globaux de la plateforme : voir /docs/fr/concepts/limits. Plafonds spécifiques au module :
| Limit | Value |
|---|---|
| Nombre maximum de requêtes par job | 20 |
| Nombre maximum de zones par job | 50 |
| Longueur maximum d'une requête | 200 caractères |
| Coût maximum par job | 5 EF par défaut (par utilisateur, réglable jusqu'à 50) |
| Vérification email | Requise sur le compte avant création d'un job scrap. |
Errors
| Scenario | HTTP | Resolution |
|---|---|---|
| Zone non reconnue | 400 | Inspecter le tableau errors dans le corps de réponse. Vérifier que la zone est orthographiée telle qu'elle existe dans le country sélectionné (état/région, comté/département, "Ville 30km", ou nom du pays). Pour la France, codes INSEE/département/postaux et "France" fonctionnent aussi. |
| Aucun point de grille résolu | 400 | L'ensemble des zones est vide après résolution — élargir la sélection. |
| Quota EF dépassé | 400 | Réduire le nombre de requêtes ou rétrécir les zones jusqu'à ce que l'EF estimé tienne dans votre seuil par job (5 par défaut, réglable jusqu'à 50 dans Réglages). |
| Email non vérifié | 403 | Vérifier l'email du compte avant de créer un job scrap. |
| Aucun worker disponible | Le job reste en pending jusqu'à libération du pool multi-proxy partagé. Un seul job multi-proxy tourne à la fois sur l'ensemble de la plateforme. |
|
| Job échoué en cours | Un CSV partiel est conservé. Un POST /api/jobs/{id}/resume crée un job de relance qui saute les points de grille déjà traités et n'est facturé que sur le reliquat. |
|
| Téléchargement expiré | 410 | Les fichiers résultats ont une fenêtre de rétention — relancer le job ou chaîner depuis une source fraîche. |
Les requêtes refusées par Google Maps remontent dans dead_queries sur l'objet job.
Sources de données & attribution
La résolution des zones et le reverse-geocoding mondiaux reposent sur des jeux de données ouverts :
Frontières administratives mondiales © geoBoundaries (CC BY 4.0) · Villes © GeoNames (CC BY 4.0).