Python: Générer un fichier gpx

Un fichier GPX est un ensemble de coordonnées géographiques qui permet de créer des traces ou des itinéraires.

Pour utiliser ce script il est nécessaire d'installer les modules python suivants:

# python3 -m pip install --upgrade geopy requests dateutil bs4 numpy
#!/usr/bin/python3
# -*- coding: UTF-8 -*-

from geopy.geocoders import Nominatim
import requests
from dateutil.relativedelta import relativedelta
from bs4 import BeautifulSoup as bs
import numpy as np

cities = ['nantes, france', 'ancenis, france', 'angers, france']
geolocator = Nominatim(user_agent="Python3")
LAT = []
LNG = []
url = "https://routing.openstreetmap.de/routed-car/route/v1/driving/{frlng},{frlat};{tolng},{tolat}"
params = dict(overview='false', geometries='polyline', steps='true')
xml = bs(features='xml')
gpx = xml.new_tag('gpx')
gpx.attrs = {'creator':"Script Python", 'version':"1.1",\
             'xmlns':"http://www.topografix.com/GPX/1/1", 'xmlns:xsi':"http://www.w3.org/2001/XMLSchema-instance",\
             'xsi:schemaLocation':"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"}
trkl = []

for idxcity in enumerate(cities[:-1]):
    idx, city = idxcity
    FROM = geolocator.geocode(city)
    TO = geolocator.geocode(cities[idx+1])
    datas = dict(frlat=FROM.latitude, frlng=FROM.longitude, tolat=TO.latitude, tolng=TO.longitude)
    req1 = requests.get(url.format(**datas), params)
    js = req1.json()
    steps = js.get('routes')[0].get('legs')[0].get('steps')
    distance = round(js.get('routes')[0].get('distance') / 1000, 0)
    duration = relativedelta(seconds=js.get('routes')[0].get('duration'))
    frname = FROM.raw.get('display_name')
    toname = TO.raw.get('display_name')
    print(f'Itinéraire entre {frname} et {toname}.')
    wpt = xml.new_tag('wpt')
    wpt.attrs = {'lat':FROM.latitude , 'lon':FROM.longitude}
    wptname = xml.new_tag('name')
    wptname.string = frname
    wpt.append(wptname)
    gpx.append(wpt)
    trk = xml.new_tag('trk')
    name = xml.new_tag('name')
    name.string = f'{frname} - {toname}'
    desc = xml.new_tag('desc')
    desc.string = f'{distance} km, {int(duration.hours)}:{int(duration.minutes)}'
    trkseg = xml.new_tag('trkseg')
    for x in steps:
        for y in x['intersections']:
            lon, lat = y['location']
            LAT.append(lat)
            LNG.append(lon)
            trkpt = xml.new_tag('trkpt')
            trkpt.attrs = dict(lat=lat, lon=lon)
            trkseg.append(trkpt)
    trk.append(name)
    trk.append(desc)
    trk.append(trkseg)
    trkl.append(trk)

wpt = xml.new_tag('wpt')
wpt.attrs = {'lat':TO.latitude , 'lon':TO.longitude}
wptname = xml.new_tag('name')
wptname.string = toname
wpt.append(wptname)
gpx.append(wpt)
for trk in trkl:
    gpx.append(trk)
xml.append(gpx)

print(xml.prettify())
print(f'Position centrale: {np.mean(LAT)},{np.mean(LNG)}')

Dans mon exemple, je souhaite créer un itinéraire Nantes - Ancenis - Angers

Ce script va générer un contenu xml comme ceci:

