URL: https://linuxfr.org/users/laurentu/journaux/ban-de-addok Title: BAN de ADDOK Authors: passke Date: 2021年04月07日T21:49:41+02:00 License: CC By-SA Tags: open_source, open_data, géolocalisation et debian Score: 35 La [BAN](https://www.data.gouv.fr/fr/datasets/base-adresse-nationale/) (Base Adresse Nationale) est un jeu de données publié en Open Data et issu d'une collaboration entre plusieurs acteurs (communes, IGN, La Poste, OpenStreetMap,...). La BAN contient 25 millions d'adresses françaises géocodées ainsi que d'autres informations (population des communes par exemple). Elle est notamment utilisée pour fournir l'API publique [Adresse](https://geo.api.gouv.fr/adresse). [ADDOK](https://github.com/addok/addok) est un moteur de géocodage open source développé par l'[Etalab](https://www.etalab.gouv.fr/). C'est ce moteur qui fourni l'API Adresse citée précédemment. Ces deux éléments étant disponibles librement, il est donc possible de monter son propore service de géocodage reposant sur des données fiables. Le projet ADDOK fourni une [documentation](https://addok.readthedocs.io/en/latest/install/) plutôt bien réalisée sur l'installation du logiciel et son alimentation par la BAN, mais elle date un petit peu. Je vous propose ici une version simplifiée et un peu plus à jour pour une Debian Buster. Dans un premier temps on commence par installer un certain nombre de pré-requis. ```bash sudo apt install redis-server python3.7 python3.7-dev python-pip python3.7-venv ``` Le reste de l'installation et de la configuration peut se faire en tant qu'utilisateur standard. On commence par créer un *venv* dédié. ```bash cd $HOME python3.7 -m venv addok source addok/bin/activate ``` Une fois dans le *venv* on installe Addok. ```bash pip install wheel pip install addok pip install addok-fr pip install addok-france ``` Le logiciel étant installé, il faut maintenant créer un fichier de configuration. Un exemple est fourni *addok/lib/python3.7/site-packages/addok/config/default.py* et pourrait être utilisé directement. Il faut cependant le modifier quelque peu pour profiter des plugins *addok-fr* et *addok-france*. On crée donc le fichier addok/addok.conf dont le contenu un peu long est à la fin de l'article. Il reste maintenant à obtenir les données à injecter dans le géocodeur. Ce dernier utilise une base Redis et en injectant la totalité de la BAN, il faudrait plusieurs Go de RAM. Heureusement, il est possible de télécharger des [extraits de la BAN](https://adresse.data.gouv.fr/data/ban/adresses/latest/addok/) par département. Par exemple pour le Bas-Rhin: ``` wget https://adresse.data.gouv.fr/data/ban/adresses/latest/addok/adresses-addok-67.ndjson.gz gunzip adresses-addok-67.ndjson.gz ``` Il suffit maintenant d'injecter les données récupérées: ``` addok batch adresses-addok-67.ndjson addok ngrams ``` Un premier test simple consiste à ouvrir un *shell* addok et à géocoder une adresse: ``` addok --config addok/addok.conf shell Addok 1.0.2 Loaded local config from addok/addok.conf Loaded plugins: addok.shell==1.0.2, addok.http.base==1.0.2, addok.batch==1.0.2, addok.pairs==1.0.2, addok.fuzzy==1.0.2, addok.autocomplete==1.0.2, france==1.1.0, fr==1.0.1 Welcome to the Addok shell o/ Type HELP or ? to list commands. Type QUIT or ctrl-C or ctrl-D to quit.> Strasbourg Strasbourg (J6Ol | 0.9610972727272726) Route de la Wantzenau 67000 Strasbourg (k5Pr | 0.7135927272727272) Avenue de Colmar 67100 Strasbourg (xkZE | 0.7129881818181817) Route de Schirmeck 67200 Strasbourg (76wG | 0.7129481818181818) Route des Romains 67200 Strasbourg (P19l | 0.7128863636363635) Route d’Oberhausbergen 67200 Strasbourg (667Q | 0.7127390909090908) Route de Mittelhausbergen 67200 Strasbourg (NxnK | 0.7122436363636363) Route du Polygone 67100 Strasbourg (qjrR | 0.7112654545454544) Rue de la Ganzau 67100 Strasbourg (oYRk | 0.7110227272727272) Rue Boecklin 67000 Strasbourg (y83E | 0.7103163636363635) 71.6 ms — 1 run(s) — 10 results -------------------------------------------------------------------------------- ``` Si cette étape fonctionne on peut lancer le serveur intégré: ``` addok --config addok/addok.conf serve Addok 1.0.2 Loaded local config from addok/addok.conf Loaded plugins: addok.shell==1.0.2, addok.http.base==1.0.2, addok.batch==1.0.2, addok.pairs==1.0.2, addok.fuzzy==1.0.2, addok.autocomplete==1.0.2, france==1.1.0, fr==1.0.1 Serving HTTP on 127.0.0.1:7878... ``` Et enfin utiliser l'API pour géocoder l'adresse: ``` curl "http://localhost:7878/search/?q=Strasbourg" {"type": "FeatureCollection", "version": "draft", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [7.761454, 48.579831]}, "properties": {"label": "Strasbourg", "score": 0.9610972727272726, "id": "67482", "type": "municipality", "name": "Strasbourg", "postcode": "67200", "citycode": "67482", "x": 1051008.43, "y": 6841654.82, "population": 279284, "city": "Strasbourg", "context": "67, Bas-Rhin, Grand Est", "importance": 0.57207}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [7.787474, 48.616029]}, "properties": {"label": "Route de la Wantzenau 67000 Strasbourg", "score": 0.7135927272727272, "id": "67482_7080", "name": "Route de la Wantzenau", "postcode": "67000", "citycode": "67482", "x": 1052680.41, "y": 6845787.55, "city": "Strasbourg", "context": "67, Bas-Rhin, Grand Est", "type": "street", "importance": 0.84952}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [7.749156, 48.558389]}, "properties": {"label": "Avenue de Colmar 67100 Strasbourg", "score": 0.7129881818181817, "id": "67482_1430", "name": "Avenue de Colmar", "postcode": "67100", "citycode": "67482", "x": 1050246.21, "y": 6839220.87, "city": "Strasbourg", "context": "67, Bas-Rhin, Grand Est", "type": "street", "importance": 0.84287}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [7.709492, 48.567865]}, "properties": {"label": "Route de Schirmeck 67200 Strasbourg", "score": 0.7129481818181818, "id": "67482_6290", "name": "Route de Schirmeck", "postcode": "67200", "citycode": "67482", "x": 1047261.71, "y": 6840097.22, "city": "Strasbourg", "context": "67, Bas-Rhin, Grand Est", "type": "street", "importance": 0.84243}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [7.707628, 48.578578]}, "properties": {"label": "Route des Romains 67200 Strasbourg", "score": 0.7128863636363635, "id": "67482_5690", "name": "Route des Romains", "postcode": "67200", "citycode": "67482", "x": 1047053.47, "y": 6841277.85, "city": "Strasbourg", "context": "67, Bas-Rhin, Grand Est", "type": "street", "importance": 0.84175}}], "attribution": "BANO", "licence": "ODbL", "query": "Strasbourg", "limit": 5} ``` L'ensemble de l'API est documenté sur le site [geo.api.gouv.fr](https://geo.api.gouv.fr/adresse). *addok/addok.conf* ``` import os from pathlib import Path REDIS = { 'host': os.environ.get('REDIS_HOST') or 'localhost', 'port': os.environ.get('REDIS_PORT') or 6379, 'unix_socket_path': os.environ.get('REDIS_SOCKET'), 'indexes': { 'db': os.environ.get('REDIS_DB_INDEXES') or 0, }, 'documents': { 'db': os.environ.get('REDIS_DB_DOCUMENTS') or 1, } } # Min/max number of results to be retrieved from db and scored. BUCKET_MIN = 10 BUCKET_MAX = 100 # Above this treshold, terms are considered commons. COMMON_THRESHOLD = 10000 # Above this treshold, we avoid intersecting sets. INTERSECT_LIMIT = 100000 # Min score considered matching the query. MATCH_THRESHOLD = 0.9 # Do not consider result if final score is below this threshold. MIN_SCORE = 0.1 QUERY_MAX_LENGTH = 200 GEOHASH_PRECISION = 7 MIN_EDGE_NGRAMS = 3 MAX_EDGE_NGRAMS = 20 SYNONYMS_PATH = None # Pipeline stream to be used. PROCESSORS_PYPATHS = [ # Rename in TOKEN_PROCESSORS / STRING_PROCESSORS? 'addok.helpers.text.tokenize', 'addok.helpers.text.normalize', 'addok_france.glue_ordinal', #ajout addok_france 'addok_france.fold_ordinal', #ajout addok_france 'addok_france.flag_housenumber', #ajout addok_france 'addok.helpers.text.flag_housenumber', 'addok.helpers.text.synonymize', 'addok_fr.phonemicize', #ajout addok_france ] QUERY_PROCESSORS_PYPATHS = [ 'addok.helpers.text.check_query_length', 'addok_france.extract_address', #Ajout addok_france 'addok_france.clean_query', #Ajout addok_france 'addok_france.remove_leading_zeros', #Ajout addok_france ] # Remove SEARCH_PREFIXES. SEARCH_PREPROCESSORS_PYPATHS = [ 'addok.helpers.search.tokenize', 'addok.helpers.search.search_tokens', 'addok.helpers.search.select_tokens', 'addok.helpers.search.set_should_match_threshold', ] BATCH_PROCESSORS_PYPATHS = [ 'addok.batch.to_json', 'addok.helpers.index.prepare_housenumbers', 'addok.ds.store_documents', 'addok.helpers.index.index_documents', ] BATCH_FILE_LOADER_PYPATH = 'addok.helpers.load_file' BATCH_CHUNK_SIZE = 1000 # During imports, workers are consuming RAM; # let one process free for Redis by default. BATCH_WORKERS = max(os.cpu_count() - 1, 1) RESULTS_COLLECTORS_PYPATHS = [ 'addok.helpers.collectors.no_tokens_but_housenumbers_and_geohash', 'addok.helpers.collectors.no_available_tokens_abort', 'addok.helpers.collectors.only_commons', 'addok.helpers.collectors.bucket_with_meaningful', 'addok.helpers.collectors.reduce_with_other_commons', 'addok.helpers.collectors.ensure_geohash_results_are_included_if_center_is_given', # noqa 'addok.helpers.collectors.extend_results_reducing_tokens', 'addok.helpers.collectors.extend_results_extrapoling_relations', ] SEARCH_RESULT_PROCESSORS_PYPATHS = [ 'addok.helpers.results.match_housenumber', 'addok_france.make_labels', #Ajout addok_france 'addok.helpers.results.make_labels', 'addok.helpers.results.score_by_importance', 'addok.helpers.results.score_by_autocomplete_distance', 'addok.helpers.results.score_by_ngram_distance', 'addok.helpers.results.score_by_geo_distance', ] REVERSE_RESULT_PROCESSORS_PYPATHS = [ 'addok.helpers.results.load_closer', 'addok.helpers.results.make_labels', 'addok.helpers.results.score_by_geo_distance', ] RESULTS_FORMATTERS_PYPATHS = [ 'addok.helpers.formatters.geojson', ] INDEXERS_PYPATHS = [ 'addok.helpers.index.HousenumbersIndexer', 'addok.helpers.index.FieldsIndexer', # Pairs indexer must be after `FieldsIndexer`. 'addok.pairs.PairsIndexer', # Edge ngram indexer must be after `FieldsIndexer`. 'addok.autocomplete.EdgeNgramIndexer', 'addok.helpers.index.FiltersIndexer', 'addok.helpers.index.GeohashIndexer', ] # Any object like instance having `loads` and `dumps` methods. DOCUMENT_SERIALIZER_PYPATH = 'addok.helpers.serializers.ZlibSerializer' DOCUMENT_STORE_PYPATH = 'addok.ds.RedisStore' # Fields to be indexed # If you want a housenumbers field but need to name it differently, just add # type="housenumbers" to your field. FIELDS = [ {'key': 'name', 'boost': 4, 'null': False}, {'key': 'street'}, {'key': 'postcode', 'boost': lambda doc: 1.2 if doc.get('type') == 'municipality' else 1}, {'key': 'city'}, {'key': 'housenumbers'}, {'key': 'context'}, ] # Sometimes you only want to add some fields keeping the default ones. EXTRA_FIELDS = [] # Weight of a document own importance: IMPORTANCE_WEIGHT = 0.1 # Default score for the relation token => document DEFAULT_BOOST = 1.0 # Data attribution # Can also be an object {source: attribution} ATTRIBUTION = "BANO" # Data licence # Can also be an object {source: licence} LICENCE = "ODbL" # Available filters (remember that every filter means bigger index) FILTERS = ["type", "postcode"] LOG_DIR = os.environ.get("ADDOK_LOG_DIR", Path(__file__).parent.parent.parent) LOG_QUERIES = False LOG_NOT_FOUND = False INDEX_EDGE_NGRAMS = True ```

AltStyle によって変換されたページ (->オリジナル) /