調べ物した結果

現役SEが仕事と直接関係ないことを調べた結果とか感想とか

RiotGamesAPIをつかって、直近の対戦履歴をヒットさせてみる。

何するの?

とあるネットゲーム。LOL ※1の対戦履歴等がAPIから取得できるらしいので、実際にやってみた。

つかったAPI

RiotGamesAPI
https://developer.riotgames.com/
に公開されている。完全に充実。とはいい難いけど、適当にごにょごにょする分には申し分ない。

取得の構想

・RiotGamesAPIのAPIKEYを取得する。
・SummonerAPIでサモナーネーム ※2からaccountIDを取得する
・取得したaccountIDでMatchAPIを利用して対戦履歴を取得する。

RiotGamesAPIのAPIKEYを取得する。

https://developer.riotgames.comにアクセスすると、
とりあえずLOLのアカウントでログインを促されるのでログインする。(リージョン選択に気を付けて!)

そうすると下の画面にとばされる。
f:id:couraeg:20190817105007p:plain

英語の画面だけど臆することはない。ただKEYが生成されるので、中央のKEYをメモ帳にでもコピペしておいて
控えておくだけでいい(あとで確認することもできる)
KEYの有効期間が1日ぐらいで切れるので、日にちを開けて作業する場合は下のほうのregenerateで、
KEYを再生成しよう。

Summoner APIからaccountIDを取得する。

APIKEYがゲットできたので、これで無事APIを使用することができる。

APIをブラウザ上で実行してみる。

APIの応答と、使用方法を確認するためにAPI REFERENCEを確認する。画面上部の
API DOCUMENTATION」から「FULL API REFERENCE」を選択する。
f:id:couraeg:20190817105330p:plain
ここから、
f:id:couraeg:20190817105510p:plain
ここにとぶ。
画面左側のリストが使用できるAPIとなっている。
今使いたいのはSummoner-V4なので、選択する。
f:id:couraeg:20190817110022p:plain

by-account,by-name,by-puuidと、Summoner情報を取得するためのKEYが複数種類用意されている。
が、このうち普段理解して使用しているのはSummoner-nameなので、今回はSummoner-nameを使用する。
GETの部分をクリックするとAPIの詳細が開かれる。
DTOの中に「AccountID」が含まれているのがわかる。
f:id:couraeg:20190817110321p:plain

コードを組むうえではここまでの情報で十分。
イメージをつかむために実際に画面で動作させることもできる。
画面下部までスクロールして、APIを実行してみよう。
f:id:couraeg:20190817110717p:plain

パラメータを設定して(couraegは私のサマナーネーム)
Execute requestで実行すると・・・
f:id:couraeg:20190817200644p:plain

ざんねん。「403」がでた。どうやら記事を書いている途中で
APIKEYの有効期限が切れてしまったようだ。

そういう時は諦めてAPIKEYをRegenateしよう。
f:id:couraeg:20190817200021p:plain
ダッシュボードからregenateして・・・
f:id:couraeg:20190817200118p:plain
再度同様の手順でやってみると、以下のような結果が得られる。
f:id:couraeg:20190817200500p:plain

無事実行できた。めでたしめでたし。

SummonerAPIでサモナーネーム ※2からaccountIDを取得する

ソースをはっつけるのがはやい。

Reader_Base.py

import unittest
import urllib.request as urllib2
import json

class Reader_Base():
    def __init__(self, api_key):
        print("Reader_Base.py:__init__")
        self._api_key = "api_key=" + api_key
        self._api_url = ""  # setting by overrided class.
    def get(self, last_path):
        """
        get api access result.

        Parameters
        ----------
        last_path : str
            api access last path.
        
        Eaxample
        --------
        case : api-summoner access whne search by summoner name.
            self._api_url=https://jp1.api.riotgames.com/lol/summoner/v4/summoners/
            last_path=by-name/[summoner-name]
            api access url = https://jp1.api.riotgames.com/lol/summoner/v4/summoners/by-name/[summoner-name] with api key
        """
        print("Reader_Base.py:get")
        url =  self._create_url(last_path)

        with self._get_url_session(url) as f:
            ret = self._jsonLoad(f,'utf-8')

        return ret

    def _jsonLoad(self, session, character_map):
        """       
        read session to Json.
        """
        print("Reader_Base.py:_jsonLoad")
        return json.loads(session.read().decode(character_map))

    def _get_url_session(self, url):
        """
        open url sesssion.

        Returns
        -------
        opened session.
        """

        print("Reader_Base.py:_get_url_session")
        return urllib2.urlopen(url)
        
    def _create_url(self, lastPath):
        """
        craete api access url.
        """
        print("Reader_Base.py:_create_url")
        url = self._api_url
        url += lastPath
        url += "?"
        url += self._api_key
        return url

