Récupérer les données du jeu vidéo League of Legends et les exploiter

Tags :
  • POK
  • 2023-2024
  • temps 1
  • API
  • Flask
  • Python
Auteurs :
  • Samy Diafat

Ce POK a pour but de réaliser ma première connexion à une API pour y récupérer des données. L'entreprise Riot Games donne accès aux données de son jeu vidéo en ligne League of Legends à travers une API.L'objectif final est de développer une petite application web permettant d'afficher des données à partir du pseudo d'un joueur

POK intermédiaire

Avoir les bases en html/css, python (pandas), invit de commande et avoir de la patience.

Table des matières

  1. Ce que j'ai prévu pour le 1er point POK

  2. Ce que j'ai fait au 1er sprint

  3. Ce que j'ai prévu pour le second point POK

  4. Ce que j'ai fait à la fin du temps 1

  5. Conclusion

Ce que j'ai prévu pour le 1er point POK

Ce que j'ai fait au 1er sprint

Faire des requêtes directement sur le site de RiotGames

Afin d'accéder aux données, j'ai tout d'abord dû récupérer une clef me permettant de faire des requêtes à l'API.

Api key

Une fois ma clef récupérée, j'ai tout d'abord pris connaissance de l'ensemble de méthodes mis à notre disposition.

Il y a plus d'une dizaine de méthodes disponibles pour le jeu League of Legends.

Riot API

J'ai ensuite testé la requête suivante qui permet de récupérer des informations sur un compte à partir du pseudo :

Exemple requête

Ce qui m'a permis d'obtenir les données suivantes :

Exemple réponse

On passe maintenant à un notebook afin d'automatiser tout cela avec python !

Automatiser les requêtes sur python

Import de notre clef

api_key = 'RGAPI-d26162a7-7ea3-4af5-91b3-1087f97591e8'
api_key

'RGAPI-d26162a7-7ea3-4af5-91b3-1087f97591e8'

On récupère ensuite une URL venant du site de Riot Games : https://developer.riotgames.com/apis

On s'interesse tout d'abord aux données d'un compte en particulier, on utilise ici l'API V4

pseudo = 'Yomm'
api_url = 'https://euw1.api.riotgames.com/lol/summoner/v4/summoners/by-name/' + pseudo
api_url

'https://euw1.api.riotgames.com/lol/summoner/v4/summoners/by-name/Yomm'

Afin d'avoir l'autorisation d'accès à l'API, nous devons ajouter notre clef à l'url

api_url = api_url + '?api_key=' + api_key
api_url

'https://euw1.api.riotgames.com/lol/summoner/v4/summoners/by-name/Yomm?api_key=RGAPI-d26162a7-7ea3-4af5-91b3-1087f97591e8'

On importe ensuite la bibliothèque requests qui va nous permettre de faire des requêtes via python.

La bibliothèque requests en Python est utilisée pour envoyer des requêtes HTTP vers des serveurs web et interagir avec des ressources en ligne. Elle permet de créer des applications qui peuvent effectuer des opérations telles que l'envoi de requêtes GET, POST, PUT, DELETE, etc., pour récupérer des données depuis des API, envoyer des données à des serveurs, télécharger des fichiers à partir d'Internet, et bien plus encore.

import requests
requests.get(api_url)

<Response [200]>

La réponse nous permet de savoir l'état de la requête envoyée, 200 correspond à une requête réussi !

resp = requests.get(api_url)
player_info = resp.json()
player_info

{'id': 'sowIMP6jk8jfAEMsUR9W9TwUlqcHLpk-sGD727LdzXTJKJU', 'accountId': 'XEOycCgqv9jSoYu25_24LPzueZGvKrcdUX7yUy_p-6vrxw', 'puuid': 'u-bz6k4v2VzDEVkG5brW_NBGfYmjCGstDEoK0ruij3BpbwkhseE4knsJZH_Sx3NjnSzQy8iv60vTjA', 'name': 'Yomm', 'profileIconId': 608, 'revisionDate': 1697225190000, 'summonerLevel': 184}

La méthode .json() est appelée, et le contenu JSON de la réponse est automatiquement analysé et converti en une structure de données Python

On voit que player_info est un dictionnaire contenant plusieurs informations

player_info.keys()

dict_keys(['id', 'accountId', 'puuid', 'name', 'profileIconId', 'revisionDate', 'summonerLevel'])

On peut par exemple obtenir l'ID associée à un pseudo

player_info['id']

Faire des calculs à l'aide des données récoltées

Par la suite, j'ai créé des fonctions me permettant de faire des requêtes dans plusieurs sources différentes afin de croiser les informations, et de faire des calculs de moyenne par exemple.

Cliquez pour voir le code

# Cette fonction permet de récupérer le puuid d'un joueur à partir du nom d'invocateur, de la région, et d'une clef api
def get_puuid(summoner_name, region, api_key):
    api_url = (
        "https://" + 
        region +
        ".api.riotgames.com/lol/summoner/v4/summoners/by-name/" +
        summoner_name +
        "?api_key=" +
        api_key
    )
    resp = requests.get(api_url)
    player_info = resp.json()
    puuid = player_info['puuid']
    return puuid  



