데이터 분석/파이썬

롤 API 활용 예시(LEAGUE-V4, MATCH-V5)

쎄마비 2022. 6. 29. 12:00
728x90
반응형

공부 삼아 리그 오브 레전드 api를 활용해 데이터를 받아 이리저리 만져보았습니다.

여러 날에 걸쳐서 조금씩 진행한 터라 중간중간 정리가 안 된 코드도 있으니 혹시 안 되시는 부분이 있으면 레퍼런스 페이지를 참고해주세요.

 

이 페이지에서는 밀리고 있던 게임에서 승리한 팀은 어떤 전략을 사용했는지 확인해보았습니다.

전체적인 진행 순서는 다음과 같습니다.

 

  1. API key 발급
  2. 데이터 추출
  3. JSON 내 필요한 데이터 데이터프레임화
  4. timeline 로그 데이터 동일하게 작업
  5. 3, 4번 데이터 통합해서 PCA 및 분류분석
  6. 레퍼런스

 

1. API key 발급

 

api를 통해 데이터를 받아보기 위해서는 먼저 아래 페이지에서 로그인한 뒤 api key를 발급받아야 합니다.

 

 

Riot Developer Portal

About the Riot Games API With this site we hope to provide the League of Legends developer community with access to game data in a secure and reliable way. This is just part of our ongoing effort to respond to players' and developers' requests for data and

developer.riotgames.com

 

링크를 통해 Riot Developer Portal에 접속한 뒤 우측 상단 로그인 버튼을 눌러서 로그인 후 다시 우측 상단의 이름을 눌러 드롭다운 메뉴를 엽니다.

나타난 메뉴 중 첫 번째 DASHBOARD를 누르면 나타나는 페이지에서 API key를 발급받을 수 있습니다.

API KEY 발급 화면

 

 

API KEY는 24시간마다 만료되며 REGENERATE API KEY 버튼을 누르면 새로운 키를 발급받을 수 있습니다.

또한 RATE LIMITS에 기재된 것처럼 요청을 보내는 횟수가 제한되어 있으니 꼭 참고하세요!

 

2. 데이터 추출

2-1. 패키지 불러오기 

import requests
import json
import time
import pandas as pd
from tqdm import tqdm

api_key = '발급받은 api key 붙여넣기'

 

2-2. 유저 데이터 불러오기(summoner id, puuid)

# 마스터 등급 솔로 랭크 게임을 플레이한 플레이어의 summoner id 추출
url = 'https://kr.api.riotgames.com/lol/league/v4/masterleagues/by-queue/RANKED_SOLO_5x5?api_key=' + api_key

summonerId = {}

r = requests.get(url)
r = r.json()['entries']

num = 0

for i in r:
    summonerId[i['summonerName']] = i['summonerId']
    num += 1
print(num)

# summonerId를 통해 puuid 추출

puuid = {}

for i,j in zip(tqdm(summonerId.values()),summonerId.keys()):
    url2 = 'https://kr.api.riotgames.com/lol/summoner/v4/summoners/' + i + '?api_key=' + api_key
    r = requests.get(url2)
    
    if r.status_code == 200: 
        pass
    
    elif r.status_code == 429:
        print('api cost full : infinite loop start')
        print('loop location : ',i)
        start_time = time.time()
        
        while True:
            if r.status_code == 429:

                print('try 120 second wait time')
                time.sleep(120)

                r = requests.get(url2)
                print(r.status_code)

            elif r.status_code == 200:
                print('total wait time : ', time.time() - start_time)
                print('recovery api cost')
                break
                
df_puuid = pd.DataFrame(puuid, index = [0])
df_puuid = df_puuid.T
df_puuid = df_puuid.reset_index()
df_puuid.columns = ['id','puuid']

 

2-3. 최근 플레이한 5개 게임의 match id 추출하기

matchId = []
for i in tqdm(df_puuid['puuid']):

	#count=5의 숫자를 바꾸면 경기 수가 달라집니다
    url_match = 'https://asia.api.riotgames.com/lol/match/v5/matches/by-puuid/'+ i +'/ids?start=1&count=5&api_key='+api_key
    r_match = requests.get(url_match)

    if r_match.status_code == 200:
        pass

    elif r_match.status_code == 429:
        print('api cost full : infinite loop start')
        print('loop location : ',i)
        start_time = time.time()

    matchId.extend(requests.get(url_match).json())
