mirror of
https://github.com/JMP-MS/ASPIC.git
synced 2026-10-27 17:17:08 +00:00
V1.23.28 Mise à jour de la BDD des entreprises et stratégies
This commit is contained in:
@@ -115,6 +115,26 @@ NAF_CODES = [
|
||||
'98.20Z', '99.00Z',
|
||||
]
|
||||
|
||||
# Plage de divisions (2 premiers chiffres du code NAF) par section -- permet de
|
||||
# limiter le repli par code NAF precis (3e niveau) aux seuls codes de la section
|
||||
# en cours, au lieu de retester les 732 codes en entier a chaque section plafonnee
|
||||
# (bug corrige le 13/09/2026 : provoquait un blocage de plusieurs heures sur les
|
||||
# grandes villes, ex. Toulouse, ou plusieurs sections restent plafonnees).
|
||||
SECTION_DIVISIONS = {
|
||||
"A": range(1, 4), "B": range(5, 10), "C": range(10, 34), "D": range(35, 36),
|
||||
"E": range(36, 40), "F": range(41, 44), "G": range(45, 48), "H": range(49, 54),
|
||||
"I": range(55, 57), "J": range(58, 64), "K": range(64, 67), "L": range(68, 69),
|
||||
"M": range(69, 76), "N": range(77, 83), "O": range(84, 85), "P": range(85, 86),
|
||||
"Q": range(86, 89), "R": range(90, 94), "S": range(94, 97), "T": range(97, 99),
|
||||
"U": range(99, 100),
|
||||
}
|
||||
|
||||
|
||||
def codes_for_section(section):
|
||||
divisions = SECTION_DIVISIONS[section]
|
||||
return [c for c in NAF_CODES if int(c[:2]) in divisions]
|
||||
|
||||
|
||||
CAP = 10000
|
||||
PAGE_SIZE = 25
|
||||
RATE_DELAY = 0.15 # ~6-7 req/s, sous le quota documente de l'API
|
||||
@@ -128,6 +148,7 @@ CREATE TABLE IF NOT EXISTS `Entreprises{dep}Phase1` (
|
||||
`ENT_AdresseSiege` varchar(255) DEFAULT NULL,
|
||||
`ENT_CodePostal` varchar(20) DEFAULT NULL,
|
||||
`ENT_Commune` varchar(100) DEFAULT NULL,
|
||||
`ENT_CodeCommune` char(5) DEFAULT NULL,
|
||||
`ENT_Departement` char(3) DEFAULT NULL,
|
||||
`ENT_Region` char(2) DEFAULT NULL,
|
||||
`ENT_DateCreation` date DEFAULT NULL,
|
||||
@@ -154,8 +175,10 @@ CREATE TABLE IF NOT EXISTS `Entreprises{dep}Phase1` (
|
||||
`ENT_DateImport` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`ENT_DateMajInsee` datetime DEFAULT NULL,
|
||||
`ENT_ReponseBruteJson` json DEFAULT NULL,
|
||||
PRIMARY KEY (`ENT_Siren`)
|
||||
PRIMARY KEY (`ENT_Siren`),
|
||||
KEY `idx_commune` (`ENT_CodeCommune`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
|
||||
ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8
|
||||
"""
|
||||
|
||||
DDL_PHASE2 = """
|
||||
@@ -183,7 +206,7 @@ CREATE TABLE IF NOT EXISTS `Entreprises{dep}Phase3` (
|
||||
DDL_COMMUNES = """
|
||||
CREATE TABLE IF NOT EXISTS `ENT_Communes` (
|
||||
`COM_CodeInsee` char(5) NOT NULL,
|
||||
`COM_CodePostal` varchar(20) DEFAULT NULL,
|
||||
`COM_CodePostal` varchar(100) DEFAULT NULL,
|
||||
`COM_Ville` varchar(100) NOT NULL,
|
||||
`COM_Departement` char(3) NOT NULL,
|
||||
`COM_Latitude` decimal(10,6) DEFAULT NULL,
|
||||
@@ -193,6 +216,25 @@ CREATE TABLE IF NOT EXISTS `ENT_Communes` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
"""
|
||||
|
||||
DDL_DEPARTEMENTS = """
|
||||
CREATE TABLE IF NOT EXISTS `ENT_Departements` (
|
||||
`DEP_Code` char(3) NOT NULL,
|
||||
`DEP_Nom` varchar(100) NOT NULL,
|
||||
`DEP_NbEntreprises` int NOT NULL DEFAULT 0,
|
||||
`DEP_DateExtractionInitiale` datetime DEFAULT NULL,
|
||||
`DEP_DateDerniereSyncFormalites` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`DEP_Code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
"""
|
||||
|
||||
DDL_CONFIG = """
|
||||
CREATE TABLE IF NOT EXISTS `ENT_Config` (
|
||||
`CFG_Cle` varchar(100) NOT NULL,
|
||||
`CFG_Valeur` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`CFG_Cle`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
"""
|
||||
|
||||
|
||||
def log(msg):
|
||||
print(msg, file=sys.stderr, flush=True)
|
||||
@@ -209,11 +251,51 @@ def http_get_json(url, retries=5):
|
||||
time.sleep(1 + attempt)
|
||||
|
||||
|
||||
# Paris, Lyon et Marseille (PLM) : dans les donnees Sirene, le siege d'une
|
||||
# entreprise de ces trois villes est quasi toujours code au niveau de
|
||||
# l'arrondissement (75101-75120, 69381-69389, 13201-13216), jamais au code
|
||||
# commune englobant (75056, 69123, 13055) -- verifie empiriquement le 14
|
||||
# septembre 2026 sur Marseille : code_commune=13055 ne renvoie qu'une dizaine
|
||||
# de resultats, alors que chaque arrondissement (13201 a 13216) est a lui
|
||||
# seul plafonne ou proche du plafond de 10 000. Le code englobant est donc
|
||||
# remplace par la liste de ses arrondissements avant extraction.
|
||||
COMMUNES_ARRONDISSEMENTS = {"75": "75056", "69": "69123", "13": "13055"}
|
||||
|
||||
|
||||
def fetch_arrondissements_geo(dep):
|
||||
url = "https://geo.api.gouv.fr/communes?" + urllib.parse.urlencode(
|
||||
{"codeDepartement": dep, "type": "arrondissement-municipal",
|
||||
"fields": "code,nom,centre,codesPostaux,departement"}
|
||||
)
|
||||
return http_get_json(url)
|
||||
|
||||
|
||||
def fetch_communes_geo(dep):
|
||||
url = API_GEO.format(dep=dep) + "?" + urllib.parse.urlencode(
|
||||
{"fields": "code,nom,centre,codesPostaux,departement"}
|
||||
)
|
||||
return http_get_json(url)
|
||||
communes = http_get_json(url)
|
||||
code_englobant = COMMUNES_ARRONDISSEMENTS.get(dep)
|
||||
if code_englobant:
|
||||
communes = [c for c in communes if c["code"] != code_englobant]
|
||||
communes.extend(fetch_arrondissements_geo(dep))
|
||||
return communes
|
||||
|
||||
|
||||
def fetch_departement_nom(dep):
|
||||
url = f"https://geo.api.gouv.fr/departements/{dep}?fields=code,nom"
|
||||
data = http_get_json(url)
|
||||
return data.get("nom", dep)
|
||||
|
||||
|
||||
def upsert_departement(conn, dep, nom, nb_entreprises):
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO ENT_Departements (DEP_Code, DEP_Nom, DEP_NbEntreprises, DEP_DateExtractionInitiale) "
|
||||
"VALUES (%s, %s, %s, NOW()) "
|
||||
"ON DUPLICATE KEY UPDATE DEP_Nom=VALUES(DEP_Nom), DEP_NbEntreprises=VALUES(DEP_NbEntreprises)",
|
||||
(dep, nom, nb_entreprises),
|
||||
)
|
||||
|
||||
|
||||
NON_DIFFUSIBLE = "[NON-DIFFUSIBLE]"
|
||||
@@ -254,6 +336,7 @@ def map_entreprise(r):
|
||||
"ENT_AdresseSiege": clean(siege.get("adresse")),
|
||||
"ENT_CodePostal": clean(siege.get("code_postal")),
|
||||
"ENT_Commune": clean(siege.get("libelle_commune")),
|
||||
"ENT_CodeCommune": clean(siege.get("commune")),
|
||||
"ENT_Departement": clean(siege.get("departement")),
|
||||
"ENT_Region": clean(siege.get("region")),
|
||||
"ENT_DateCreation": clean(r.get("date_creation")),
|
||||
@@ -329,7 +412,7 @@ def fetch_commune_entreprises(code_commune, seen):
|
||||
# au filtre de section.
|
||||
log(f" commune {code_commune} section {section} encore plafonnee ({sec_total}), "
|
||||
f"repli par code NAF precis")
|
||||
for code in NAF_CODES:
|
||||
for code in codes_for_section(section):
|
||||
code_params = dict(base, activite_principale=code)
|
||||
code_total = probe_total(code_params)
|
||||
if code_total == 0:
|
||||
@@ -383,6 +466,8 @@ def ensure_tables(conn, dep):
|
||||
cur.execute(DDL_PHASE2.format(dep=dep))
|
||||
cur.execute(DDL_PHASE3.format(dep=dep))
|
||||
cur.execute(DDL_COMMUNES)
|
||||
cur.execute(DDL_DEPARTEMENTS)
|
||||
cur.execute(DDL_CONFIG)
|
||||
|
||||
|
||||
def ensure_communes(conn, dep, communes_geo):
|
||||
@@ -431,8 +516,16 @@ def run_department(conn, dep):
|
||||
total_finances += 1
|
||||
if results:
|
||||
log(f" {c['nom']} ({c['code']}) : {len(results)} entreprises")
|
||||
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(f"SELECT COUNT(*) FROM `{table1}`")
|
||||
(nb_total,) = cur.fetchone()
|
||||
nom_dep = fetch_departement_nom(dep)
|
||||
upsert_departement(conn, dep, nom_dep, nb_total)
|
||||
|
||||
log(f"Departement {dep} termine : {total_upserts} entreprises upsertees dans {table1}, "
|
||||
f"{total_finances} lignes financieres upsertees dans {table3}")
|
||||
f"{total_finances} lignes financieres upsertees dans {table3} (total {nb_total} -- "
|
||||
f"ENT_Departements mise a jour)")
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in New Issue
Block a user