modify 1st project and rest

This commit is contained in:
makayabou 2020-08-06 03:06:40 +02:00
parent 559539cc65
commit 3248e48d50
2 changed files with 276 additions and 41 deletions

View File

@ -3,16 +3,16 @@
## Création du projet ## Création du projet
??? important "Note importante pour les étudiants" ??? important "Note importante pour les étudiants"
Ne créez pas un nouveau dossier, Ne créez pas un nouveau dossier,
1. clonez plutôt le projet d'évaluation 1. clonez plutôt le projet d'évaluation
2. basculez sur la branche start 2. basculez sur la branche start
3. Créez une nouvelle branche nommée `start-votre-id-gitlab` 3. Créez une nouvelle branche nommée `start-votre-id-gitlab`
``` ```
git clone https://gitlab.com/devopsp1/python-webscrap.git` git clone https://gitlab.com/devopsp1/python-webscrap.git`
cd python-webscrap cd python-webscrap
git checkout start git checkout start
git checkout -b start-mon-id-gitlab git checkout -b start-mon-id-gitlab
``` ```
On démarre un projet simplement en créant un dossier, dans lequel (par convention), on crée le fichier `main.py` On démarre un projet simplement en créant un dossier, dans lequel (par convention), on crée le fichier `main.py`
@ -26,23 +26,27 @@ On met un **shebang** en 1ère ligne pour indiquer la version de python.
Dans ce script on déclare deux variables, qu'on nomme `base_url`et `endpoint1`, auxquelles on donne une valeur. Dans ce script on déclare deux variables, qu'on nomme `base_url`et `endpoint1`, auxquelles on donne une valeur.
``` !!! note "main.py"
#!/usr/bin/env python3 ```
#!/usr/bin/env python3
base_url = "https://gitlab.com/api/v4" api_url = "https://gitlab.com/api/v4"
print(base_url) print(api_url)
endpoint1 = base_url + "/groups" dataset = "/groups"
print(endpoint1) print(dataset)
``` endpoint = api_url + dataset
print(endpoint)
```
On peut simplement exécuter ce script avec `python poi.py` ou l'exécuter en mode **interactif** (-i) pour continuer à manipuler les variables et les fonctions du programme: On peut simplement exécuter ce script avec `python main.py` ou l'exécuter en mode **interactif** (-i) pour continuer à manipuler les variables et les fonctions du programme:
``` ```
user@host:~$ python -i main.py user@host:~$ python -i main.py
https://gitlab.com/api/v4 https://gitlab.com/api/v4
/groups
https://gitlab.com/api/v4/groups https://gitlab.com/api/v4/groups
>>> >>>
>>> type(endpoint1) >>> type(endpoint)
<class 'str'> <class 'str'>
``` ```
@ -75,7 +79,7 @@ Il y a d'autre variables simples:
>>> VAR_B=True >>> VAR_B=True
>>> type(VAR_B) >>> type(VAR_B)
<class 'bool'> # VAR_B est un `boolean`, une valeur booléenne, \ <class 'bool'> # VAR_B est un `boolean`, une valeur booléenne, \
# qui ne peut être que `True` ou `False` # qui ne peut être que `True` ou `False`
>>> VAR_C = 10 >>> VAR_C = 10
>>> type(VAR_C) >>> type(VAR_C)
@ -137,6 +141,6 @@ coding and playing
``` ```
??? important "Note importante pour les étudiants" ??? important "Note importante pour les étudiants"
Pour l'évaluation, vous devez demander une merge request depuis votre branche vers la branche start. Pour l'évaluation, vous devez demander une merge request depuis votre branche vers la branche start.
![Faire une merge request](img/creating-merge-request.png) ![Faire une merge request](img/creating-merge-request.png)

View File