# cette fonction permet de récupérer les identifiants des 20 dernières parties d'un joueur
def get_match_ids(puuid, mass_region, api_key):
    api_url = (
        "https://" +
        mass_region +
        ".api.riotgames.com/lol/match/v5/matches/by-puuid/" +
        puuid + 
        "/ids?start=0&count=20" + 
        "&api_key=" + 
        api_key
    )   
    # we need to add this "while" statement so that we continuously loop until it's successful
    while True:
        resp = requests.get(api_url)
        
        # whenever we see a 429, we sleep for 10 seconds and then restart from the top of the "while" loop
        if resp.status_code == 429:
            print("Rate Limit hit, sleeping for 10 seconds")
            time.sleep(10)
            # continue means start the loop again
            continue
            
        # if resp.status_code isn't 429, then we carry on to the end of the function and return the data
        resp = requests.get(api_url)
        match_ids = resp.json()
        return match_ids 


# Cette fonction permet de récupérer les données d'une partie
def get_match_data(match_id, mass_region, api_key):
    api_url = (
        "https://" + 
        mass_region + 
        ".api.riotgames.com/lol/match/v5/matches/" +
        match_id + 
        "?api_key=" + 
        api_key
    )   
    # we need to add this "while" statement so that we continuously loop until it's successful
    while True:
        resp = requests.get(api_url)
        
        # whenever we see a 429, we sleep for 10 seconds and then restart from the top of the "while" loop
        if resp.status_code == 429:
            print("Rate Limit hit, sleeping for 10 seconds")
            time.sleep(10)
            # continue means start the loop again
            continue
            
        # if resp.status_code isn't 429, then we carry on to the end of the function and return the data
        resp = requests.get(api_url)
        match_data = resp.json()
        return match_data 
pseudo = 'Yomm'
region = 'euw1'
mass_region = 'EUROPE'
get_puuid(pseudo,region,api_key)

'u-bz6k4v2VzDEVkG5brW_NBGfYmjCGstDEoK0ruij3BpbwkhseE4knsJZH_Sx3NjnSzQy8iv60vTjA'

puuid_player = get_puuid(pseudo,region,api_key)
id_matches = get_match_ids(puuid_player, mass_region, api_key)
print('Les identifiants des 20 dernières parties de',pseudo,'sont',id_matches)

Les identifiants des 20 dernières parties de Yomm sont ['EUW1_6620612418', 'EUW1_6620591242', 'EUW1_6620117730', 'EUW1_6616569027', 'EUW1_6616516559', 'EUW1_6615412808', 'EUW1_6611335474', 'EUW1_6611256844', 'EUW1_6610248381', 'EUW1_6610147341', 'EUW1_6609656368', 'EUW1_6607254752', 'EUW1_6607085859', 'EUW1_6606463762', 'EUW1_6603360397', 'EUW1_6603288425', 'EUW1_6603210097', 'EUW1_6601582307', 'EUW1_6601554856', 'EUW1_6600766557']

# Fonction permettant de récupérer les données d'un joueur à partie des données d'une partie et d'un ID
def find_player_data(match_data, puuid):
    participants = match_data['metadata']['participants']
    player_index = participants.index(puuid)
    player_data = match_data['info']['participants'][player_index]
    return player_data

Si l'on veut regarder uniquement une info

print(data)
data['kda']

[5.0, 8.333333333333334, 6.636363636363637, 3.526315789473684, 2.5454545454545454, 1.2857142857142856, 4.8, 19.0, 1.4444444444444444, 8.75, 5.75, 3.2142857142857144, 5.615384615384615, 2.5384615384615383, 5.777777777777778, 16.076923076923077, 14.75, 9.411764705882353, 5.3125, 14.375]

Vous pouvez trouver l'ensemble de mes fonctions sur mon github ! lien github

Utilisation du framework Flask pour développer une petite application

Enfin, voici le code permettant d'utiliser Flask et d'avoir une petite interface graphique

Cliquez pour voir le code

from flask import Flask, render_template,request
app = Flask(__name__)

@app.route("/")
@app.route("/home")
def home():
    return render_template("homepage.html")
 
@app.route("/league")
def search():
    return render_template("league.html")

@app.route("/tft")
def datapage():
    return render_template("tft.html")

@app.route("/valorant")
def datapage2():
    return render_template("valorant.html")


