프로젝트/빅데이터분석 기말 프로젝트

롤 분류기 (1) - 라이엇 api를 사용해 정보를 긁어보자.

AI쟁이J 2022. 5. 26. 01:17

gold_user1.csv
0.89MB

 

 

라이엇 API

빅데이터 분석 시간에 배웠던 서비스의 오픈 API를 사용할 수 있는 DEVELOPER 홈페이지. 나같은 밥도 이 페이지에 들어오면 DEVELOPER 라는 이미지 덕분에 라이엇이 인정해 준 개발자 된 것 같기도 하고 뭐 그렇다.

 

다양한 정보를 긁어올 수 있는 API 페이지가 있는데, 구글에 검색해 봐도 잘 이해가 안가서 그냥 직접 박치기로 몇개를 해 보니 대충 감이 잡혔다. 소환사 정보부터 한 게임의 구체적인 모든 내역이 다 정리가 되어있다. 롤 짬밥 10년덕에 어떤 데이터들을 어떻게 불러올 수 있는지 파악하기가 쉬웠다. 역시 도메인 지식이 중요하다.

 

아무튼 나의 계획은 

구글에서 검색하면 예제로 많이 나오는 챌, 그마, 마스터 등의 상위 티어 유저 알아보기! (1명의 정보만) 뭐 이런게 아니라 내가 속한 지극히 평범하고 못하는 구간인 골드에서 소환사 정보를 끌어오고, 그들의 승/패/cs/킬/데스 등의 데이터를 모아서 잘하는 사람인지, 벌레인지 구별할 것이다. 이 아이디어는 늘 게임을 시작하기 전 팀 아이디를 포우에 긁고, 최근 전적의 킬/데스와 전체 승/패를 슥 보면서 아 닷지할까... 고민하던 내가 생각이 나 이걸 좀 더 체계화 하고 싶었기에 떠올랐다.

하지만 이 데이터들은 쉽게 모여있지 않았고, 당장 어떻게 구해야할지 엄청 헤맸다. 그리고 여러모로 고민 끝에 도달한 수집 방법은

 

1. LEAGUE-EXP-V4 API에서 골드 구간의 리그에 속한 소환사들의 정보를 긁어온 후, 소환사 이름, 승, 패 정보를 모두 긁는다. 

2. 이를 SUMMONER-V4 API에서 소환사 명을 통해 검색 후 PUUID를 획득한다.

3. PUUID를 이용해 MATCH-V5 API에서 그 소환사의 고유 아이디에 담긴 매치 데이터를 수집, 자세한 그 사람의 전적을 수집한다.

 

SQL을 공부할 때 DB에 속한 데이터들이 꼭 여러 카테고리에 나누어 담겨져 있어서 그걸 통해 join을 시키면서 결국 내가 원하는 정보의 집합으로 구현하는 일을 많이 했었는데, 딱 그 느낌이 들었다. 

 

그럼 우선 1번부터 하기 위해 코드를 짜자.

 

import requests
import pandas as pd
import numpy as np

api_key = 'RGAPI-a2fce775-b3f1-4146-ad8a-e5c5ecb3a9cf'

tiers = ['I', 'II', 'III', 'IV']
user_list = []

for tier in tiers:
    for page in range(1,11):
        user_url = "https://kr.api.riotgames.com/lol/league-exp/v4/entries/RANKED_SOLO_5x5/GOLD/{}?page={}".format(tier, page)
        r = requests.get(user_url, headers = {"X-Riot-Token":api_key})
        df = pd.DataFrame(r.json())
        user_list.append(df)

 

페이지 수를 1 ~ 100으로 지정했었는데 데이터가 20만개 가까이 나왔다. 물론 당연히 롤의 유저에 비하면 티끌같지만, 그래도 좀 심각하게 많았다. 그래서 1 ~ 10페이지씩 골드 1,2,3,4 구간으로 수집하기로 했고 약 8200개가 나와서 적당하다고 생각했다. 이 정도의 표본으로 수십만의 골드 모집단에 대표성이 있을진 솔직히 모르겠지만.. 후에 있을 puuid 수집 과정이 더 많다면 아예 불가능하다. 그러게 사람 좀 적은 다이아라도 갈걸;;;

 

아 그리고 for문 두 개 쓴 것에 나름 내 스스로 흡족했다. 솔직히 교수님이 짜주신 코드 말고 직접 짜는 경우는 거의 처음이다... 그래서 골드 1,2,3,4  하나하나 다 모으고 그걸 골드1 df, 골드2 df 등으로 만들고 concat 하는 방식으로 골드 df를 완성시키려 했는데, 참.. 노가다고 한심했다. 그래서 고민 끝에 티어 변수를 담고, url에서 그것도 바로바로 I ~ IV 까지 수집하도록 format()을 써서 구현했고 컴퓨터가 알아서 I 10페이지 ~ IV 10페이지 수집해줬다. 발전했다!

 

 

gold_user_df = pd.concat(user_list)
gold_user_df.reset_index(drop = True, inplace = True)

