<jupyter_start><jupyter_text>2A.eco - Exercice API SNCFManipulation d'une [API REST](https://fr.wikipedia.org/wiki/Representational_state_transfer), celle de la SNCF est prise comme exemple. Exercices.<jupyter_code>from jyquickhelper import add_notebook_menu
add_notebook_menu()<jupyter_output><empty_output><jupyter_text>API signifie Application Programming Interface. Le mot le plus important est “interface”, et c’est le mot le plus simple, car nous utilisons tous des interfaces au quotidien. Par exemple une télécommande de la TV. Vous avez un groupe de boutons et interrupteurs qui vous permettent de faire différentes opérations. Vous savez quel bouton correspond à quelle action. Par exemple, vous ne pouvez pas allumer votre TV avec le bouton de volume. Pour que cela marche, vous devez respecter l'interface et interagir avec elle de la façon qui a été prévue lors de sa conception.Une API est une interface pour les applications. Une API vient presque toujours avec une documentation. La documentation du code est un texte écrit par les développeurs qui rend plus facile l’utilisation du code de cette API. Elle explique comment le code fonctionne, pourquoi il a été écrit d’une certaine façon et pas d’une autre, comment contribuer au projet, et bien plus encore. Lire la documentation est essentiel pour bien intégrer l’API d’une autre plateforme. Et chaque API a sa propre logique de fonctionnement. Ici, vous allez découvrir l'API de la SNCF qui donne accès à de nombreuses informations liées à la mobilité. Ici, comme souvent, il s'agit d'une API [REST](Comment fonctionne une API sans Python ? Ici, on a une api  classique). REST signifie “Representational State Transfer”. Les API REST sont basées sur HTTP, qui signifie Hypertext Transfer Protocol. C’est le protocole au coeur du web. Il définit la communication entre les différentes parties du web. L’échange est basé sur des requêtes client et serveur. Le principe du client-serveur définit les deux entités qui interagissent dans une API REST : un client et un serveur, les mêmes entités qui communiquent sur le web. Un client envoie une requête, et le serveur renvoie une réponse. Les réponses du serveur pour les API REST peuvent être délivrées dans de multiples formats. JSON (JavaScript Object Notation) est souvent utilisé, mais XML, CSV, ou même RSS sont aussi valables. Ici (comme souvent), il s'agit d'un format JSON.  Partie 0 - modules recommandés et connexion à l'API Il vous faudra sûrement les modules suivant : - [requests](http://docs.python-requests.org/en/master/)- [datetime](https://docs.python.org/3/library/datetime.html)- [pandas](http://pandas.pydata.org/)- [matplotlib](http://matplotlib.org/)Créer un login pour vous connecter à l'API de la SNCF https://data.sncf.com/api.Il est possible de stocker une clé de façon cachée sur votre ordinateur avec le module [keyring](http://pythonhosted.org/keyring/).<jupyter_code>import os
from pyquickhelper.loghelper import get_password
key = get_password("sncf", "ensae_teaching_cs,key")<jupyter_output><empty_output><jupyter_text>Requêter une API sans Python  Pour faire une requếté via l'API SNCF, il "suffit" de passer les bons paramètres dans l'url, au format indiqué par la documentation. Comme souvent, c'est un système clé/valeur : url?key1=value1&key2=value2. Pour savoir quelles clés et quelles valeurs indiquer : il faut lire la [Documentation](http://doc.navitia.io/) (la SNCF n'a pas fait sa propre documentation, mais il suffit de remplacer navitia.io par sncf.com dans les exemples donnés).En réponse à la requête, le serveur renvoie un document JSON (JavaScript Object Notation). Cela ressemble à un dictionnaire Python.Exemple, aller à : https://api.sncf.com/v1/coverage/sncf/stop_areas (si cela ne fonctionne pas, indiquez votre token de la manière suivante :  https://{token}@api.sncf.com/v1/coverage/sncf/stop_areas. Exemple : [stop_areas.json](https://raw.githubusercontent.com/sdpython/ensae_teaching_cs/master/_doc/notebooks/td2a_eco/stop_areas.json).Enregistrez le résultat dans un fichier texte (au même endroit où vous avez ouvert votre notebook tant qu'à faire), et ajoutez l'extension .json  Manipuler un fichier json en Python  Nous exliquons ci-dessous comment importer et exporter un fichier json en Python.<jupyter_code>import json

