MATCH-V4 API์์ matchID ์ถ์ถํ๊ธฐ
์ง๋ ๊ฒ์๊ธ์์ puuID๊น์ง ์ถ์ถํ์ฌ ๋ฐ์ดํฐ ํ๋ ์ ํํ๋ก ๋ง๋ค์์ต๋๋ค.
/lol/match/v5/matches/by-puuid/{puuid}/ids๋ฅผ ํ์ฉํ์ฌ matchID๋ฅผ ์ถ์ถ ํ๊ฒ ์ต๋๋ค.
api_key = MY_API
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0",
"Accept-Language": "ko,en;q=0.9,en-US;q=0.8",
"Accept-Charset": "application/x-www-form-urlencoded; charset=UTF-8",
"Origin": "https://developer.riotgames.com"
}
summoner_matchID_list=[]
for puuid in puuid_list:
url=f"https://asia.api.riotgames.com/lol/match/v5/matches/by-puuid/{puuid}/ids?start=0&count=20&api_key=MY_API"
rp2=requests.get(url,headers=header)
if rp2.status_code==429:
print("Rate limit exceeded. Sleeping for 60 seconds")
time.sleep(60)
rp2=requests.get(url,headers=header)
if rp2.status_code==200:
summoner_match_data=rp2.json()
summoner_matchID_list.append({'puuid': puuid, 'match_ids': summoner_match_data})
# ๋๋ ์ด ์ถ๊ฐ
time.sleep(1) # ๊ฐ ์์ฒญ ์ฌ์ด์ 1์ด์ ๋๋ ์ด๋ฅผ ์ถ๊ฐํ์ฌ Riot API์ Rate Limit์ ๊ฑธ๋ฆฌ์ง ์๋๋ก
์ด์ ๊ฒ์๊ธ์์ ๋ง๋ puuID ๋ฆฌ์คํธ๋ฅผ ๋ฃ์ด์ matchID๋ฅผ ํธ์ถ ํ๊ฒ ์ต๋๋ค.
์ ๋๋ก ํธ์ถ๋จ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด์ matchID๋ฅผ ๋ฃ์ด์ ๊ฒ์ ์ ๋ณด๋ฅผ ํธ์ถํ๊ฒ ์ต๋๋ค.
matchID๋ฅผ ํ์ฉํด ๊ฒ์ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ (๋๊ธฐ์ ๋ฐฉ์)
api_key = MY_API
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0",
"Accept-Language": "ko,en;q=0.9,en-US;q=0.8",
"Accept-Charset": "application/x-www-form-urlencoded; charset=UTF-8",
"Origin": "https://developer.riotgames.com",
"X-Riot-Token": api_key
}
match_user_data=[]
for player in summoner_matchID_list:
puuid=player['puuid']
match_ids=player['match_ids']
for match_id in match_ids:
url = f"https://asia.api.riotgames.com/lol/match/v5/matches/{match_id}"
rp3=requests.get(url,headers=header)
if rp3.status_code==429:
print("Rate limit exceeded. Sleeping for 60 seconds")
time.sleep(60)
rp3=requests.get(url,headers=header)
if rp3.status_code==200:
match_data=rp3.json()
match_user_data.append({'puuid': puuid, 'match_id': match_id, 'match_data':match_data})
# ๋๋ ์ด ์ถ๊ฐ
time.sleep(1) # ๊ฐ ์์ฒญ ์ฌ์ด์ 1์ด์ ๋๋ ์ด๋ฅผ ์ถ๊ฐํ์ฌ Riot API์ Rate Limit์ ๊ฑธ๋ฆฌ์ง ์๋๋ก
ํด๋น ์ฝ๋๋ฅผ ๋๋ ธ๋๋ฐ 40๋ถ ๋์ ๋์๊ฐ๋๋ ๊ฒฐ๊ตญ ์ค๋ฅ๊ฐ ๋ฌ์ต๋๋ค.
API ํธ์ถ์ ๋๋ฌด ๋ง์ด ํด์ ์๊ธด ์ค๋ฅ ๊ฐ์ต๋๋ค.
250๊ฐ ๋ฟ๋ง ์๋๋ผ ์์ผ๋ก ํฐ์ด๋ณ๋ก 500๊ฐ์ฉ์ ํธ์ถํด์ผ ํ ํ ๋ฐ, 250*20=4100 ํ ์ ๋ณด ํธ์ถํ๋๋ฐ ๋๋ฌด ์ค๋๊ฑธ๋ฆฌ๊ณ ์ค๋ฅ๊ฐ ๋ด์ต๋๋ค. ์์ฑํ ์ฝ๋๊ฐ ๋๊ธฐ์ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์์ฒญํ๋๋ฐ ๋๊ธฐ์ ๋ฐฉ์์ผ๋ก ์์ฒญ์ ์ฒ๋ฆฌํ๋ฉด ํ๋์ ์์ฒญ์ด ์๋ฃ๋ ๋๊น์ง ๋ค์ ์์ฒญ์ ๊ธฐ๋ค๋ ค์ผ ํ๊ธฐ ๋๋ฌธ์ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฝ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋น๋๊ธฐ ์์ฒญ(asynchronous requests)์ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ์์ฒญ์ ๋์์ ์ฒ๋ฆฌํ ์ ์์ด ์๋๋ฅผ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค. aiohttp์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋น๋๊ธฐ์ ์ผ๋ก API ์์ฒญ์ ๋ณด๋ผ ์ ์์ต๋๋ค.
matchID๋ฅผ ํ์ฉํด ๊ฒ์ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ (๋น๋๊ธฐ์ ๋ฐฉ์)
import aiohttp # asyncio๋ฅผ ์ฌ์ฉํ์ฌ HTTP ์์ฒญ์ ํ๊ธฐ ์ํด ์ฌ์ฉ
import asyncio # Python 3.3๋ถํฐ ์๊ฐ๋ ๋น๋๊ธฐ ์ง์ ๋ชจ๋
import time
# ๋น๋๊ธฐ ์์ฒญ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํจ์
async def fetch_match_data(session, puuid, match_id, header):
# Riot API์์ ๊ฐ match_id์ ๋ํด ๋น๋๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ญํ
# session : aiohttp.ClientSession()์ ์ฌ์ฉํ์ฌ ์์ฑ๋ HTTP ์ธ์
๊ฐ์ฒด. ๋น๋๊ธฐ์ ์ผ๋ก HTTP ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํด ํ์
url = f"https://asia.api.riotgames.com/lol/match/v5/matches/{match_id}"
async with session.get(url, headers=header) as response:
# session์ ํตํด ์ฌ๋ฌ๊ฐ์ matchID๋ฅผ ๋์์ ์
๋ ฅํ์ฌ url ์ฃผ์ ๊ฐ์ ธ์ค๊ธฐ
if response.status == 429:
# Rate limit์ ๊ฑธ๋ฆฌ๋ฉด (status == 429), Retry-After ํค๋ ๊ฐ์ ํ์ธํ์ฌ 60์ด ๋งํผ ๋๊ธฐํ ํ ์ฌ์๋
retry_after = int(response.headers.get('Retry-After', 60)) # Retry-After ํค๋ ํ์ธ
print(f"Rate limit exceeded. Sleeping for {retry_after} seconds.")
await asyncio.sleep(retry_after) # ๋น๋๊ธฐ ๋๊ธฐ
# 60์ด๋งํผ ๋๊ธฐ์ค์ธ ์ํ
async with session.get(url, headers=header) as retry_response:
if retry_response.status == 200:
# 60์ด๋งํผ ๋๊ธฐ ํ ์ฌ์๋
return await retry_response.json(), puuid, match_id
elif response.status == 200:
return await response.json(), puuid, match_id
# ์๋ต์ด ์ฑ๊ณต์ ์ผ ๊ฒฝ์ฐ (status == 200), ์๋ต ๋ฐ์ดํฐ๋ฅผ json ํ์์ผ๋ก ๋ฐํ
else:
print(f"Error: {response.status}")
return None, puuid, match_id
# ์ค๋ฅ ์๋ต์ด ๋ฐ์ํ ๊ฒฝ์ฐ ์ํ ์ฝ๋์ ํจ๊ป ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๊ณ None์ ๋ฐํ
# ๋น๋๊ธฐ ๋ฉ์ธ ํจ์
async def fetch_all_matches(summoner_matchID_list, header):#์ฌ๋ฌ ํ๋ ์ด์ด์ ์ฌ๋ฌ match_id์ ๋ํด ๋น๋๊ธฐ์ ์ผ๋ก API ์์ฒญ์ ๋์์ ์ฒ๋ฆฌ
match_user_data = []
async with aiohttp.ClientSession() as session:
tasks = []
# ๊ฐ ํ๋ ์ด์ด์ puuid์ ํด๋น match_ids์ ๋ํด fetch_all_data ํจ์๋ฅผ ํธ์ถํ๋ ์์
(task)์ ์์ฑ
for player in summoner_matchID_list:
puuid = player['puuid']
match_ids = player['match_ids']
for match_id in match_ids:
task = asyncio.create_task(fetch_match_data(session, puuid, match_id, header))
# asyncio.create_task()๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์์
์ ์์ฑํ๊ณ , ์ด ์์
์ ๋ชจ๋ ๋ชจ์์ asyncio.gather()๋ก ๋์์ ์คํ
tasks.append(task)
await asyncio.sleep(1) # ๋น๋๊ธฐ ๋๊ธฐ (1์ด)
responses = await asyncio.gather(*tasks)
# ์๋ต ๋ฐ์ดํฐ ์ฒ๋ฆฌ
for match_data, puuid, match_id in responses:
if match_data:
match_user_data.append({'puuid': puuid, 'match_id': match_id, 'match_data': match_data})
return match_user_data
2์ด๋ง์ ๋๋ฌ์ต๋๋ค. ์ฝ๋์ ๋ํ ํด์ค๋ ๊ฐ์ด ๋ฌ์๋์์ต๋๋ค.
์ ๋๋ก ํธ์ถ๋๋์ง ํ์ธํด๋ด ์๋ค.
sample3=pd.DataFrame(match_user_data)
sample3['match_data'][0]
ํ์ํ ์ ๋ณด๋ค์ ๋ง๊ฒ ๋ถ๋ฌ์์ต๋๋ค.
์ด์ ์ด ์ ๋ณด์์ ์ฌ์ฉํ ๊ฒ๋ง์ ์ถ์ถํ์ฌ MySQL DB์ ๋ด๊ฒ ์ต๋๋ค.
ํ์ง๋ง ์ด์ ์ ์์ฑํ ์ฝ๋๋ค๋ ๋น๋๊ธฐ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋น ๋ฅด๊ฒ ํธ์ถํ ์ ์๋๋ก ์์ ๊ณผ์ ์ ๋จผ์ ๊ฑฐ์น๊ฒ ์ต๋๋ค.