コメントの英語は許してほしい。
こいつは既定のクラスそのまま使う予定はない。
メインのsummonerクラスの実装は↓。

summoner_reader.py

from . import info
from .. import reader_base 

class Reader(reader_base.Reader_Base):    
    def __init__(self, api_key):
        print("Summoner.Reader.py:__init__")
        self._api_key = "api_key=" + api_key
        self._api_url = "https://jp1.api.riotgames.com/lol/summoner/v4/summoners/"

    def get_by_summoner(self, summoner_name):
        print("Summoner.Reader.py:get")      
        lastpath = "by-name/" + summoner_name

        return info.Info(self.get(lastpath))

そのままjsonで扱うのは色々と不都合が起きそうなので、
ひとまずクラスにぶちこんでおいた

info.py

class Info():
    def __init__(self, summoner_dto):
        self._dto = summoner_dto

    @property
    def profile_Icon_Id(self):
        return self._dto["profileIconId"]

    @property
    def name(self):
        return self._dto["name"]

    @property
    def puuid(self):
        return self._dto["puuid"]

    @property
    def summoner_level(self):
        return self._dto["summonerLevel"]

    @property
    def revision_date(self):
        return self._dto["revisionDate"]

    @property
    def id(self):
        return self._dto["id"]

    @property
    def account_id(self):
        return self._dto["accountId"]

今回使うのはaccountIDだけだけど。
summonerのaccountIDを取得する準備はこれで終わり。

取得したaccountIDでMatchAPIを利用して対戦履歴を取得する。

基本の手順はsummnerと同様。こーどだけぺたぺた.

match_reader.py

from . import match_list
from .. import reader_base

class Reader(reader_base.Reader_Base):
    def __init__(self, api_key):
        print("Match.Reader.py:__init__")
        self._api_key = "api_key=" + api_key
        self._api_url = "https://jp1.api.riotgames.com/lol/match/v4/matchlists/"
    
    def get_by_account_id(self, account_id):
        print("Match.Reader.py:get")
        last_path = "by-account/" + account_id

        return match_list.Match_List(self.get(last_path))

match_list.py

from . import match_reference

class Match_List():
    def __init__(self, match_list_dto):
        self._dto = match_list_dto        
        
    @property
    def matches(self):
        ret = []
        for value in self._dto["matches"]:
            ret.append(match_reference.Match_Reference(value))
        return ret

    @property
    def total_games(self):
        return self._dto["totalGames"]

    @property
    def start_index(self):
        return self._dto["startIndex"]

    @property
    def end_index(self):
        return self._dto["endIndex"]    

マッチの詳細はリスト形式(最大100件)で帰ってくる(matchs)。
1件ずつは別のDTOなので、クラスも合わせて分解。

match_reference

class Match_Reference():
    def __init__(self, match_reference_dto):
        self._dto = match_reference_dto

    @property
    def lane(self):
        return self._dto["lane"]

    @property
    def game_id(self):
        return self._dto["gameId"]

    @property
    def champion(self):
        return self._dto["champion"]

    @property
    def platform_id(self):
        return self._dto["platformId"]

    @property
    def session(self):
        return self._dto["session"]

    @property
    def queue(self):
        return self._dto["queue"]

    @property
    def role(self):
        return self._dto["role"]

    @property
    def timestamp(self):
        return self._dto["timestamp"]

これでした準備は完了。

実際に使う場合のサンプル

import sys
import unittest
import urllib.request as urllib2
import json
import public.packages.api as api

class MyFirstAPI():
    def __init__(self,api_key, summoner_name):
        self._api_key = api_key
        self._summoner_name = summoner_name

    def get_summoner_name(self):
        summoner_reader =  api.summoner.summoner_reader.Reader(self._api_key)
        suminfo = summoner_reader.get_by_summoner(self._summoner_name)
        match_reader = api.match.match_reader.Reader(self._api_key)       
        matchs = match_reader.get_by_account_id(suminfo.account_id)
        print(matchs.total_games)

実行時にAPI_KEYを指定して実行するだけ。このサンプルコードなら
指定したサモナーネームの合計ゲーム数がprintされる。

github.com


以上。


※1 LOL-Legue of Legends
10年前、当時の友人たちに誘われてから今までやっている、世界的に知名度がある(はず)
のゲーム。基本無料なのでやりませう

※2 サモナーネーム
LOL内で使用するアカウント名のようなもの。