with open('stop_areas.json','r') as f:
    data=json.load(f)
data<jupyter_output><empty_output><jupyter_text>Ce n'est pas très lisible. Utilisez le module pretty print.<jupyter_code>import pprint

pprint.pprint(data)<jupyter_output>{'disruptions': [],
 'links': [{'href': 'https://api.sncf.com/v1/coverage/sncf/stop_areas/{stop_areas.id}',
            'rel': 'stop_areas',
            'templated': True,
            'type': 'stop_areas'},
           {'href': 'https://api.sncf.com/v1/coverage/sncf/stop_areas/{stop_areas.id}/route_schedules',
            'rel': 'route_schedules',
            'templated': True,
            'type': 'route_schedules'},
           {'href': 'https://api.sncf.com/v1/coverage/sncf/stop_areas/{stop_areas.id}/stop_schedules',
            'rel': 'stop_schedules',
            'templated': True,
            'type': 'stop_schedules'},
           {'href': 'https://api.sncf.com/v1/coverage/sncf/stop_areas/{stop_areas.id}/arrivals',
            'rel': 'arrivals',
            'templated': True,
            'type': 'arrivals'},
           {'href': 'https://api.sncf.com/v1/coverage/sncf/stop_areas/{stop_areas.id}/departures',
            'rel': 'departures',
            'templated': True,
            'ty[...]<jupyter_text>Avec du javascript.<jupyter_code>from jyquickhelper import JSONJS
JSONJS(data)<jupyter_output><empty_output><jupyter_text>Pour exporter des données en json<jupyter_code>with open('./data_export.json','w') as f:
    json.dump(data,f)<jupyter_output><empty_output><jupyter_text>Il est aussi possible de passer par une chaine de caractères. Exemple :<jupyter_code>import json

data = {
    'name' : 'Mewtwo',
    'pokedex_id' : 150,
    'type' : 'psychic',
    'location':None,
    'best':True
}

#L'encoding JSON gère les types None, bool, int, float, str, lists, tuples et dictionaires.
#L'encoding presque identique à celui de Python, à quelques différences près : 
#None <-> null
#True <-> true
#False <-> false

json_str=json.dumps(data)
print("JSON :", json_str)

data= json.loads(json_str)
print("DATA :", data)<jupyter_output>JSON : {"name": "Mewtwo", "pokedex_id": 150, "type": "psychic", "location": null, "best": true}
DATA : {'name': 'Mewtwo', 'pokedex_id': 150, 'type': 'psychic', 'location': None, 'best': True}<jupyter_text>Il est possible de trier les clés d'un JSON.<jupyter_code>print(json.dumps(data,sort_keys=True))<jupyter_output>{"best": true, "location": null, "name": "Mewtwo", "pokedex_id": 150, "type": "psychic"}<jupyter_text>Requêter une API avec Python<jupyter_code>import requests
import pprint

#token_auth='votre token ici, recu dans votre boite mail'
token_auth=key

url_avec_params='https://api.sncf.com/v1/coverage/sncf/stop_areas'

r=requests.get(url_avec_params,auth=(token_auth,''))

pprint.pprint(r.json())
JSONJS(r.json())<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10767292075049006, 'fraction_numerical': 0.003920470456454775, 'mean_word_length': 4.700718276137271, 'pattern_counts': {'":': 10, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 12, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '250518', 'license': 'MIT', 'n_tokens_mistral': 2414, 'n_tokens_neox': 2381, 'n_words': 742, 'path': '_doc/notebooks/td2a_eco/TD2A_eco_API_SNCF.ipynb', 'repo_name': 'sdpython/ensae_teaching_cs', 'size': '7142'}