Liste des mairies sur data.gouv.fr

Description
Processus
  1. Extraction des mairies (annuaire.py) : lecture du fichier brut input/2026-06-22_053126-data.gouv_local.json (annuaire service-public.gouv.fr, 86 212 services). Filtrage sur les entrées dont le champ pivot[].type_service_local == "mairie" et dont le siren est renseigné. Cas particulier de Paris, Lyon et Marseille : chaque arrondissement y est une entrée distincte partageant le SIREN de la ville ; une seule ligne est conservée par ville, avec le code INSEE de la commune entière (75056, 69123, 13055) plutôt qu'un code d'arrondissement. Résultat : 23 920 mairies.

  2. Jointure avec data.gouv.fr (join.py) : croisement avec l'export des organisations data.gouv.fr (input/export-organization-20260622-061308.csv) sur la clé siren (annuaire) = 9 premiers caractères du business_number_id (SIRET, export). 839 correspondances trouvées. 18 SIREN correspondent à plusieurs organisations (doublons de lignes dans l'export).


Fichiers produits
data/annuaire_mairies.csv

Toutes les mairies avec SIREN extraites de l'annuaire service-public.

ColonneDescription
nomNom de la mairie
sirenNuméro SIREN (9 chiffres)
code_insee_communeCode INSEE de la commune
data/annuaire_mairies_join.csv

Mairies présentes à la fois dans l'annuaire service-public et sur data.gouv.fr.

ColonneDescription
idIdentifiant de l'organisation data.gouv.fr
nameNom de l'organisation data.gouv.fr
annuaire_nomNom dans l'annuaire service-public
sirenNuméro SIREN
code_insee_communeCode INSEE de la commune
metric.datasetsNombre de jeux de données publiés
data/annuaire_mairies_join_duplicates.csv

Même schéma que annuaire_mairies_join.csv. Contient uniquement les lignes pour lesquelles un même SIREN correspond à plusieurs organisations dans l'export data.gouv.fr.

Code
Extrait de l'annuaire des services publics

A partir de la base locale de l'annuaire des services publics en JSON, produit un CSV nom,siren,code_insee_commune :

import csv
import json

INPUT_FILE = "input/2026-06-22_053126-data.gouv_local.json"
OUTPUT_FILE = "data/annuaire_mairies.csv"
FIELDNAMES = ["nom", "siren", "code_insee_commune"]

# Paris, Lyon, Marseille each expose one service per arrondissement, all
# sharing the city's siren. Collapse those down to the whole-city code.
PLM_CODES = {"75056", "69123", "13055"}


def is_mairie(service: dict) -> bool:
    return any(
        p.get("type_service_local") == "mairie"
        for p in service.get("pivot", [])
    )


def get_code_insee(service: dict) -> str:
    for p in service.get("pivot", []):
        if p.get("type_service_local") == "mairie":
            codes = p.get("code_insee_commune", [])
            return codes[0] if codes else ""
    return ""


def main():
    print(f"Loading {INPUT_FILE}...")
    with open(INPUT_FILE, encoding="utf-8") as f:
        data = json.load(f)

    services = data.get("service", [])
    print(f"{len(services)} services total")

    entries_by_siren = {}
    for svc in services:
        if not is_mairie(svc):
            continue
        siren = svc.get("siren", "").strip()
        if not siren:
            continue
        entries_by_siren.setdefault(siren, []).append(
            (svc.get("nom", ""), get_code_insee(svc))
        )

    count = 0
    with open(OUTPUT_FILE, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=FIELDNAMES)
        writer.writeheader()
        for siren, entries in entries_by_siren.items():
            plm_code = next((c for _, c in entries if c in PLM_CODES), None)
            if plm_code:
                nom = next(n for n, c in entries if c == plm_code)
                writer.writerow({
                    "nom": nom,
                    "siren": siren,
                    "code_insee_commune": plm_code,
                })
                count += 1
            else:
                for nom, code in entries:
                    writer.writerow({
                        "nom": nom,
                        "siren": siren,
                        "code_insee_commune": code,
                    })
                    count += 1

    print(f"Done. {count} mairies with siren written to {OUTPUT_FILE}")


if __name__ == "__main__":
    main()
Jointure annuaire des services publics X data.gouv.fr

A partir du CSV extrait de l'annuaire plus haut et du catalogue des ressources de data.gouv.fr, créé les fichiers de jointure et des doublons :

import csv
import os

ANNUAIRE_FILE = "data/annuaire_mairies.csv"
EXPORT_FILE = "input/export-organization-20260622-061308.csv"
OUTPUT_FILE = "data/annuaire_mairies_join.csv"
DUPLICATES_FILE = "data/annuaire_mairies_join_duplicates.csv"


def main():
    # Index annuaire by siren
    annuaire: dict[str, dict] = {}
    with open(ANNUAIRE_FILE, newline="", encoding="utf-8") as f:
        for row in csv.DictReader(f):
            annuaire[row["siren"]] = row

    print(f"Annuaire: {len(annuaire)} mairies")

    os.makedirs("data", exist_ok=True)

    matched = 0
    siren_hits: dict[str, list[str]] = {}
    rows_by_siren: dict[str, list[dict]] = {}

    with open(EXPORT_FILE, newline="", encoding="utf-8") as fin, \
         open(OUTPUT_FILE, "w", newline="", encoding="utf-8") as fout:

        reader = csv.DictReader(fin, delimiter=";")
        fieldnames = ["id", "name", "annuaire_nom", "siren", "code_insee_commune", "metric.datasets"]
        writer = csv.DictWriter(fout, fieldnames=fieldnames)
        writer.writeheader()

        for row in reader:
            siren = (row.get("business_number_id") or "").strip()[:9]
            if siren in annuaire:
                siren_hits.setdefault(siren, []).append(row.get("business_number_id", "").strip())
                out_row = {
                    "id": row["id"],
                    "name": row["name"],
                    "annuaire_nom": annuaire[siren]["nom"],
                    "siren": siren,
                    "code_insee_commune": annuaire[siren]["code_insee_commune"],
                    "metric.datasets": row.get("metric.datasets", ""),
                }
                rows_by_siren.setdefault(siren, []).append(out_row)
                writer.writerow(out_row)
                matched += 1

    duplicates = {siren: rows for siren, rows in rows_by_siren.items() if len(rows) > 1}
    if duplicates:
        print(f"WARNING: {len(duplicates)} siren(s) matched multiple orgs")
        with open(DUPLICATES_FILE, "w", newline="", encoding="utf-8") as fdup:
            writer_dup = csv.DictWriter(fdup, fieldnames=["id", "name", "annuaire_nom", "siren", "code_insee_commune", "metric.datasets"])
            writer_dup.writeheader()
            for rows in duplicates.values():
                writer_dup.writerows(rows)
        print(f"Duplicates written to {DUPLICATES_FILE}")

    print(f"Done. {matched} rows written to {OUTPUT_FILE}")


if __name__ == "__main__":
    main()
Producteur
Alexandre Bulté
Ce jeu de données a été publié à l'initiative et sous la responsabilité de Alexandre Bulté.
Dernière mise à jour
23 juin 2026

Vues

0

Téléchargements

0

  • Documentation des fichiers manquante

  • Couverture temporelle non renseignée

3 fichiers principaux

Mis à jour le 23 juin 2026 csv (71,5 Ko)34

Mis à jour le 23 juin 2026 csv (3,1 Ko)10

Mis à jour le 23 juin 2026 csv (936,5 Ko)48