len(matchId)

# 중복 제거
match_set = set(matchId)
match_list = list(match_set)
len(match_list)

 

2-4. 게임별 정보 추출하여 JSON으로 저장하기

matchdata = {}
        
num = 0

for i in tqdm(match_list):

    if num%7 == 0:
        time.sleep(4)
    elif num%100 == 0:
        print('Wait 121s')
        time.sleep(121)   
        
    num += 1
    url4 = 'https://asia.api.riotgames.com/lol/match/v5/matches/' + str(i) +'?api_key=' + api_key
    r = requests.get(url4)

    if r.status_code == 200: 
        pass

    elif r.status_code == 429:
        print('api cost full : infinite loop start')
        print('loop location : ',i)
        start_time = time.time()

        while True: 
            if r.status_code == 429:

                print('try 120 second wait time')
                time.sleep(120)

                r = requests.get(url2)
                print(r.status_code)

            elif r.status_code == 200: 
                print('total wait time : ', time.time() - start_time)
                print('recovery api cost')
                break
                             
    try:
        r = r.json()['info']['participants']
        matchdata[i] = r
    except:
        print("기타 에러")
        
with open('./matchdata.json','w') as f:
  json.dump(matchdata, f, ensure_ascii=False, indent=4)

 

3. JSON 내 필요한 데이터 데이터프레임화

# 빈 데이터프레임 만들기

temp_df = pd.DataFrame(columns=['no','gameNo','playerNo','assists',
 'baronKills',
 'bountyLevel',
 'champExperience',
 'champLevel',
 'championId',
 'championName',
 'championTransform',
 'consumablesPurchased',
 'damageDealtToBuildings',
 'damageDealtToObjectives',
 'damageDealtToTurrets',
 'damageSelfMitigated',
 'deaths',
 'detectorWardsPlaced',
 'doubleKills',
 'dragonKills',
 'eligibleForProgression',
 'firstBloodAssist',
 'firstBloodKill',
 'firstTowerAssist',
 'firstTowerKill',
 'gameEndedInEarlySurrender',
 'gameEndedInSurrender',
 'goldEarned',
 'goldSpent',
 'individualPosition',
 'inhibitorKills',
 'inhibitorTakedowns',
 'inhibitorsLost',
 'item0',
 'item1',
 'item2',
 'item3',
 'item4',
 'item5',
 'item6',
 'itemsPurchased',
 'killingSprees',
 'kills',
 'lane',
 'largestCriticalStrike',
 'largestKillingSpree',
 'largestMultiKill',
 'longestTimeSpentLiving',
 'magicDamageDealt',
 'magicDamageDealtToChampions',
 'magicDamageTaken',
 'neutralMinionsKilled',
 'nexusKills',
 'nexusLost',
 'nexusTakedowns',
 'objectivesStolen',
 'objectivesStolenAssists',
 'participantId',
 'pentaKills',
 'physicalDamageDealt',
 'physicalDamageDealtToChampions',
 'physicalDamageTaken',
 'profileIcon',
 'puuid',
 'quadraKills',
 'riotIdName',
 'riotIdTagline',
 'role',
 'sightWardsBoughtInGame',
 'spell1Casts',
 'spell2Casts',
 'spell3Casts',
 'spell4Casts',
 'summoner1Casts',
 'summoner1Id',
 'summoner2Casts',
 'summoner2Id',
 'summonerId',
 'summonerLevel',
 'summonerName',
 'teamEarlySurrendered',
 'teamId',
 'teamPosition',
 'timeCCingOthers',
 'timePlayed',
 'totalDamageDealt',
 'totalDamageDealtToChampions',
 'totalDamageShieldedOnTeammates',
 'totalDamageTaken',
 'totalHeal',
 'totalHealsOnTeammates',
 'totalMinionsKilled',
 'totalTimeCCDealt',
 'totalTimeSpentDead',
 'totalUnitsHealed',
 'tripleKills',
 'trueDamageDealt',
 'trueDamageDealtToChampions',
 'trueDamageTaken',
 'turretKills',
 'turretTakedowns',
 'turretsLost',
 'unrealKills',
 'visionScore',
 'visionWardsBoughtInGame',
 'wardsKilled',
 'wardsPlaced',
 'win'])
 
 