<?xml version="1.0" encoding="utf-8"?>
<gpx creator="Script Python" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
 <wpt lat="47.2186371" lon="-1.5541362">
  <name>
   Nantes, Loire-Atlantique, Pays de la Loire, France métropolitaine, France
  </name>
 </wpt>
 <wpt lat="47.3648141" lon="-1.1816088">
  <name>
   Ancenis, Châteaubriant-Ancenis, Loire-Atlantique, Pays de la Loire, France métropolitaine, 44150, France
  </name>
 </wpt>
 <wpt lat="47.4739884" lon="-0.5515588">
  <name>
   Angers, Maine-et-Loire, Pays de la Loire, France métropolitaine, France
  </name>
 </wpt>
 <trk>
  <name>
   Nantes, Loire-Atlantique, Pays de la Loire, France métropolitaine, France - Ancenis, Châteaubriant-Ancenis, Loire-Atlantique, Pays de la Loire, France métropolitaine, 44150, France
  </name>
  <desc>
   44.0 km, 0:37
  </desc>
  <trkseg>
   <trkpt lat="47.218536" lon="-1.554075"/>
   <trkpt lat="47.218427" lon="-1.55398"/>
   <trkpt lat="47.218355" lon="-1.553938"/>
   <trkpt lat="47.218337" lon="-1.553975"/>
   <trkpt lat="47.218143" lon="-1.553968"/>
   <trkpt lat="47.218345" lon="-1.553476"/>
   <trkpt lat="47.217903" lon="-1.553421"/>
   <trkpt lat="47.217333" lon="-1.553389"/>
   <trkpt lat="47.21738" lon="-1.552416"/>
   <trkpt lat="47.217183" lon="-1.55225"/>
   <trkpt lat="47.216706" lon="-1.551836"/>
   <trkpt lat="47.214756" lon="-1.550238"/>
   <trkpt lat="47.214525" lon="-1.55024"/>
   <trkpt lat="47.214364" lon="-1.55024"/>
   <trkpt lat="47.214335" lon="-1.550143"/>
   <trkpt lat="47.214401" lon="-1.549983"/>
   <trkpt lat="47.215347" lon="-1.547803"/>
   <trkpt lat="47.215441" lon="-1.547616"/>
   <trkpt lat="47.215485" lon="-1.547787"/>
   <trkpt lat="47.215777" lon="-1.547168"/>
   <trkpt lat="47.214924" lon="-1.546208"/>
   <trkpt lat="47.214733" lon="-1.546091"/>
   <trkpt lat="47.214651" lon="-1.546014"/>
   <trkpt lat="47.213826" lon="-1.545304"/>
   <trkpt lat="47.21329" lon="-1.54487"/>
   <trkpt lat="47.21323" lon="-1.544817"/>
   <trkpt lat="47.213195" lon="-1.544786"/>
   <trkpt lat="47.211943" lon="-1.543759"/>
   <trkpt lat="47.211785" lon="-1.543751"/>
   <trkpt lat="47.21172" lon="-1.543605"/>
   <trkpt lat="47.211718" lon="-1.543567"/>
   <trkpt lat="47.211794" lon="-1.543374"/>
   <trkpt lat="47.211883" lon="-1.543345"/>
   <trkpt lat="47.212079" lon="-1.542566"/>
   <trkpt lat="47.212058" lon="-1.542522"/>
   <trkpt lat="47.212074" lon="-1.542362"/>
   <trkpt lat="47.212166" lon="-1.542314"/>
   <trkpt lat="47.212658" lon="-1.541764"/>
   <trkpt lat="47.213442" lon="-1.540108"/>
   <trkpt lat="47.213524" lon="-1.539675"/>
   <trkpt lat="47.213516" lon="-1.539587"/>
   <trkpt lat="47.213565" lon="-1.539412"/>
   <trkpt lat="47.213187" lon="-1.537239"/>
   <trkpt lat="47.21313" lon="-1.53719"/>
   <trkpt lat="47.213121" lon="-1.537007"/>
   <trkpt lat="47.213037" lon="-1.536746"/>
   <trkpt lat="47.212985" lon="-1.536673"/>
   <trkpt lat="47.213028" lon="-1.536488"/>
   <trkpt lat="47.213094" lon="-1.536477"/>
   <trkpt lat="47.213187" lon="-1.534501"/>
   <trkpt lat="47.21322" lon="-1.533176"/>
   <trkpt lat="47.213208" lon="-1.532928"/>
   <trkpt lat="47.213599" lon="-1.529777"/>
   <trkpt lat="47.21352" lon="-1.529614"/>
   <trkpt lat="47.213549" lon="-1.529374"/>
   <trkpt lat="47.213601" lon="-1.52929"/>
   <trkpt lat="47.213848" lon="-1.527269"/>
   <trkpt lat="47.213891" lon="-1.527133"/>
   <trkpt lat="47.214444" lon="-1.525283"/>
   <trkpt lat="47.214487" lon="-1.525111"/>
   <trkpt lat="47.215749" lon="-1.521155"/>
   <trkpt lat="47.215802" lon="-1.521012"/>
   <trkpt lat="47.216484" lon="-1.519088"/>
   <trkpt lat="47.21657" lon="-1.518772"/>
   <trkpt lat="47.216602" lon="-1.518664"/>
   <trkpt lat="47.218048" lon="-1.515754"/>
   <trkpt lat="47.218123" lon="-1.515623"/>
   <trkpt lat="47.218259" lon="-1.515588"/>
   <trkpt lat="47.218354" lon="-1.515663"/>
   <trkpt lat="47.219157" lon="-1.516011"/>
   <trkpt lat="47.219943" lon="-1.515468"/>
   <trkpt lat="47.232161" lon="-1.485789"/>
   <trkpt lat="47.232229" lon="-1.485681"/>
   <trkpt lat="47.235333" lon="-1.482751"/>
   <trkpt lat="47.2354" lon="-1.482516"/>
   <trkpt lat="47.235546" lon="-1.482416"/>
   <trkpt lat="47.237493" lon="-1.479355"/>
   <trkpt lat="47.237476" lon="-1.479187"/>
   <trkpt lat="47.237571" lon="-1.47894"/>
   <trkpt lat="47.237679" lon="-1.478875"/>
   <trkpt lat="47.237841" lon="-1.478929"/>
   <trkpt lat="47.237865" lon="-1.478955"/>
   <trkpt lat="47.23968" lon="-1.47769"/>
   <trkpt lat="47.252684" lon="-1.477342"/>
   <trkpt lat="47.255057" lon="-1.47844"/>
   <trkpt lat="47.26823" lon="-1.479836"/>
   <trkpt lat="47.270611" lon="-1.479649"/>
   <trkpt lat="47.273086" lon="-1.479482"/>
   <trkpt lat="47.287258" lon="-1.479302"/>
   <trkpt lat="47.290543" lon="-1.476443"/>
   <trkpt lat="47.291107" lon="-1.471735"/>
   <trkpt lat="47.399341" lon="-1.200555"/>
   <trkpt lat="47.39931" lon="-1.195302"/>
   <trkpt lat="47.399266" lon="-1.192826"/>
   <trkpt lat="47.399277" lon="-1.192706"/>
   <trkpt lat="47.399304" lon="-1.192254"/>
   <trkpt lat="47.399387" lon="-1.191168"/>
   <trkpt lat="47.399341" lon="-1.190568"/>
   <trkpt lat="47.399294" lon="-1.190479"/>
   <trkpt lat="47.396962" lon="-1.190001"/>
   <trkpt lat="47.395567" lon="-1.189791"/>
   <trkpt lat="47.395442" lon="-1.189771"/>
   <trkpt lat="47.394798" lon="-1.189592"/>
   <trkpt lat="47.394688" lon="-1.189555"/>
   <trkpt lat="47.391687" lon="-1.188792"/>
   <trkpt lat="47.391615" lon="-1.18885"/>
   <trkpt lat="47.391446" lon="-1.188684"/>
   <trkpt lat="47.391328" lon="-1.188495"/>
   <trkpt lat="47.390855" lon="-1.18821"/>
   <trkpt lat="47.390459" lon="-1.188124"/>
   <trkpt lat="47.390307" lon="-1.188215"/>
   <trkpt lat="47.39019" lon="-1.18816"/>
   <trkpt lat="47.390099" lon="-1.187937"/>
   <trkpt lat="47.390099" lon="-1.18787"/>
   <trkpt lat="47.386784" lon="-1.185549"/>
   <trkpt lat="47.386387" lon="-1.185516"/>
   <trkpt lat="47.386278" lon="-1.185596"/>
   <trkpt lat="47.386194" lon="-1.185538"/>
   <trkpt lat="47.386165" lon="-1.185462"/>
   <trkpt lat="47.385743" lon="-1.185042"/>
   <trkpt lat="47.383247" lon="-1.183994"/>
   <trkpt lat="47.382652" lon="-1.183919"/>
   <trkpt lat="47.382623" lon="-1.183975"/>
   <trkpt lat="47.382522" lon="-1.184013"/>
   <trkpt lat="47.382465" lon="-1.18397"/>
   <trkpt lat="47.382435" lon="-1.18385"/>
   <trkpt lat="47.37964" lon="-1.182634"/>
   <trkpt lat="47.378879" lon="-1.182151"/>
   <trkpt lat="47.377554" lon="-1.181295"/>
   <trkpt lat="47.377402" lon="-1.181282"/>
   <trkpt lat="47.377354" lon="-1.181357"/>
   <trkpt lat="47.377255" lon="-1.181394"/>
   <trkpt lat="47.377135" lon="-1.181101"/>
   <trkpt lat="47.376946" lon="-1.180899"/>
   <trkpt lat="47.375527" lon="-1.179969"/>
   <trkpt lat="47.373767" lon="-1.178955"/>
   <trkpt lat="47.373402" lon="-1.178983"/>
   <trkpt lat="47.373302" lon="-1.179059"/>
   <trkpt lat="47.373222" lon="-1.178978"/>
   <trkpt lat="47.372174" lon="-1.178905"/>
   <trkpt lat="47.372112" lon="-1.178948"/>
   <trkpt lat="47.372092" lon="-1.178902"/>
   <trkpt lat="47.371988" lon="-1.178904"/>
   <trkpt lat="47.3704" lon="-1.178883"/>
   <trkpt lat="47.370202" lon="-1.178866"/>
   <trkpt lat="47.369961" lon="-1.178839"/>
   <trkpt lat="47.369467" lon="-1.178797"/>
   <trkpt lat="47.369026" lon="-1.178756"/>
   <trkpt lat="47.368278" lon="-1.178584"/>
   <trkpt lat="47.366732" lon="-1.178582"/>
   <trkpt lat="47.3667" lon="-1.178583"/>
   <trkpt lat="47.366514" lon="-1.178598"/>
   <trkpt lat="47.365991" lon="-1.1786"/>
   <trkpt lat="47.365403" lon="-1.178805"/>
   <trkpt lat="47.364949" lon="-1.178912"/>
   <trkpt lat="47.364547" lon="-1.178981"/>
   <trkpt lat="47.364474" lon="-1.17934"/>
   <trkpt lat="47.364424" lon="-1.17992"/>
   <trkpt lat="47.364136" lon="-1.180728"/>
   <trkpt lat="47.36416" lon="-1.180945"/>
   <trkpt lat="47.364268" lon="-1.181819"/>
   <trkpt lat="47.364763" lon="-1.18192"/>
  </trkseg>
 </trk>
 <trk>
  <name>
   Ancenis, Châteaubriant-Ancenis, Loire-Atlantique, Pays de la Loire, France métropolitaine, 44150, France - Angers, Maine-et-Loire, Pays de la Loire, France métropolitaine, France
  </name>
  <desc>
   57.0 km, 0:41
  </desc>
  <trkseg>
   <trkpt lat="47.364763" lon="-1.18192"/>
   <trkpt lat="47.364848" lon="-1.18196"/>
   <trkpt lat="47.365275" lon="-1.182104"/>
   <trkpt lat="47.365965" lon="-1.182286"/>
   <trkpt lat="47.36612" lon="-1.18113"/>
   <trkpt lat="47.366403" lon="-1.179826"/>
   <trkpt lat="47.366732" lon="-1.178582"/>
   <trkpt lat="47.368278" lon="-1.178584"/>
   <trkpt lat="47.369026" lon="-1.178756"/>
   <trkpt lat="47.369467" lon="-1.178797"/>
   <trkpt lat="47.369961" lon="-1.178839"/>
   <trkpt lat="47.370202" lon="-1.178866"/>
   <trkpt lat="47.3704" lon="-1.178883"/>
   <trkpt lat="47.371988" lon="-1.178904"/>
   <trkpt lat="47.372092" lon="-1.178902"/>
   <trkpt lat="47.37213" lon="-1.178835"/>
   <trkpt lat="47.372174" lon="-1.178905"/>
   <trkpt lat="47.373149" lon="-1.178876"/>
   <trkpt lat="47.373211" lon="-1.178881"/>
   <trkpt lat="47.373272" lon="-1.178766"/>
   <trkpt lat="47.373372" lon="-1.17878"/>
   <trkpt lat="47.373415" lon="-1.178882"/>
   <trkpt lat="47.373767" lon="-1.178955"/>
   <trkpt lat="47.375527" lon="-1.179969"/>
   <trkpt lat="47.376946" lon="-1.180899"/>
   <trkpt lat="47.377202" lon="-1.180991"/>
   <trkpt lat="47.377317" lon="-1.180973"/>
   <trkpt lat="47.377418" lon="-1.18115"/>
   <trkpt lat="47.378879" lon="-1.182151"/>
   <trkpt lat="47.37964" lon="-1.182634"/>
   <trkpt lat="47.382469" lon="-1.183726"/>
   <trkpt lat="47.38252" lon="-1.183687"/>
   <trkpt lat="47.382627" lon="-1.183736"/>
   <trkpt lat="47.382649" lon="-1.183773"/>
   <trkpt lat="47.383247" lon="-1.183994"/>
   <trkpt lat="47.385743" lon="-1.185042"/>
   <trkpt lat="47.386187" lon="-1.185301"/>
   <trkpt lat="47.386324" lon="-1.18524"/>
   <trkpt lat="47.386395" lon="-1.185331"/>
   <trkpt lat="47.386784" lon="-1.185549"/>
   <trkpt lat="47.390184" lon="-1.18765"/>
   <trkpt lat="47.390236" lon="-1.187609"/>
   <trkpt lat="47.390418" lon="-1.187636"/>
   <trkpt lat="47.390457" lon="-1.187677"/>
   <trkpt lat="47.390521" lon="-1.187884"/>
   <trkpt lat="47.390855" lon="-1.18821"/>
   <trkpt lat="47.391328" lon="-1.188495"/>
   <trkpt lat="47.391505" lon="-1.18847"/>
   <trkpt lat="47.391608" lon="-1.188436"/>
   <trkpt lat="47.391718" lon="-1.188566"/>
   <trkpt lat="47.394176" lon="-1.18923"/>
   <trkpt lat="47.394707" lon="-1.189419"/>
   <trkpt lat="47.394816" lon="-1.189455"/>
   <trkpt lat="47.396101" lon="-1.189755"/>
   <trkpt lat="47.396578" lon="-1.189826"/>
   <trkpt lat="47.398083" lon="-1.190038"/>
   <trkpt lat="47.39932" lon="-1.190194"/>
   <trkpt lat="47.399436" lon="-1.190105"/>
   <trkpt lat="47.399616" lon="-1.190257"/>
   <trkpt lat="47.399625" lon="-1.190297"/>
   <trkpt lat="47.399598" lon="-1.190518"/>
   <trkpt lat="47.399572" lon="-1.190561"/>
   <trkpt lat="47.399396" lon="-1.192017"/>
   <trkpt lat="47.399366" lon="-1.192722"/>
   <trkpt lat="47.399355" lon="-1.192841"/>
   <trkpt lat="47.39927" lon="-1.194329"/>
   <trkpt lat="47.399938" lon="-1.194827"/>
   <trkpt lat="47.401803" lon="-1.191068"/>
   <trkpt lat="47.434482" lon="-0.816724"/>
   <trkpt lat="47.433855" lon="-0.809441"/>
   <trkpt lat="47.46242" lon="-0.695047"/>
   <trkpt lat="47.467222" lon="-0.677305"/>
   <trkpt lat="47.466628" lon="-0.674247"/>
   <trkpt lat="47.462466" lon="-0.64317"/>
   <trkpt lat="47.4658" lon="-0.631566"/>
   <trkpt lat="47.466724" lon="-0.628554"/>
   <trkpt lat="47.46786" lon="-0.624756"/>
   <trkpt lat="47.469056" lon="-0.620722"/>
   <trkpt lat="47.470005" lon="-0.617478"/>
   <trkpt lat="47.469578" lon="-0.612166"/>
   <trkpt lat="47.468996" lon="-0.605593"/>
   <trkpt lat="47.469353" lon="-0.597749"/>
   <trkpt lat="47.469475" lon="-0.594958"/>
   <trkpt lat="47.468084" lon="-0.585639"/>
   <trkpt lat="47.464676" lon="-0.574428"/>
   <trkpt lat="47.465802" lon="-0.568425"/>
   <trkpt lat="47.46848" lon="-0.564903"/>
   <trkpt lat="47.469906" lon="-0.562375"/>
   <trkpt lat="47.470104" lon="-0.561996"/>
   <trkpt lat="47.471074" lon="-0.560347"/>
   <trkpt lat="47.471585" lon="-0.559436"/>
   <trkpt lat="47.472442" lon="-0.558075"/>
   <trkpt lat="47.474047" lon="-0.556018"/>
   <trkpt lat="47.475157" lon="-0.555216"/>
   <trkpt lat="47.476197" lon="-0.554405"/>
   <trkpt lat="47.476813" lon="-0.553653"/>
   <trkpt lat="47.476842" lon="-0.553634"/>
   <trkpt lat="47.477151" lon="-0.553118"/>
   <trkpt lat="47.476517" lon="-0.551532"/>
   <trkpt lat="47.476224" lon="-0.550865"/>
   <trkpt lat="47.47594" lon="-0.550269"/>
   <trkpt lat="47.475462" lon="-0.549161"/>
   <trkpt lat="47.475096" lon="-0.549804"/>
   <trkpt lat="47.475076" lon="-0.549856"/>
   <trkpt lat="47.474792" lon="-0.550535"/>
   <trkpt lat="47.474586" lon="-0.551368"/>
   <trkpt lat="47.474561" lon="-0.55151"/>
   <trkpt lat="47.474384" lon="-0.552383"/>
   <trkpt lat="47.473949" lon="-0.551608"/>
  </trkseg>
 </trk>
</gpx>

Ce contenu xml peut ensuite être chargé dans n'importe quelle application ou site internet utilisant ce genre de fichier.

Etiquettes: