API de Strava

De wikijoan
Salta a la navegació Salta a la cerca

Introducció

M'he donat d'alta a Strava (per registrar activitats de córrer i bicicleta, que es comunica amb els dispositius GPS). Sense fer la subscripció està molt limitat, i a més, en el cas de ciclisme, no distingeix entre carretera i MTB. Sembla que està més orientat a la bici de carretera. M'interessa el concepte de segments, que són trossos de ruta (pujades) en què es publica les estadístiques que fa la gent.

No sóc ni vull ser premium. Anem a mirar la API, i a veure si amb la API es pot accedir a informació que només estaria disponible per als comptes premium.

La API de Strava (Strava V3 API)

The Strava V3 API is a publicly available interface that allows developers to access Strava data.

The Strava REST API includes data on athletes, segments, routes, clubs, and gear. It is free to use. The Strava API does not allow you to get data for all Strava public athletes, as you can see on our website.

To get data on athletes, you will have to make an application and request that athletes sign in with Strava, and grant your application certain permissions using OAuth 2.0. You can get data on yourself without authentication for testing purposes.

Strava API usage is limited on a per-application basis using both a 15-minute and daily request limit. The default rate limit allows 100 requests every 15 minutes, with up to 1,000 requests per day.

Nom aplicació: Prova Starva API
Categoria: Motivación social
Authorization Callback Domain: localhost

ID Cliente: 63026
secreto cliente: 41aa9abcb8afb983dbbba166c2ed57f9d06bc3ab
token acceso: 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2 (lectura)
(caduca en unes 24 hores)
token actualització: 6c271fe343601ca585767d2df5d1d1cf1f3676bd (lectura)
Límites de frecuencia: 100 solicitudes cada 15 minutos, 1000 diario

i ara ja puc fer una request:

$ curl -X GET https://www.strava.com/api/v3/athlete -H 'Authorization: Bearer 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2'

Resposta:

{"id":80767812,"username":null,"resource_state":2,"firstname":"Joan","lastname":"Quintana","bio":null,"city":"Barcelona","state":"Barcelona","country":"Spain","sex":"M","premium":false,"summit":false,"created_at":"2021-03-13T17:18:45Z","updated_at":"2021-03-13T17:37:13Z","badge_type_id":0,"weight":0.0,"profile_medium":"https://lh3.googleusercontent.com/a-/AOh14GhAdjE9IX9kZwVGkjeGdhu7winX-GvwDh_yjC8l=s96-c","profile":"https://lh3.googleusercontent.com/a-/AOh14GhAdjE9IX9kZwVGkjeGdhu7winX-GvwDh_yjC8l=s96-c","friend":null,"follower":null}

L'objectiu és accedir als segments de Strava, accedir a la ruta dels segments, i accedir a informació que des de la web no pots fer a no ser que siguis Premium.

API documentation:

Explorar segments

Explorar segments (retorna només 10 segments com a molt):

$ curl -X GET 'https://www.strava.com/api/v3/segments/explore?bounds=41.4022,2.0697,41.4637,2.1241&activity_type=riding&min_cat=0&max_cat=5' -H 'Authorization: Bearer 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2'

min_cat i max_cat són opcionals, i no tinc clar quin és el rang. 0 és el màxim pendent.

bounds: required array[Float], in query The latitude and longitude for two points describing a rectangular boundary for the search: [southwest corner latitutde, southwest corner longitude, northeast corner latitude, northeast corner longitude]

$ curl -X GET 'https://www.strava.com/api/v3/segments/explore?bounds=41.4022,2.0697,41.4637,2.1241&activity_type=riding' -H 'Authorization: Bearer 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2'

Resultat:

{"segments":[

{"id":8574585,"resource_state":2,"name":"TIBIDABO HILL CLIMB 2014","climb_category":2,"climb_category_desc":"3","avg_grade":5.7,"start_latlng":[41.404361,2.116831],"end_latlng":[41.418897,2.116763],"elev_difference":291.4,"distance":5096.7,
"points":"..."
,"starred":false,"elevation_profile":"https://d3o5xota0a1fcr.cloudfront.net/v6/charts/YLITWWQFXYKHWPYBZG35IAAMTKDUFOTAN5P7YYCGSVKEH35IZUQW2DCPTOCXRVHJI3J3LDTYB2LSBXZNXP5I2===","local_legend_enabled":true},

{"id":6303892,"resource_state":2,"name":"Subida final Tibi Dabo","climb_category":0,"climb_category_desc":"NC","avg_grade":13.0,"start_latlng":[41.42064,2.119151],"end_latlng":[41.421265,2.119292],"elev_difference":22.2,"distance":171.1,
"points":"...",
"starred":false,"elevation_profile":"https://d3o5xota0a1fcr.cloudfront.net/v6/charts/66F5P7SRMEYI4M2HZMIUQ7AFPJ62IUCUXWIMPSUKFQ54E5METI7AK2FKLQYY74PEDINXBUDSC33Y43HP2C5A====","local_legend_enabled":true},

...
]}