# for 문으로 데이터 추출
i=0
for j in tqdm(list(matchdata.keys())):
    for k in range(0,10):
        temp_df.loc[i*10+k] = [i, j, k, matchdata[j][k]["assists"],
                                     matchdata[j][k]["baronKills"],
                                     matchdata[j][k]["bountyLevel"],
                                     matchdata[j][k]["champExperience"],
                                     matchdata[j][k]["champLevel"],
                                     matchdata[j][k]["championId"],
                                     matchdata[j][k]["championName"],
                                     matchdata[j][k]["championTransform"],
                                     matchdata[j][k]["consumablesPurchased"],
                                     matchdata[j][k]["damageDealtToBuildings"],
                                     matchdata[j][k]["damageDealtToObjectives"],
                                     matchdata[j][k]["damageDealtToTurrets"],
                                     matchdata[j][k]["damageSelfMitigated"],
                                     matchdata[j][k]["deaths"],
                                     matchdata[j][k]["detectorWardsPlaced"],
                                     matchdata[j][k]["doubleKills"],
                                     matchdata[j][k]["dragonKills"],
                                     matchdata[j][k]["eligibleForProgression"],
                                     matchdata[j][k]["firstBloodAssist"],
                                     matchdata[j][k]["firstBloodKill"],
                                     matchdata[j][k]["firstTowerAssist"],
                                     matchdata[j][k]["firstTowerKill"],
                                     matchdata[j][k]["gameEndedInEarlySurrender"],
                                     matchdata[j][k]["gameEndedInSurrender"],
                                     matchdata[j][k]["goldEarned"],
                                     matchdata[j][k]["goldSpent"],
                                     matchdata[j][k]["individualPosition"],
                                     matchdata[j][k]["inhibitorKills"],
                                     matchdata[j][k]["inhibitorTakedowns"],
                                     matchdata[j][k]["inhibitorsLost"],
                                     matchdata[j][k]["item0"],
                                     matchdata[j][k]["item1"],
                                     matchdata[j][k]["item2"],
                                     matchdata[j][k]["item3"],
                                     matchdata[j][k]["item4"],
                                     matchdata[j][k]["item5"],
                                     matchdata[j][k]["item6"],
                                     matchdata[j][k]["itemsPurchased"],
                                     matchdata[j][k]["killingSprees"],
                                     matchdata[j][k]["kills"],
                                     matchdata[j][k]["lane"],
                                     matchdata[j][k]["largestCriticalStrike"],
                                     matchdata[j][k]["largestKillingSpree"],
                                     matchdata[j][k]["largestMultiKill"],
                                     matchdata[j][k]["longestTimeSpentLiving"],
                                     matchdata[j][k]["magicDamageDealt"],
                                     matchdata[j][k]["magicDamageDealtToChampions"],
                                     matchdata[j][k]["magicDamageTaken"],
                                     matchdata[j][k]["neutralMinionsKilled"],
                                     matchdata[j][k]["nexusKills"],
                                     matchdata[j][k]["nexusLost"],
                                     matchdata[j][k]["nexusTakedowns"],
                                     matchdata[j][k]["objectivesStolen"],
                                     matchdata[j][k]["objectivesStolenAssists"],
                                     matchdata[j][k]["participantId"],
                                     matchdata[j][k]["pentaKills"],
                                     matchdata[j][k]["physicalDamageDealt"],
                                     matchdata[j][k]["physicalDamageDealtToChampions"],
                                     matchdata[j][k]["physicalDamageTaken"],
                                     matchdata[j][k]["profileIcon"],
                                     matchdata[j][k]["puuid"],
                                     matchdata[j][k]["quadraKills"],
                                     matchdata[j][k]["riotIdName"],
                                     matchdata[j][k]["riotIdTagline"],
                                     matchdata[j][k]["role"],
                                     matchdata[j][k]["sightWardsBoughtInGame"],
                                     matchdata[j][k]["spell1Casts"],
                                     matchdata[j][k]["spell2Casts"],
                                     matchdata[j][k]["spell3Casts"],
                                     matchdata[j][k]["spell4Casts"],
                                     matchdata[j][k]["summoner1Casts"],
                                     matchdata[j][k]["summoner1Id"],
                                     matchdata[j][k]["summoner2Casts"],
                                     matchdata[j][k]["summoner2Id"],
                                     matchdata[j][k]["summonerId"],
                                     matchdata[j][k]["summonerLevel"],
                                     matchdata[j][k]["summonerName"],
                                     matchdata[j][k]["teamEarlySurrendered"],
                                     matchdata[j][k]["teamId"],
                                     matchdata[j][k]["teamPosition"],
                                     matchdata[j][k]["timeCCingOthers"],
                                     matchdata[j][k]["timePlayed"],
                                     matchdata[j][k]["totalDamageDealt"],
                                     matchdata[j][k]["totalDamageDealtToChampions"],
                                     matchdata[j][k]["totalDamageShieldedOnTeammates"],
                                     matchdata[j][k]["totalDamageTaken"],
                                     matchdata[j][k]["totalHeal"],
                                     matchdata[j][k]["totalHealsOnTeammates"],
                                     matchdata[j][k]["totalMinionsKilled"],
                                     matchdata[j][k]["totalTimeCCDealt"],
                                     matchdata[j][k]["totalTimeSpentDead"],
                                     matchdata[j][k]["totalUnitsHealed"],
                                     matchdata[j][k]["tripleKills"],
                                     matchdata[j][k]["trueDamageDealt"],
                                     matchdata[j][k]["trueDamageDealtToChampions"],
                                     matchdata[j][k]["trueDamageTaken"],
                                     matchdata[j][k]["turretKills"],
                                     matchdata[j][k]["turretTakedowns"],
                                     matchdata[j][k]["turretsLost"],
                                     matchdata[j][k]["unrealKills"],
                                     matchdata[j][k]["visionScore"],
                                     matchdata[j][k]["visionWardsBoughtInGame"],
                                     matchdata[j][k]["wardsKilled"],
                                     matchdata[j][k]["wardsPlaced"],
                                     matchdata[j][k]["win"]]
    i += 1

 