@ -15,22 +15,6 @@ L'API utilisée, appellée REST API communique avec le site web par des requête
Nous allons utiliser l'APi de Gitlab qui contient énormément d'informations sur les projets hébergés. Nous allons utiliser l'APi de Gitlab qui contient énormément d'informations sur les projets hébergés.
---
## Générer un jeton d'authentification
Pour accéder aux données présentées par l'API (par exemple, la liste des 'issues' qui me sont attribuées),
Gitlab a besoin de m'identifier.
Pour cela, à partir de notre interface web utilisateur de Gitlab, nous allons générer un **jeton d'authentification**.
Vous pouvez utiliser ce [tutoriel pour générer votre jeton d'API](https://screenful.com/gitlab/gitlab-apikey){target=_blank}
--- ---
@ -84,13 +68,260 @@ Dans notre fichier `main.py` nous devons maintenant importer les libraires
import requests import requests
import json import json
base_url = "https://gitlab.com/api/v4" api_url = "https://gitlab.com/api/v4"
endpoint1 = base_url + "/groups" dataset = "/groups"
endpoint = api_url + dataset
``` ```
--- ---
## Accès à l'API ## Accès à l'API
Nous allons ajouter à notre code une fonction, issue de la bibliothèque requests, pour accéder aux données via l'API REST. Nous allons maintenant éxecuter ce code en mode interactif, et accéder à l'API dans la console python:
!!! bug ""
```
user@host:~$ python -i main.py
>>> r = requests.get(endpoint)
```
Nous avons placé dans la variable `r`le résultat de la fonction `get`, prise de la bibliothèque `requests`, avec comme 1er argument `endpoint`, c'est à dire `https://gitlab.com/api/v4/groups`
!!! bug ""
```
>>> print(r)
<Response [200]>
```
Le résultat ne semble pas encourageant, et pourtant ! Le code **200** signifie qu'une URL a bien été trouvée, ce qu'on préfère à une erreur **404**!
!!! bug ""
```
>>> type(r)
<class 'requests.models.Response'>
```
Le type de `r` est une classe, c'est un **objet Python**, qui contient d'autres données que ce simple `**Status Code 200**`
!!! bug ""
```
>>> help(r)
>>> dir(r)
['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', '_next', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']
```
Les fonctions `help()` et `dir()` nous aident à manipuler cet objet.
!!! bug ""
```
>>> r.__attrs__
['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request']
```
La **méthode** `__attrs` nous donne une liste d'attributs de notre objet `r`
!!! bug ""
```
>>> r.url
'https://gitlab.com/api/v4/groups'
```
On peut ainsi vérifier l'URL sollicitée.
!!! bug ""
```
>>> r.content
```
Avant d'accéder au contenu, il va falloir le mettre en forme!
---
## Formuler un requête à l'API
Comme il y a beaucoup de données (ici, tous les groupes créés sur Gitlab, il est nécessaire de filtrer notre requête.
Nous allons pour cela utiliser des paramètres, écrits au format **json** et stockés dans une variable nommée `payload`
!!! bug ""
```
>>> payload = {"search": "garage"}
>>> r = requests.get(endpoint,params=payload)
```
nous chercherons ainsi les groupes qui contiennent le mot **garage**
La fonction get prend comme deuxième argument les données json.
On place ces données dans la variable `params` afin de préserver `payload`
!!! bug ""
```
>>> r.headers
{'Date': 'Wed, 05 Aug 2020 18:42:47 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked',
'Connection': 'keep-alive', 'Set-Cookie': '__cfduid=dcbe4c6164f5e175674b0abff0fb011c71596652967; expires=Fri, 04-Sep-20 18:42:47 GMT;
path=/; domain=.gitlab.com; HttpOnly; SameSite=Lax; Secure', 'Vary': 'Accept-Encoding, Origin', 'Cache-Control': 'max-age=0,
private, must-revalidate', 'Etag': 'W/"44cfa1c513193c8d78cdfc584f6dea72"', 'Link': '<https://gitlab.com/api/v4/groups?order_by=name&owned=false&page=2&per_page=20&search=garage&sort=asc&statistics=false&with_custom_attributes=false>;
rel="next", <https://gitlab.com/api/v4/groups?order_by=name&owned=false&page=1&per_page=20&search=garage&sort=asc&statistics=false&with_custom_attributes=false>;
rel="first", <https://gitlab.com/api/v4/groups?order_by=name&owned=false&page=2&per_page=20&search=garage&sort=asc&statistics=false&with_custom_attributes=false>;
rel="last"', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'SAMEORIGIN', 'X-Next-Page': '2', 'X-Page': '1', 'X-Per-Page': '20', 'X-Prev-Page': '',
'X-Request-Id': 'wo9iLfsTax', 'X-Runtime': '0.116039', 'X-Total': '37', 'X-Total-Pages': '2', 'Strict-Transport-Security': 'max-age=31536000',
'Referrer-Policy': 'strict-origin-when-cross-origin', 'Content-Encoding': 'gzip', 'GitLab-LB': 'fe-12-lb-gprd', 'GitLab-SV': 'api-18-sv-gprd',
'CF-Cache-Status': 'DYNAMIC', 'cf-request-id': '046187edf40000edab20af4200000001', 'Expect-CT': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
'Server': 'cloudflare', 'CF-RAY': '5be2a8f65905edab-CDG'}
>>>
>>> r.headers['X-Total']
'37'
```
Les headers nous donnent des informations intéressantes, et notamment ce `X-Total`, qui est le nombre total de résultats obtenus.
**Rappel : ** Les headers sont encadrés par des accolades ( `curly brackets : { }` ). C'est donc un objet de la classe `dic`. On accède à ses éléments en mettant entre crochets et guillemets la clé dont on veut voir la valeur, ici ` r.headers['X-Total']`
---
## Accéder au contenu de la requête
Il nous faut maintenant accéder aux données contenues dans la requête
!!! bug ""
```
>>> data = r.json()
>>>
>>> type(data)
<class 'list'>
```
On créé la variable data, dans lequelle on met le contenu `r` sur lequel on a appliqué la fonction `json()`
!!! bug ""
```
>>> data[0].keys()
dict_keys(['id', 'web_url', 'name', 'path', 'description', 'visibility', 'share_with_group_lock',
'require_two_factor_authentication', 'two_factor_grace_period', 'project_creation_level', 'auto_devops_enabled',
'subgroup_creation_level', 'emails_disabled', 'mentions_disabled', 'lfs_enabled', 'default_branch_protection',
'avatar_url', 'request_access_enabled', 'full_name', 'full_path', 'created_at', 'parent_id', 'ldap_cn', 'ldap_access'])
```
Prenons le 1er élément de la liste `data` (numéroté 0), et consultons la liste de ses `keys()`.
Chaque élément de la liste `data`correspond à un résultat de la recherche, et est constitué d'un dictionnaire dans lequel nous allons pouvoir `itérer`
---
## Itération dans la liste de résultats
### `for`
Nous allons utiliser la boucle `for` pour **répéter une action sur chaque élément de la liste** (=itérer)
!!! bug ""
```
>>> for i in data:
... print(i['name']) # Appuyez 2 fois Entrée pour créer un 1ère ligne non indentée
... # et marquer la fin des instructions de for
AppGarage
Atheed-Garage
Code Garage
[..]
Garagenum
>>>
```
Retenez bien la syntaxe simple de la boucle `for`dans Python: les `:` pour marquer le début des instructions, et c'est l'indentation ( `4` ++space++ en début de ligne) seulement qui marque la liste des instructions.
### `if`
Nous pouvons maintenant utiliser if pour afficher les détails d'un des résultats obtenus, que nous stockerons dans une variable nommée result:
!!! bug ""
```
>>> for i in data:
... if i['name'] == "Garagenum":
... result = i
...
>>> print(result)
{'id': 4160307, 'web_url': 'https://gitlab.com/groups/garagenum', 'name': 'Garagenum', 'path': 'garagenum', 'description': '', 'visibility': 'public', 'share_with_group_lock': False, 'require_two_factor_authentication': False, 'two_factor_grace_period': 48, 'project_creation_level': 'developer', 'auto_devops_enabled': None, 'subgroup_creation_level': 'owner', 'emails_disabled': None, 'mentions_disabled': None, 'lfs_enabled': True, 'default_branch_protection': 2, 'avatar_url': None, 'request_access_enabled': False, 'full_name': 'Garagenum', 'full_path': 'garagenum', 'created_at': '2018-11-30T14:35:23.504Z', 'parent_id': None, 'ldap_cn': None, 'ldap_access': None}
```
Syntaxe similaire que pour le `for`, ici le `if`est imbriqué dans le `for`
### Affichage
Nous utiliserons aussi la boucle `for`pour afficher les résultats de manière lisible:
!!! bug ""
```
>>> for i in result:
... print(i + " : " + str(result[i]))
...
id : 4160307
web_url : https://gitlab.com/groups/garagenum
name : Garagenum
[...]
```
Le `str(result[i])`permet de transformer chaque valeur de `result`en **chaîne de caractères (str)**, pour permettre l'affichage par `print()`
---
## Authentification
Certaines données peuvent demander une authentification pour en autoriser l'accès.
Cherchons par exemple, dans les sous-groupes du garage, un groupe privé nommé `interventions`:
!!! bug ""
```
>>> r = requests.get(endpoint,{"search":"garage"})
>>>
>>> for i in r.json():
... if i['name'] == "Garagenum":
... gn_id = i['id']
...
>>> print("L'ID du groupe Garagenum est " + gn_id)
L'ID du groupe Garagenum est 4160307
>>>
>>>
>>> gn_endpoint = "https://gitlab.com/api/v4/groups/gn_id/subgroups"
>>>
>>> payload = {'search': 'interventions'}
>>>
>>> r = requests.get(gn_endpoint, params = payload)
>>> for i in r.json():
... print(i['name'])
...
>>>
```
Aucun résultat, et pourtant, ce groupe existe!
Pour vous authentifier, il vous faut d'abord créer un jeton d'authentification dans gitlab
## Générer un jeton d'authentification
Pour accéder aux données présentées par l'API (par exemple, la liste des 'issues' qui me sont attribuées),
Gitlab a besoin de m'identifier.
Pour cela, à partir de notre interface web utilisateur de Gitlab, nous allons générer un **jeton d'authentification**.
Vous pouvez utiliser ce [tutoriel pour générer votre jeton d'API](https://screenful.com/gitlab/gitlab-apikey){target=_blank}
### Accès authentifié
Il vous suffit maintenant de modifier la variable `payload` , qui contient la liste des options pour la requête.
!!! bug ""
```
>>> payload['private_token'] = "p4zggV-SY1rB4s"
>>>
>>> r = requests.get(gn_endpoint, payload)
>>>
>>> for i in r.json():
... print(i['name'])
...
interventions
```
**Notez bien** la manière dont une nouvelle clé `private-token` a été ajoutée au dictonnaire `payload`
---
## Pour les étudiants
??? important "Conditions de validation"
Pour valider cette unité, il faut que vous fassiez une merge-request vers la branche `start`
Votre code doit permettre d'obtenir le résultat