modify 1st project and rest
This commit is contained in:
parent
559539cc65
commit
3248e48d50
@ -3,16 +3,16 @@
|
||||
## Création du projet
|
||||
|
||||
??? important "Note importante pour les étudiants"
|
||||
Ne créez pas un nouveau dossier,
|
||||
1. clonez plutôt le projet d'évaluation
|
||||
2. basculez sur la branche start
|
||||
3. Créez une nouvelle branche nommée `start-votre-id-gitlab`
|
||||
```
|
||||
git clone https://gitlab.com/devopsp1/python-webscrap.git`
|
||||
cd python-webscrap
|
||||
git checkout start
|
||||
git checkout -b start-mon-id-gitlab
|
||||
```
|
||||
Ne créez pas un nouveau dossier,
|
||||
1. clonez plutôt le projet d'évaluation
|
||||
2. basculez sur la branche start
|
||||
3. Créez une nouvelle branche nommée `start-votre-id-gitlab`
|
||||
```
|
||||
git clone https://gitlab.com/devopsp1/python-webscrap.git`
|
||||
cd python-webscrap
|
||||
git checkout start
|
||||
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`
|
||||
|
||||
@ -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.
|
||||
|
||||
```
|
||||
#!/usr/bin/env python3
|
||||
!!! note "main.py"
|
||||
```
|
||||
#!/usr/bin/env python3
|
||||
|
||||
base_url = "https://gitlab.com/api/v4"
|
||||
print(base_url)
|
||||
endpoint1 = base_url + "/groups"
|
||||
print(endpoint1)
|
||||
```
|
||||
api_url = "https://gitlab.com/api/v4"
|
||||
print(api_url)
|
||||
dataset = "/groups"
|
||||
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
|
||||
https://gitlab.com/api/v4
|
||||
/groups
|
||||
https://gitlab.com/api/v4/groups
|
||||
>>>
|
||||
>>> type(endpoint1)
|
||||
>>> type(endpoint)
|
||||
<class 'str'>
|
||||
|
||||
```
|
||||
@ -75,7 +79,7 @@ Il y a d'autre variables simples:
|
||||
>>> VAR_B=True
|
||||
>>> type(VAR_B)
|
||||
<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
|
||||
>>> type(VAR_C)
|
||||
@ -137,6 +141,6 @@ coding and playing
|
||||
```
|
||||
|
||||
??? 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.
|
||||

|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 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 json
|
||||
|
||||
base_url = "https://gitlab.com/api/v4"
|
||||
endpoint1 = base_url + "/groups"
|
||||
api_url = "https://gitlab.com/api/v4"
|
||||
dataset = "/groups"
|
||||
endpoint = api_url + dataset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user