4. timeline 로그 데이터 동일하게 작업

 

이제 만들어진 데이터프레임을 가지고 자유롭게 활용하시면 됩니다.

검색해보니 승리를 예측하는 모델을 만드는 등등 다양한 활용 예시가 있었는데요.

이번에는 MATCH-V5의 timeline에서 받을 수 있는 로그 데이터를 추가로 활용해보기 위해서 먼저 사용한 것과 같은 방식으로 JSON 파일을 거쳐 데이터프레임을 만들었습니다.

 

4.1 timeline 데이터 JSON으로 추출하기

matchdata = {}
        
num = 0

for i in tqdm(matchlist):

    if num%100 != 0:
        time.sleep(1)
    elif num%100 == 0:
        print('Wait 121s')
        time.sleep(121)
    
        
    num += 1
    url = 'https://asia.api.riotgames.com/lol/match/v5/matches/' + str(i) +'/timeline/?api_key=' + api_key
    r = requests.get(url)

    if r.status_code == 200:
        pass

    elif r.status_code == 429:
        print('api cost full : infinite loop start')
        print('loop location : ',i)
        start_time = time.time()

        while True:
            if r.status_code == 429:

                print('try 120 second wait time')
                time.sleep(121)

                r = requests.get(url)
                print(r.status_code)

            elif r.status_code == 200:
                print('total wait time : ', time.time() - start_time)
                print('recovery api cost')
                break
                
                
    try:
        r = r.json()['info']['frames']
        matchdata[i] = r
    except:
        print("기타 에러")
        
 with open('./timedata_all.json','w') as f:
  json.dump(matchdata, f, ensure_ascii=False, indent=4)

 

4-2. JSON 내 필요한 데이터 데이터프레임화

df_gap = pd.DataFrame(columns = ['gameId', 'timestamp', 'blue_kill', 'red_kill'])
for i in tqdm(json_data.keys()):
  blue_kill = 0
  red_kill = 0
  for j in range(0, len(json_data[i])):
    if len(json_data[i][j]['events']) > 1:
      for k in range(0, len(json_data[i][j]['events'])):
        if json_data[i][j]['events'][k]['type'] == 'CHAMPION_KILL':
          if json_data[i][j]['events'][k]['killerId'] <= 5:
            blue_kill += 1
          elif json_data[i][j]['events'][k]['killerId'] > 5:
            red_kill += 1
          if abs(blue_kill-red_kill) > 5:
            df_gap.loc[len(df_gap)] = [i, json_data[i][j]['events'][k]['timestamp'], blue_kill, red_kill]

    elif len(json_data[i][j]['events']) == 1:
      k = 0
      if json_data[i][j]['events'][k]['type'] == 'CHAMPION_KILL':
        if json_data[i][j]['events'][k]['killerId'] <= 5:
          blue_kill += 1
        elif json_data[i][j]['events'][k]['killerId'] > 5:
          red_kill += 1
        if abs(blue_kill-red_kill) > 5:
          df_gap.loc[len(df_gap)] = [i, json_data[i][j]['events'][k]['timestamp'], blue_kill, red_kill]

 