Accedim a la info dels segments:

$ curl -X GET https://www.strava.com/api/v3/segments/229781 -H 'Authorization: Bearer 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2'

Resultat:

{"id":229781,"resource_state":3,"name":"Hawk Hill","activity_type":"Ride","distance":2684.82,"average_grade":5.8,"maximum_grade":10.9,"elevation_high":247.2,"elevation_low":92.0,"start_latlng":[37.833112,-122.483436],"end_latlng":[37.828072,-122.498139],"elevation_profile":"https://d3o5xota0a1fcr.cloudfront.net/v6/charts/KO5P7GCFLK5P5NF5GNUX3D6IVFLIEYRYD6JRBEGMXHOCPENJUQZXD5IIEJOYINQE2HX3XLZMYRTF5GHG5JLQ====","start_latitude":37.833112,"start_longitude":-122.483436,"end_latitude":37.828072,"end_longitude":-122.498139,"climb_category":1,"city":"San Francisco","state":"CA","country":"United States","private":false,"hazardous":false,"starred":false,"created_at":"2009-09-21T20:29:41Z","updated_at":"2021-03-13T09:01:33Z","total_elevation_gain":155.2,"map":{"id":"s229781","polyline":"}g|eFnpqjVl@En@Md@HbAd@d@^h@Xx@VbARjBDh@OPQf@w@d@k@XKXDFPF\\CbGT`AV`@v@|@NTNb@?XOb@cAxAWLuE@eAFMBoAv@eBt@q@b@}@tAeAt@i@dAC`AFZj@dBA~@Yh@MbAVn@b@b@\\d@Ef@Qd@_@d@eB|@c@h@YfBI|AMpA?VF\\\\t@f@t@h@j@|@b@hCb@b@XTd@Bl@GtA?jAL`ALp@Tr@RXd@Rx@Pn@^Zh@Tx@Zf@`@FTCzDy@f@Yx@m@n@Op@VJr@","resource_state":3},"effort_count":556805,"athlete_count":49100,"star_count":5022,"athlete_segment_stats":{"pr_elapsed_time":null,"pr_date":null,"pr_activity_id":null,"effort_count":0},"xoms":{"kom":"5:37","qom":"6:42","destination":{"href":"strava://segments/229781/leaderboard","type":"overall","name":"All-Time"}},"local_legend":{"athlete_id":54312907,"title":"Dalton Nonweiler","profile":"https://dgalywyr863hv.cloudfront.net/pictures/athletes/54312907/14907176/5/large.jpg","effort_description":"86 efforts in the last 90 days","effort_count":"86","effort_counts":{"overall":"86 efforts","female":"41 efforts"},"destination":"strava://segments/229781/local_legend?categories%5B%5D=overall"}}

De moment, només treballo amb el terminal. Quan tingui fins a quin punt puc arribar amb la API, podré programar clients python. Per exemple:

Exportar rutes a GPX

Export Route GPX (getRouteAsGPX)

$ curl -X GET 'https://www.strava.com/api/v3/routes/6303892/export_gpx' -H 'Authorization: Bearer 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2' > ruta.gpx

No he de confondre les rutes amb els segments.

Els segments no es poden exportar a GPX. Però sí que es pot recuperar la informació del segment, i tinc el camp map.polyline que segurament conté la informació de la ruta

$ curl -X GET 'https://www.strava.com/api/v3/segments/8574585' -H 'Authorization: Bearer 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2' > segment.txt

