Téléverser une contribution communautaire sur data.gouv.fr¶
Ou, s’il l’on préfère, uploader une community resource sur data.gouv.fr.
Objectif¶
Tous les mois le ministère de l’intérieur met à jour les données concernant les faits constatés par département depuis 1996. Ces données sont mises à disposition sous forme d’un fichier Excel, donc difficilement manipulable, avec un onglet par département (encore pire).
Pour pouvoir les utiliser efficacement (sous R par exemple), on a besoin de regrouper ces données
dans un fichier .csv
(plus exactement .tsv
pour mettre en évidence qu’on
utilise la tabulation comme délimiteur).
Cette transformation est décrite dans l’article Conversion Excel vers tsv des données sur les faits constatées.
Une fois ce travail effectué, le site data.gouv.fr permet d’en faire bénéficier les autres utilisateurs en ajoutant au jeu de données initial une contribution communautaire qui apparaitra sous les fichiers principaux.
Le but de ce tutoriel est de montrer comment, en utilisant l’API fournie par data.gouv.fr, on peut automatiser la création de cette contribution communautaire sans intervention manuelle.
Pour cela, on utilisera la commande curl
, qui est un peu le couteau suisse
lorsque qu’il faut parler une API Web, et la commande jq
qui permet de travailler
les réponses JSON.
Il faut maintenant tenter de décrypter la documentation API pour comprendre les bonnes commandes à passer.
Variables¶
Avant toute chose, il faut penser à récupérer sa clé API qui figure dans les
paramètres de son profil utilisateur. Comme on va faire des mises à jour et des créations,
il faut être identifié et la clé est le reflet de cette identification.
Dans la suite, on considère que cette clé figure dans la variable KEY
KEY="<clé APPI personnelle>"
Pour simplifier les appels API, on crée également la variable suivante:
API="https://www.data.gouv.fr/api/1"
Enfin, on aura besoin de l’identifiant du jeu de données. On trouve cet identifiant en cliquant sur le bouton bleu détails, sur la droite de l’écran des données concernant les faits constatés.
Pour le jeu de données qui m’intéresse, je fais donc l’affectation suivante
DATASET=5617ad4dc751df6211cdbb49
Uploader le fichier¶
On considère que le fichier qui va constituer la ressource est dans la variable FILE
FILE="exemple.tsv"
La première phase consiste à uploader le fichier. Dans la documentation API, on
trouve la syntaxe sous /datasets/{dataset}/upload/community/
. Les accolades
autour de dataset signifie qu’il faut passer l’identifiant du jeu de données
dans l’URL.
Dans la documentation API, on voit qu’il faut passer une commande POST
en fournissant le nom du fichier en paramètre file.
Traduit en commande curl
, cela donne
curl \
-H "X-API-KEY:$KEY" \
-X POST \
-F "file=@$FILE" \
"$API/datasets/$DATASET/upload/community/"
Cette commande analyse le fichier transmis et renvoit un objet JSON qu’il faut conserver car il va être utile pour la commande qui va suivre
{
"checksum": {
"type": "sha1",
"value": "1e7309678c995c11c9163d1f59add3ea84b2c63b"
},
"created_at": "2016-06-02T10:52:41.782282",
"description": null,
"filesize": 11284,
"filetype": "file",
"format": "tsv",
"id": "483ed173-6f6d-4f15-a9e5-512b6b0463e1",
"is_available": true,
"last_modified": "2016-06-02T10:52:41.782311",
"metrics": {
"nb_hits": 0,
"nb_uniq_visitors": 0,
"nb_visits": 0,
"views": 0
},
"mime": "text/tab-separated-values",
"published": "2016-06-02T10:52:41.782493",
"success": true,
"title": "exemple.tsv",
"url": "https://www.data.gouv.fr/s/resources/chiffres-departementaux-mensuels-relatifs-aux-crimes-et-delits-enregistres-par-les-services-de-police-et-de-gendarmerie-depuis-janvier-1996/20160602-105241/exemple.tsv",
}
Mettre à jour la ressource communautaire¶
A ce stade, la ressource communautaire existe et a un identifiant
qui apparait dans le champ id
du JSON ci-dessus :
483ed173-6f6d-4f15-a9e5-512b6b0463e1
dans notre cas. Mais elle
n’apparait toujours pas dans les ressources liées au jeu de données,
malgré le fait qu’on avait transmis l’identifiant du jeu de données.
Il faut passer une nouvelle commande pour faire le lien entre la ressource communautaire et le dataset.
Dans la documentation API, on trouve la syntaxe sous
/datasets/community_resources/{community}/
.
On voit déjà qu’il faut qu’on récupère l’identifiant de la ressource qui apparait
dans la réponse JSON précédente. On le fait en utilisant la commande
jq
qui permet de travailler sur les fichiers JSON. En l’occurence,
pour récupérer l’identifiant dans la variable $CR
, on fait
CR=$(jq -r '.id' $JSON)
Pour mettre à jour la ressource, la documentation API indique
qu’il faut transmettre une commande PUT
avec un objet JSON. Ce qui donne
la commande suivante:
curl \
-H "Content-Type: application/json" \
-H "X-API-KEY:$KEY" \
-X PUT \
-d @$JSON \
"$API/datasets/community_resources/$CR/"
Quelques remarques sur cette commande :
-H « Content-Type: application/json » : l’ajout de cet header est important car la commande ne fonctionne pas correctement sinon.
la variable
$JSON
contient le nom du fichier qui contient l’objet JSON
J’avais l’espoir que la transmission en paramètre de l’objet JSON de l’étape précédente pouvait suffire, mais ce n’est pas le cas. La ressource reste non rattachée au dataset, et donc invisible.
Après plusieurs tentatives, et en observant les appels réseau lorsqu’on transmet manuellement une ressource depuis le
site data.gouv.fr, j’ai repéré qu’il fallait que le champ dataset
soit présent dans l’objet JSON,
simplement en ajoutant le champ correspondant, en dernière ligne sur l’exemple ci-dessous:
{
"checksum": {
"type": "sha1",
"value": "1e7309678c995c11c9163d1f59add3ea84b2c63b"
},
"created_at": "2016-06-02T10:52:41.782282",
"description": null,
"filesize": 11284,
"filetype": "file",
"format": "tsv",
"id": "483ed173-6f6d-4f15-a9e5-512b6b0463e1",
"is_available": true,
"last_modified": "2016-06-02T10:52:41.782311",
"metrics": {
"nb_hits": 0,
"nb_uniq_visitors": 0,
"nb_visits": 0,
"views": 0
},
"mime": "text/tab-separated-values",
"published": "2016-06-02T10:52:41.782493",
"success": true,
"title": "exemple.tsv",
"url": "https://www.data.gouv.fr/s/resources/chiffres-departementaux-mensuels-relatifs-aux-crimes-et-delits-enregistres-par-les-services-de-police-et-de-gendarmerie-depuis-janvier-1996/20160602-105241/exemple.tsv",
"dataset": "5617ad4dc751df6211cdbb49"
}
La même commande curl
que ci-dessus, mais avec ce fichier complété, fonctionne et la ressource
apparait bien sur le site data.gouv.fr.
Cette deuxième commande renvoit également un objet JSON dont on remarque qu’il est beaucoup plus complet,
en particulier au niveau du champ dataset
ou owner
:
{
"checksum": {
"type": "sha1",
"value": "1e7309678c995c11c9163d1f59add3ea84b2c63b"
},
"created_at": "2016-06-02T10:52:41.782000",
"dataset": {
"class": "Dataset",
"id": "5617ad4dc751df6211cdbb49",
"page": "https://www.data.gouv.fr/fr/datasets/chiffres-departementaux-mensuels-relatifs-aux-crimes-et-delits-enregistres-par-les-services-de-police-et-de-gendarmerie-depuis-janvier-1996/",
"title": "Chiffres départementaux mensuels relatifs aux crimes et délits enregistrés par les services de police et de gendarmerie depuis janvier 1996",
"uri": "https://www.data.gouv.fr/api/1/datasets/chiffres-departementaux-mensuels-relatifs-aux-crimes-et-delits-enregistres-par-les-services-de-police-et-de-gendarmerie-depuis-janvier-1996/"
},
"description": null,
"filesize": 11284,
"filetype": "file",
"format": "tsv",
"id": "483ed173-6f6d-4f15-a9e5-512b6b0463e1",
"is_available": true,
"last_modified": "2016-06-02T11:26:48.794702",
"metrics": {
"nb_hits": 0,
"nb_uniq_visitors": 0,
"nb_visits": 0,
"views": 0
},
"mime": "text/tab-separated-values",
"organization": null,
"owner": {
"avatar": "https://www.data.gouv.fr/s/avatars/f7/b0f99299ec484ea8054d5f24841450-100.png",
"class": "User",
"first_name": "Philippe",
"id": "53700bc3a3a7294600435fbe",
"last_name": "Chataignon",
"page": "https://www.data.gouv.fr/fr/users/philippe-chataignon/",
"slug": "philippe-chataignon",
"uri": "https://www.data.gouv.fr/api/1/users/philippe-chataignon/"
},
"published": "2016-06-02T10:52:41.782493",
"title": "exemple.tsv",
"url": "https://www.data.gouv.fr/s/resources/chiffres-departementaux-mensuels-relatifs-aux-crimes-et-delits-enregistres-par-les-services-de-police-et-de-gendarmerie-depuis-janvier-1996/20160602-105241/exemple.tsv"
}
Script final¶
Qui dit automatisation dit script shell.
L’ensemble des éléments ci-dessus peut être regroupé dans un script unique qui enchaîne les différentes étapes.
Avec les explications ci-dessus, le script devrait être compréhensible.
Le seul élément non expliqué est l’utilisation de jq
pour ajouter le champ dataset
. La
syntaxe de la commande jq
n’est pas des plus limpides. '.'
signifie tous les champs que l’on
passe à un filtre |
puis on crée le champ dataset
et on lui affecte la variable shell DATASET
en échappant les "
.
jq ". | .dataset=\"$DATASET\""
Le script prend 2 paramètres : le fichier à transmettre et l’identifiant du dataset concerné. Dans l’article
Conversion Excel vers tsv des données sur les faits constatées, ce script s’appelle cr_upload
: il est appelé à la fin du programme R, une fois
la conversion réalisée pour téléverser le fichier créé vers data.gouv.fr:
#!/bin/sh
KEY="<clé API>"
API="https://www.data.gouv.fr/api/1"
JSON=$(tempfile -p json)
FILE=$1
DATASET=$2
## upload file
curl \
-s \
-H "X-API-KEY:$KEY" \
-X POST \
-F "file=@$FILE" \
"$API/datasets/$DATASET/upload/community/" | jq ". | .dataset=\"$DATASET\"" > $JSON
# get cr id
CR=$(jq -r '.id' $JSON)
echo "community_ressource_id:" $CR
### update rc
curl \
-s \
-H "Content-Type: application/json" \
-H "X-API-KEY:$KEY" \
-X PUT \
-d @$JSON \pi
"$API/datasets/community_resources/$CR/"
rm $JSON
Effacer la ressource¶
Lors de test, on peut-être amener à créer des ressources qu’on veut effacer. Il suffit de
passer la commande curl
suivante avec l’identifiant de la ressource concernée
curl -H "X-API-KEY:$KEY" -X DELETE "$API/datasets/community_resources/483ed173-6f6d-4f15-a9e5-512b6b0463e11/"
Conclusion¶
Les API, c’est bien. Comme le dit Henri Verdier dans cet article, « les API fournissent l’ensemble des instructions pour qu’une application puisse se « brancher » facilement sur une base de données ou une autre brique logicielle ». Dans le cas expliqué ici, l’API permet effectivement d’automatiser le travail et de le faire faire par une machine, ce qui est l’objectif.
Après, la question reste posée sur l’utilisation du terme facilement. La documentation API a le mérite d’exister. Mais j’ai ressenti un grand sentiment de solitude pour aborder l’utilisation concrète de cette API et je n’ai pas trouvé d’exemple d’utilisation, via Google par exemple. Peut-être que je n’ai pas cherché au bon endroit ? Peut-être existe-t-il un cercle secret des utilisateurs de l’API data.gouv.fr ? En tout cas, l’absence d’exemples concrêts d’utilisation de cette API est ce qui m’a à écrire cet article pour laisser une trace éventuellement utile à d’autres.