new_df = gold_user_df.drop(['leagueId', 'queueType', 'veteran','inactive','freshBlood','hotStreak','miniSeries', 'summonerId'], axis = 1)
new_df #추후 승/패 데이터로 쓸 것

 

pd.concat(user_list)는 구글에서 봤는데, 위의 데이터들은 모두 user_list 에 list의 형태로 쌓인다. 그래서 이걸 일일이 df로 변환하고, 이 df들을 모두 concat해서 완성하는 방식을 하려 했는데, 일단 오류가 났다. 그래서 다른 방법을 찾았는데 애초에 user_list라는 리스트에 df의 형식으로 df의 형태를 가진 변수들이 하나하나의 list로 쌓이도록? 저장을 한 후, 여기에 pd.concat()을 그냥 하면 알아서 df형식으로 바뀐다. 신기했다. 그리고 이 방법이 훨씬 효율적이며, 메모리를 적게 사용한다고 하더라. 오류 해결하려다 효율적인 코드를 짰다. 굿

 

리그라고 롤 틀딱들은 아는 '자이라의 공성병들' '블리츠크랭크의 노예들' 뭐 이런 이름들이 있는데, 지금은 보기가 어려운데 아마 시스템상으로는 남아있는 것 같다. 그래서 수집한 데이터에 그 리그에 오래 있던 베테랑인지, 뭐 이런 변수들이 있었는데 쓸모없는 데이터라 모두 drop했다.

 

 

 

알짜배기 정보만 남음.

그리고 이 df의 summonerName이 내 목표였다. 그래서 이걸 모두 수집.

gold_user_name = new_df['summonerName'].tolist()
len(gold_user_name)

8200개 맞다. 내가 롤하면서 만나본 애들도 있을 듯 하다.

 

이제 이걸 통해 SUMMONER-V4 API에서 캐야하는데.. 이게 문제가 복잡하다.

위의 정보는 I ~ IV까지 10페이지, 즉 페이지 당 소환사 정보가 약 200개 가까이 들어가 있어서 한번의 API 요청으로 200개가 넘는 데이터가 불러졌다. 그래서 사실상 40번의 요청으로 저만큼의 8200개의 정보가 수집이 되었는데, 여기서 해야할 일은 8200개의 각 소환사 이름을 모두 API 요청을 해서 puuid를 따와야 한다. 8200개의 요청을 보내는 셈.

근데 라이엇은 1초에 20개, 2분에 100개씩 요청 제한을 두고 있다. 

이래서 8200개의 데이터밖에 현실적으로 수집할 수 밖에 없다.. 8200개면 82x2 = 164분이 걸린다. 2시간 44분..

 

 

from urllib import parse
import time

puuid = []

for user in gold_user_name:
    encod = parse.quote(user)
    summoner_url = "https://kr.api.riotgames.com/lol/summoner/v4/summoners/by-name/{}".format(encod)
    r = requests.get(summoner_url, headers = {"X-Riot-Token":api_key})
    if len(r.json()) < 5:  # 찾아지지 않는 경우 NA로 대체
        puuid.append(np.nan)
    else:
        puuid.append(r.json()['puuid'])
    time.sleep(0.9)

그래서 했다. 

parse.quote() 함수에 대해 알게 되었는데, 한글 이름들을 구글에 치면 %E42%F42% 뭐시기 이렇게 변환되는 경우를 자주 봤는데 이걸 해주는 함수이다. 한글 소환사 이름들을 API에 저 꼴로 변환해서 요청해준다.

여기서도 나의 코딩에 흡족했는데, 바로 if문이다. 처음에 에러가 계속 나서 나는 요청을 너무 많이 해서 그런 줄 알았다. 그래서 time.sleep(0.9)를 통해 딱 2분에 100개 안 넘게 조절을 해도 났다. 근데 계속 에러가 났을 때 92개씩만 정보가 담기길래 92번째 아이디를 검색 후, 직접 api 페이지에 넣어보니 {status : 404} 하면서 없는 소환사 정보라고 나왔다. 이 때의 r.json() 의 길이가 저 변수 하나로 1이기에 그런 경우에는 오류로 멈추지 말고 np.nan으로 리스트를 채우라고 코딩했다.

time.sleep(0.9)를 걸고... 비장한 마음으로 run 하고, 롤했다. 롤 데이터 수집하는거니까 ㅇㅇ.. 3판 하고 오니까 데이터가 다 담겼다.

 

 

new_df['puuid'] = puuid
new_df = new_df.dropna()
new_df.to_csv('gold_user1.csv')

 

내 2시간 30분이 사라지지 않게끔 바로 df에 새 열로 합친 후, 여기엔 없지만 isnull().sum() 으로 nan처리된 데이터 확인하니까 249개였다. 그래서 puuid없으면 어차피 쓸모 없으므로 제거하고, 빨리 csv로 저장했다. 첨부파일에 7896명의 정보가 있다. 박제다.