{"id":8574585,"resource_state":3,"name":"TIBIDABO HILL CLIMB 2014","activity_type":"Ride","distance":5096.7,"average_grade":5.7,"maximum_grade":15.8,"elevation_high":439.4,"elevation_low":148.0,"start_latlng":[41.404361,2.116831],"end_latlng":[41.418897,2.116763],"elevation_profile":"https://d3o5xota0a1fcr.cloudfront.net/v6/charts/YLITWWQFXYKHWPYBZG35IAAMTKDUFOTAN5P7YYCGSVKEH35IZUQW2DCPTOCXRVHJI3J3LDTYB2LSBXZNXP5I2===","start_latitude":41.404361,"start_longitude":2.116831,"end_latitude":41.418897,"end_longitude":2.116763,"climb_category":2,"city":"Barcelona","state":"Catalunya","country":"Spain","private":false,"hazardous":false,"starred":false,"created_at":"2014-11-29T14:02:30Z","updated_at":"2021-03-13T09:02:59Z","total_elevation_gain":291.4,
"map":
	{"id":"s8574585",
	"polyline":"gxu{Fem|Kc@fAq@fAoApAMR[ZMXw@v@a@VQZi@j@sAhAk@hA_@f@oDxCiAhA_@j@a@~@{@pCC`@EFD^H`B?`@BNNZV@JGDMEqA@q@H]NOFSLo@t@eB^i@d@i@t@m@n@Yz@EHBR\\`AdDFdEJ`@RNHIVGf@ATH`At@VXDl@GJU@WY[e@YSKC_@GgA@YMKMc@eBYeBSWg@AUTSVa@|@[tAAPDb@Nr@@TCb@[bACd@BNJ^Xh@N^BNB`@Nn@DJTNZ\\Rn@?\\c@zAA^B\\JZHHh@NZDVHTRHJBNAb@I|@B\\Th@PTVf@F`@Cl@Sj@WJ{Ae@{@OKBSPOr@IvA[z@UTw@JWE_@]QUUKKCu@Hs@NMEIIi@kAOUGE]OUMGIGY?y@XiB@]E]U[SGU?c@XcA`Aw@|@i@~@WbASPK?IC_Au@q@_@SAI@g@Lo@XK?YB[MYOQSQYi@Y_@AK@CDg@X]Bg@KUMi@e@[k@GU@MHQb@a@DIFU@WIYg@u@]y@IqAP{ABq@Is@e@iB}@wAw@oBk@aAa@g@g@w@Km@Q{AYkB_AmCc@eB?]H]NWxAiBZq@JYFm@@m@C[G]OWa@k@eAu@o@k@iBkCm@k@SKc@CK@]LS@e@]]]E@GDEH@`@PZJd@CHEFI?OSMe@Uk@",
	"resource_state":3},
"effort_count":87425,"athlete_count":9629,"star_count":674,"athlete_segment_stats":{"pr_elapsed_time":null,"pr_date":null,"pr_activity_id":null,"effort_count":0},"xoms":{"kom":"11:19","qom":"15:05","destination":{"href":"strava://segments/8574585/leaderboard","type":"overall","name":"All-Time"}},"local_legend":{"athlete_id":6034662,"title":"Javier Solera","profile":"https://dgalywyr863hv.cloudfront.net/pictures/athletes/6034662/4197425/1/large.jpg","effort_description":"29 efforts in the last 90 days","effort_count":"29","effort_counts":{"overall":"29 efforts","female":"19 efforts"},"destination":"strava://segments/8574585/local_legend?categories%5B%5D=overall"}}

Veiem que la polilínia és una cadena de text (conjunt de bytes), que porta codificat les coordenades de la polilínia.

This string turns out to be an encoded list of coordinates, encoded using Google’s Encoded Polyline Algorithm Format. It can easily be decoded by using, for example, the PyPI module polyline:

>> polyline.decode(summary_polyline)
[(52.1041, 5.10558), (52.10533, 5.10595), (52.10605, 5.10692), (52.10623, 5.10707), (52.10632, 5.10721), (52.10641, 5.1075), (52.10645, 5.10752), (52.1074, 5.10679), (52.10853, 5.10611), ... ]
$ pip3 install polyline