@app.route('/submit',methods = ['POST', 'GET'])
def submit():
    print('je rentre dans submit')
    if request.method == 'POST':
        pseudo = request.form['nm']
        return f"Login successfully by POST method, Hello {pseudo}"
    else:
        pseudo = request.args.get('nm')
        data_player_ranked = get_data_champion(pseudo,region,api_key)
        data_player = get_player_data(pseudo,region,api_key)
        #print('bouton activé')
        print('le pseudo du site')
        print(pseudo)
        if pseudo:
            #data_player_ranked = get_data_champion(pseudo,region,api_key)
            print(data_player_ranked)
            #data_player = get_player_data(pseudo,region,api_key)
            icone = data_player['icon_id'][0]
            rank_flex = data_player['rank_flex']
            rank_solo = data_player['rank_solo']
            rank_flex_icon = change_rank(data_player['rank_flex'])
            rank_solo_icon = change_rank(data_player['rank_solo'])
            summoner_level = data_player['summoner_level'][0]
                
            champ_solo = data_player_ranked['solo']['Champion_solo']
            champ_flex =data_player_ranked['flex']['Champion_flex']
            winrate_solo = round(data_player_ranked['solo']['Winrate_solo'] * 100)
            winrate_flex = round(data_player_ranked['flex']['Winrate_flex'] * 100)
            
            
            print(champ_solo,champ_flex,winrate_solo,winrate_flex)
            print('pseudo=',pseudo)
            print('lvl=',summoner_level)
            print('rank solo',rank_solo)
            print('rank flex',rank_flex)
            print('icone solo',rank_solo_icon)
            print('icone flex',rank_flex_icon)
            print('icone joueur',icone)
            print(data_player_ranked)
            return render_template("datapage.html",pseudo=pseudo,summoner_level=summoner_level,icone=icone,rank_flex=rank_flex,rank_solo=rank_solo,rank_flex_icon=rank_flex_icon,rank_solo_icon=rank_solo_icon,champ_solo=champ_solo,champ_flex=champ_flex,winrate_solo=winrate_solo,winrate_flex=winrate_flex)
        else:
            return "Aucun pseudo n'a été spécifié dans la demande GET."
   
if __name__ =="__main__":  
    app.run()

* Serving Flask app "main" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) 127.0.0.1 - - [16/Oct/2023 18:02:09] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [16/Oct/2023 18:02:09] "GET /static/style.css HTTP/1.1" 404 - 127.0.0.1 - - [16/Oct/2023 18:02:09] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [16/Oct/2023 18:02:10] "GET /league HTTP/1.1" 200 - 127.0.0.1 - - [16/Oct/2023 18:02:10] "GET /static/style.css HTTP/1.1" 404 - 127.0.0.1 - - [16/Oct/2023 18:02:10] "GET /league HTTP/1.1" 200 -

je rentre dans submit Récupération des statistiques en classés Récupération des parties classés Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Récupération des parties classés Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds

127.0.0.1 - - [16/Oct/2023 18:06:41] "GET /submit?nm=nicpsy HTTP/1.1" 200 - 127.0.0.1 - - [16/Oct/2023 18:06:41] "GET /static/style.css HTTP/1.1" 404 -

le pseudo du site nicpsy {'solo': {'Champion_solo': 'Sylas', 'Winrate_solo': 0.515625}, 'flex': {'Champion_flex': 'Sylas', 'Winrate_flex': 0.6056338028169014}} Sylas Sylas 52 61 pseudo= nicpsy lvl= 208 rank solo PLATINUM IV 0 rank flex EMERALD II 0 icone solo platine icone flex emeraude icone joueur 6271 {'solo': {'Champion_solo': 'Sylas', 'Winrate_solo': 0.515625}, 'flex': {'Champion_flex': 'Sylas', 'Winrate_flex': 0.6056338028169014}} je rentre dans submit Récupération des statistiques en classés

127.0.0.1 - - [16/Oct/2023 18:06:41] "GET /static/Sylas.png HTTP/1.1" 200 -

Récupération des parties classés Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Récupération des parties classés Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds Rate Limit hit, sleeping for 10 seconds

127.0.0.1 - - [16/Oct/2023 18:11:06] "GET /submit?nm=nicpsy HTTP/1.1" 200 -

le pseudo du site nicpsy {'solo': {'Champion_solo': 'Sylas', 'Winrate_solo': 0.515625}, 'flex': {'Champion_flex': 'Sylas', 'Winrate_flex': 0.6056338028169014}} Sylas Sylas 52 61 pseudo= nicpsy lvl= 208 rank solo PLATINUM IV 0 rank flex EMERALD II 0 icone solo platine icone flex emeraude icone joueur 6271

Voici ce que l'on obtient

Exemple homepage Exemple seerank Exemple result

Ce que j'ai prévu pour le second point POK

Ce que j'ai fait à la fin du temps 1

Présentation des pages de l'application :

Page d'accueil

Les 3 icones forment une barre de navigation, il faut cliquer sur le jeu désiré.

samy gg leo

Page du jeu TFT

samy gg leo

Page du jeu Valorant

samy gg leo

Page du jeu League of Legends

samy gg leo

Comparaison avec des statistiques issues du site OP.GG

samy gg leo

Comparaison avec le site op.gg qui permet d'avoir des statistiques : samy gg leo samy gg leo

On peut voir sur le site que les données coincident bien !

Pour un autre joueur :

samy gg leo

samy gg leo samy gg leo

Conclusion

Je suis assez content du résultat obtenu, mais je n'ai clairement pas réussi à estimer mon temps correctement car j'ai passé beaucoup plus de temps que prévu sur ce premier POK. En revanche, cela m'a permis d'aller plus loin que prévu donc je ne pense pas continuer sur ce sujet.