4-3. 킬 차이 5 이상을 임의의 조건으로 두어 특정 게임 추려내기

df_gap['red_lead'] = df_gap['blue_kill'] - df_gap['red_kill'] < 0
df_gap['blue_lead'] = df_gap['blue_kill'] - df_gap['red_kill'] > 0

# 플레이어별 데이터를 게임별로 합산
df_t = df_gap.groupby('gameId')[['timestamp']].count()
df_b = df_gap.groupby('gameId')[['blue_kill']].sum()
df_r = df_gap.groupby('gameId')[['red_kill']].sum()
df_rl = df_gap.groupby('gameId')[['red_lead']].sum()
df_bl = df_gap.groupby('gameId')[['blue_lead']].sum()
df_pivot = pd.concat([df_t,df_b,df_r, df_rl, df_bl], axis = 1)

# 형식 변경
df_pivot['turnovers'] = (df_pivot['red_lead'] > 0) & (df_pivot['blue_lead'] > 0)
df = df_pivot[['red_lead', 'blue_lead', 'turnovers']]
df.reset_index(drop = False, inplace = True)

# 팀 별로 데이터 형식 다시 변경
df_tov = pd.DataFrame(columns = ['gamdId','teamID', 'leads', 'turnovers'])
k = 0	
for i in df['gameId']:	
	df_tov.loc[k] = [i, 100, df.iloc[df.index[(df['gameId'] == i)][0]]['blue_lead'], df.iloc[df.index[(df['gameId'] == i)][0]]['turnovers']]
	df_tov.loc[k+1] =  [i, 200, df.iloc[df.index[(df['gameId'] == i)][0]]['red_lead'], df.iloc[df.index[(df['gameId'] == i)][0]]['turnovers']]
	k += 2

 

 

5. PCA 및 분류분석

 

분류분석 코드는 사라져 PCA까지만 남겨둡니다.

분석 결과 킬 수가 밀리던 팀이 역전한 경기에서는 바론 위주의 전략이 가장 유효한 것으로 나타났습니다. 이외에는 잘 죽지 않는 것, 경기 시간이 길어지는 것이 중요하게 나타나 지고 있는 경기에서는 경기를 길게 보고 덜 죽으면서 버텨서 바론을 먹는 것이 중요하다고 할 수 있겠습니다.

 

import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

# 불필요한 열 삭제 상황별 데이터프레임 분리
COL_DEL = ['Unnamed: 0','gamdId','teamID','gameNo','turnovers']

df_all = df.drop(COL_DEL, axis = 1)
df_win = df[df['win']==True].drop(COL_DEL, axis = 1)
df_lose = df[df['win']==False].drop(COL_DEL, axis = 1)
df_tov = df[df['turnovers']==True].drop(COL_DEL, axis = 1)
df_tov_win = df[df['turnovers']==True][df['win']==True].drop(COL_DEL, axis = 1)
df_tov_lose = df[df['turnovers']==True][df['win']==False].drop(COL_DEL, axis = 1)

# X, y 분리
df_X = df_all.drop('win', axis = 1).values
df_y = df_all['win'].values

df_win_X = df_win.drop('win', axis = 1).values
df_win_y = df_win['win'].values

df_lose_X = df_lose.drop('win', axis = 1).values
df_lose_y = df_lose['win'].values

df_tov_X = df_tov.drop('win', axis = 1).values
df_tov_y = df_tov['win'].values

df_tov_win_X = df_tov_win.drop('win', axis = 1).values
df_tov_win_y = df_tov_win['win'].values

df_tov_lose_X = df_tov_lose.drop('win', axis = 1).values
df_tov_lose_y = df_tov_lose['win'].values