$ python3
>> import polyline
>> #polyline.decode(summary_polyline)
>> polyline.decode("gxu{Fem|Kc@fAq@fAoApAMR[ZMXw@v@a@VQZi@j@sAhAk@hA_@f@oDxCiAhA_@j@a@~@{@pCC`@EFD^H`B?`@BNNZV@JGDMEqA@q@H]NOFSLo@t@eB^i@d@i@t@m@n@Yz@EHBR\\`AdDFdEJ`@RNHIVGf@ATH`At@VXDl@GJU@WY[e@YSKC_@GgA@YMKMc@eBYeBSWg@AUTSVa@|@[tAAPDb@Nr@@TCb@[bACd@BNJ^Xh@N^BNB`@Nn@DJTNZ\\Rn@?\\c@zAA^B\\JZHHh@NZDVHTRHJBNAb@I|@B\\Th@PTVf@F`@Cl@Sj@WJ{Ae@{@OKBSPOr@IvA[z@UTw@JWE_@]QUUKKCu@Hs@NMEIIi@kAOUGE]OUMGIGY?y@XiB@]E]U[SGU?c@XcA`Aw@|@i@~@WbASPK?IC_Au@q@_@SAI@g@Lo@XK?YB[MYOQSQYi@Y_@AK@CDg@X]Bg@KUMi@e@[k@GU@MHQb@a@DIFU@WIYg@u@]y@IqAP{ABq@Is@e@iB}@wAw@oBk@aAa@g@g@w@Km@Q{AYkB_AmCc@eB?]H]NWxAiBZq@JYFm@@m@C[G]OWa@k@eAu@o@k@iBkCm@k@SKc@CK@]LS@e@]]]E@GDEH@`@PZJd@CHEFI?OSMe@Uk@")

[(41.40436, 2.11683), (41.40454, 2.11647), (41.40479, 2.11611), (41.40519, 2.1157), (41.40526, 2.1156), (41.4054, 2.11546), (41.40547, 2.11533), (41.40575, 2.11505), (41.40592, 2.11493), (41.40601, 2.11479), (41.40622, 2.11457), (41.40664, 2.1142), (41.40686, 2.11383), (41.40702, 2.11363), (41.4079, 2.11286), (41.40827, 2.11249), (41.40843, 2.11227), (41.4086, 2.11195), (41.4089, 2.11122), (41.40892, 2.11105), (41.40895, 2.11101), (41.40892, 2.11085), (41.40887, 2.11036), (41.40887, 2.11019), (41.40885, 2.11011), (41.40877, 2.10997), (41.40865, 2.10996), (41.40859, 2.11), (41.40856, 2.11007), (41.40859, 2.11048), (41.40858, 2.11073), (41.40853, 2.11088), (41.40845, 2.11096), (41.40841, 2.11106), (41.40834, 2.1113), (41.40807, 2.11181), (41.40791, 2.11202), (41.40772, 2.11223), (41.40745, 2.11246), (41.40721, 2.11259), (41.40691, 2.11262), (41.40686, 2.1126), (41.40676, 2.11245), (41.40643, 2.11162), (41.40639, 2.11063), (41.40633, 2.11046), (41.40623, 2.11038), (41.40618, 2.11043), (41.40606, 2.11047), (41.40586, 2.11048), (41.40575, 2.11043), (41.40542, 2.11016), (41.4053, 2.11003), (41.40527, 2.1098), (41.40531, 2.10974), (41.40542, 2.10973), (41.40554, 2.10986), (41.40568, 2.11005), (41.40581, 2.11015), (41.40587, 2.11017), (41.40603, 2.11021), (41.40639, 2.1102), (41.40652, 2.11027), (41.40658, 2.11034), (41.40676, 2.11085), (41.40689, 2.11136), (41.40699, 2.11148), (41.40719, 2.11149), (41.4073, 2.11138), (41.4074, 2.11126), (41.40757, 2.11095), (41.40771, 2.11052), (41.40772, 2.11043), (41.40769, 2.11025), (41.40761, 2.10999), (41.4076, 2.10988), (41.40762, 2.1097), (41.40776, 2.10936), (41.40778, 2.10917), (41.40776, 2.10909), (41.4077, 2.10893), (41.40757, 2.10872), (41.40749, 2.10856), (41.40747, 2.10848), (41.40745, 2.10831), (41.40737, 2.10807), (41.40734, 2.10801), (41.40723, 2.10793), (41.40709, 2.10778), (41.40699, 2.10754), (41.40699, 2.10739), (41.40717, 2.10693), (41.40718, 2.10677), (41.40716, 2.10662), (41.4071, 2.10648), (41.40705, 2.10643), (41.40684, 2.10635), (41.4067, 2.10632), (41.40658, 2.10627), (41.40647, 2.10617), (41.40642, 2.10611), (41.4064, 2.10603), (41.40641, 2.10585), (41.40646, 2.10554), (41.40644, 2.10539), (41.40633, 2.10518), (41.40624, 2.10507), (41.40612, 2.10487), (41.40608, 2.1047), (41.4061, 2.10447), (41.4062, 2.10425), (41.40632, 2.10419), (41.40678, 2.10438), (41.40708, 2.10446), (41.40714, 2.10444), (41.40724, 2.10435), (41.40732, 2.10409), (41.40737, 2.10365), (41.40751, 2.10335), (41.40762, 2.10324), (41.4079, 2.10318), (41.40802, 2.10321), (41.40818, 2.10336), (41.40827, 2.10347), (41.40838, 2.10353), (41.40844, 2.10355), (41.40871, 2.1035), (41.40897, 2.10342), (41.40904, 2.10345), (41.40909, 2.1035), (41.4093, 2.10388), (41.40938, 2.10399), (41.40942, 2.10402), (41.40957, 2.1041), (41.40968, 2.10417), (41.40972, 2.10422), (41.40976, 2.10435), (41.40976, 2.10464), (41.40963, 2.10517), (41.40962, 2.10532), (41.40965, 2.10547), (41.40976, 2.10561), (41.40986, 2.10565), (41.40997, 2.10565), (41.41015, 2.10552), (41.41049, 2.10519), (41.41077, 2.10488), (41.41098, 2.10456), (41.4111, 2.10422), (41.4112, 2.10413), (41.41126, 2.10413), (41.41131, 2.10415), (41.41163, 2.10442), (41.41188, 2.10458), (41.41198, 2.10459), (41.41203, 2.10458), (41.41223, 2.10451), (41.41247, 2.10438), (41.41253, 2.10438), (41.41266, 2.10436), (41.4128, 2.10443), (41.41293, 2.10451), (41.41302, 2.10461), (41.41311, 2.10474), (41.41332, 2.10487), (41.41348, 2.10488), (41.41354, 2.10487), (41.41356, 2.10484), (41.41376, 2.10471), (41.41391, 2.10469), (41.41411, 2.10475), (41.41422, 2.10482), (41.41443, 2.10501), (41.41457, 2.10523), (41.41461, 2.10534), (41.4146, 2.10541), (41.41455, 2.1055), (41.41437, 2.10567), (41.41434, 2.10572), (41.4143, 2.10583), (41.41429, 2.10595), (41.41434, 2.10608), (41.41454, 2.10635), (41.41469, 2.10664), (41.41474, 2.10705), (41.41465, 2.10751), (41.41463, 2.10776), (41.41468, 2.10802), (41.41487, 2.10855), (41.41518, 2.10899), (41.41546, 2.10955), (41.41568, 2.10988), (41.41585, 2.11008), (41.41605, 2.11036), (41.41611, 2.11059), (41.4162, 2.11105), (41.41633, 2.11159), (41.41665, 2.1123), (41.41683, 2.11281), (41.41683, 2.11296), (41.41678, 2.11311), (41.4167, 2.11323), (41.41625, 2.11376), (41.41611, 2.11401), (41.41605, 2.11414), (41.41601, 2.11437), (41.416, 2.1146), (41.41602, 2.11474), (41.41606, 2.11489), (41.41614, 2.11501), (41.41631, 2.11523), (41.41666, 2.1155), (41.4169, 2.11572), (41.41743, 2.11642), (41.41766, 2.11664), (41.41776, 2.1167), (41.41794, 2.11672), (41.418, 2.11671), (41.41815, 2.11664), (41.41825, 2.11663), (41.41844, 2.11678), (41.41859, 2.11693), (41.41862, 2.11692), (41.41866, 2.11689), (41.41869, 2.11684), (41.41868, 2.11667), (41.41859, 2.11653), (41.41853, 2.11634), (41.41855, 2.11629), (41.41858, 2.11625), (41.41863, 2.11625), (41.41871, 2.11635), (41.41878, 2.11654), (41.41889, 2.11676)]

ja tinc l'array de punts que correspon al segment.

Ara podria fer un petit script per convertir aquest array de punts a un arxiu gpx.

Rankings del segment

Donat un segment, trobar el ranking del segment.

curl -X GET 'https://www.strava.com/api/v3/segments/23430539/leaderboard?club_id=318793&page=1&per_page=100' -H 'Authorization: Bearer 6617d0ef6d40fc8b34a643673b673d7a0c5e6c2' > segment.txt
{"message":"Forbidden","errors":[]}

sembla ser que no tinc permisos per fer això

efectivament, sense subscripció no està disponible.

Conclusió

Sense la subscripció, amb la API puc accedir a més informació. De totes maneres, si vull veure tota la informació (en concret les taules de leaderboard, necessito la subscripció, uns 5e/mes).

És una bona API per fer un Projecte de final de curs. Potser hi ha algun alumne amb la subscripció de Strava. Els ho demano en el Classroom.


creat per Joan Quintana Compte, març 2021