# 테스트, 트레인 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(df_X, df_y, test_size = 0.3, random_state = 0)
win_X_train, win_X_test, win_y_train, win_y_test = train_test_split(df_win_X, df_win_y, test_size = 0.3, random_state = 0)
lose_X_train, lose_X_test, lose_y_train, lose_y_test = train_test_split(df_lose_X, df_lose_y, test_size = 0.3,random_state = 0)
tov_X_train, tov_X_test, tov_y_train, tov_y_test = train_test_split(df_tov_X, df_tov_y, test_size = 0.3, random_state = 0)
tov_win_X_train, tov_win_X_test, tov_win_y_train, tov_win_y_test = train_test_split(df_tov_win_X, df_tov_win_y, test_size = 0.3, random_state = 0)
tov_lose_X_train, tov_lose_X_test, tov_lose_y_train, tov_lose_y_test = train_test_split(df_tov_lose_X, df_tov_lose_y, test_size = 0.3, random_state = 0)

# 표준화
scaler = StandardScaler()
X_train_std = scaler.fit_transform(X_train)
X_test_std = scaler.transform(X_test)

win_X_train_std = scaler.fit_transform(win_X_train)
win_X_test_std = scaler.transform(win_X_test)

lose_X_train_std = scaler.fit_transform(lose_X_train)
lose_X_test_std = scaler.transform(lose_X_test)

tov_X_train_std = scaler.fit_transform(tov_X_train)
tov_X_test_std = scaler.transform(tov_X_test)

tov_win_X_train_std = scaler.fit_transform(tov_win_X_train)
tov_win_X_test_std = scaler.transform(tov_win_X_test)

tov_lose_X_train_std = scaler.fit_transform(tov_lose_X_train)
tov_lose_X_test_std = scaler.transform(tov_lose_X_test)

# 나머지는 동일하여 생략하고 역전 경기 PCA만 기재합니다

# 주성분 개수 확인을 위한 표와 그래프
pca = PCA(n_components = 10)
X_pca = pca.fit_transform(tov_X_train_std)

pca_result = pd.DataFrame({'고유값':pca.explained_variance_, '기여율':pca.explained_variance_ratio_})
pca_result['누적기여율'] = pca_result['기여율'].cumsum()
pca_result

plt.bar(range(1,11), pca.explained_variance_ratio_, alpha = 0.5, align = 'center')
plt.step(range(1,11), np.cumsum(pca.explained_variance_ratio_), where = 'mid')
plt.xlabel('PCA')
plt.ylabel('Variance explained')
plt.show()

# 3개로 주성분 분석 진행하여 확인
pca = PCA(n_components = 3)
X_train_pca = pca.fit_transform(tov_X_train_std)
X_test_pca = pca.transform(tov_X_test_std)

plt.matshow(pca.components_, cmap="viridis")
plt.yticks([0, 1, 2], [1, 2, 3])
plt.colorbar()
plt.xticks(range(len(df_all.drop('win', axis = 1).columns)), df_all.drop('win', axis = 1).columns, rotation=60, ha='left')
plt.xlabel("attr")
plt.ylabel("principle comp")
plt.show()

tov_pca = pd.DataFrame(pca.components_, columns = df_all.drop('win', axis = 1).columns, index = ['PCA 1', 'PCA 2', 'PCA 3'])
tov_pca

 

 

 

 

6. 레퍼런스

 

Riot API (MATCH-V5) 코드 구현

MATCH-V5 매치기록이 담겨있는 MATCH-V5 관련 파이썬 코드를 작성하였습니다. 해당 API는 다음과 같이 3개 존재합니다. (matchID라는 새로운 변수가 보이는데, 게임 진행시 고유 게임번호를 나타내는 변

dk-kang.tistory.com

 

 

Riot API(라이엇 api) Timeline API를 활용한 리그오브레전드 게임별 게임 시작 후 n분 까지의 데이터 수

안녕하세요. 일단 본론으로 들어가기 전에 구글에 라이엇 데이터 수집 관련해서 검색을 하게 되면 제 블로그가 최상단이더라구요! 일단 너무 신기하기도 했고, 더 열심히 해서 많은 사람들에게

shinminyong.tistory.com

 

728x90
반응형

'데이터 분석 > 파이썬' 카테고리의 다른 글

파이썬으로 영단어 공부하기  (0) 2022.05.04
파이썬으로 간단한 자판기 만들기  (0) 2022.04.28