일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 코딩테스트준비
- greedy
- 프로그래머스
- git
- 파이썬
- sort
- lol
- 스파르타내일배움캠프TIL
- 그리디
- github
- 리그오브레전드
- programmers
- 롤
- SQL
- 그리디알고리즘
- java
- 코딩테스트
- 내일배움캠프
- 백준
- python
- 장고
- 자바
- 탐욕알고리즘
- Riot
- 라이엇
- Django
- 알고리즘
- drf
- 스파르타내일배움캠프
- API
- Today
- Total
Lina's Toolbox
[Django/RIOT API] 6. 유저네임으로 챔피언정보(선호 챔피언, 챔피언 이미지) 조회하기 (champion-mastery-v4) 본문
[Django/RIOT API] 6. 유저네임으로 챔피언정보(선호 챔피언, 챔피언 이미지) 조회하기 (champion-mastery-v4)
Woolina 2024. 10. 12. 15:32
puuid로 챔피언 마스터리 정보 불러오기
https://developer.riotgames.com/apis#champion-mastery-v4
챔피언 숙련도 관련 정보는 여기서 얻을 수 있다!
나는 puuid를 통해 상위 n개의 선호 챔피언 정보를 가져오는
/lol/champion-mastery/v4/champion-masteries/by-puuid/{encryptedPUUID}/top를 사용했다.
리턴 값이 꽤 많은데, 사실 내가 사용할 건 championId 딱 하나다. 😅
account-v1를 통해 조회한 인코딩된 puuid를 입력하고,
내가 보고싶은 상위 선호 챔피언의 갯수(count)를 적고 Api key 선택 후 요청하면,
Response Body
[
{
"puuid": "FGS9t-Uro7Inj8Gksk4NxIvM-dfgdkgjMiPCVKBzo8DbL9mrbp7s_I5-GLjWBC83F5Iu_De6g",
"championId": 233,
"championLevel": 11,
"championPoints": 86999,
"lastPlayTime": 1727391869000,
"championPointsSinceLastLevel": 399,
"championPointsUntilNextLevel": 10601,
"markRequiredForNextLevel": 2,
"tokensEarned": 1,
"championSeasonMilestone": 0,
"milestoneGrades": [
"C-"
],
"nextSeasonMilestone": {
"requireGradeCounts": {
"B-": 1,
"C-": 4
},
"rewardMarks": 1,
"bonus": false,
"rewardConfig": {
"rewardValue": "5f4333db-e90d-4705-903b-08dbf5e61006",
"rewardType": "HEXTECH_CHEST",
"maximumReward": 6
},
"totalGamesRequires": 5
}
}
]
가장 상위 선호 챔피언에 대한 마스터리 정보가 반환된다!
여기서 내가 사용할 값은 championId
파이썬 코드
def get_top_champions(api_key, puuid):
"""유저의 상위 5개 챔피언 ID를 조회합니다."""
url_top_champions = f"https://kr.api.riotgames.com/lol/champion-mastery/v4/champion-masteries/by-puuid/{puuid}/top?count=5&api_key={api_key}"
try:
response = requests.get(url_top_champions, timeout=10)
response.raise_for_status() # HTTPError가 발생하면 예외 발생
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching top champions: {e}")
return []
상위 5개를 조회할 것이므로 아예 endpoint에 ?count=5 가 추가되어있다.
챔피언 Id로 챔피언 이름, 챔피언 이미지 불러오기
그런데 여기서 챔피언 ID는 그냥 int값이므로 쓸모가 없다.
나는 이 챔피언 아이디 값을 통해 해당 챔피언의 이름과, 이미지를 얻고싶었다.
Data Dragon이 sdn으로 챔피언에 대한 정보와 이미지를 제공해주는 것을 찾았다.
이걸 이용하면 되겠다! 싶었다.
참고로 url에서 14.20.1은 게임의 버전으로,
만약 낮은 게임 버전으로 검색했을 경우 당시에 아직 출시되지 않았던 챔피언 정보는 나오지 않는다.
따라서 최신 버전을 적어주는 게 좋다.
ddragon sdn에서, id가 챔피언 명이고,
챔피언 이미지 sdn은 url 마지막에 /{챔피언이름}.png 로 들어가므로, 이것을 이용해야겠다고 생각했다.
파이썬 코드
def get_champion_name(champion_id):
"""주어진 챔피언 ID로 챔피언 이름을 조회합니다."""
url_champion_data = "https://ddragon.leagueoflegends.com/cdn/14.20.1/data/ko_KR/champion.json"
try:
response = requests.get(url_champion_data, timeout=10)
response.raise_for_status()
champions = response.json()["data"]
for champion in champions.values():
if champion["key"] == str(champion_id):
return champion["id"], champion["name"] # (챔피언 ID, 챔피언 이름)
except requests.exceptions.RequestException as e:
print(f"Error fetching champion data: {e}")
return None, None
# 상위 5개 챔피언 ID 조회
top_champions = get_top_champions(api_key, puuid)
champion_info = []
for champion in top_champions:
champion_id = champion['championId']
champion_name, _ = get_champion_name(champion_id)
if champion_name: # 챔피언 이름이 유효한 경우
champion_image_link = f"https://ddragon.leagueoflegends.com/cdn/14.20.1/img/champion/{champion_name}.png"
champion_info.append({
"championId": champion_id,
"championName": champion_name,
"championImage": champion_image_link
})
API 호출 파이썬 전체코드
profiles/riot.py
"""
description:
라이엇 API 활용해
라이엇 유저네임, 유저태그 입력하면
해당 유저가 존재한다면
프로필 아이콘, 레벨, 최근 수정일, 티어, 랭크, 승패 수, 선호 포지션 등을 반환.
작성자: 김우린
작성일: 2024-10-12
"""
import sys
import os
import requests
from urllib.parse import quote
# 현재 파일의 경로를 기준으로 상위 디렉토리(프로젝트 루트)를 PYTHONPATH에 추가
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/..")
from wpgg.settings import RIOT_API_KEY
# API 키 설정
api_key = RIOT_API_KEY
def get_user_puuid(api_key, riot_id, tag_line):
"""주어진 리그 ID와 태그라인으로 유저의 PUUID를 조회합니다."""
encoded_riot_id = quote(riot_id)
encoded_tag_line = quote(tag_line)
url_puuid = f"https://asia.api.riotgames.com/riot/account/v1/accounts/by-riot-id/{encoded_riot_id}/{encoded_tag_line}?api_key={api_key}"
try:
response = requests.get(url_puuid, timeout=10)
if response.status_code == 404:
return None # 유저가 존재하지 않음
response.raise_for_status() # HTTPError가 발생하면 예외 발생
return response.json()['puuid']
except requests.exceptions.RequestException as e:
print(f"Error fetching PUUID: {e}")
return None
def get_user_profile(api_key, puuid):
"""PUUID로부터 유저의 프로필 정보를 조회합니다."""
url_profile = f"https://kr.api.riotgames.com/lol/summoner/v4/summoners/by-puuid/{puuid}?api_key={api_key}"
try:
response = requests.get(url_profile, timeout=10)
response.raise_for_status() # HTTPError가 발생하면 예외 발생
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching profile: {e}")
return None
def get_user_league(api_key, summoner_id):
"""소환사 ID로부터 유저의 리그 정보를 조회합니다."""
url_league = f"https://kr.api.riotgames.com/lol/league/v4/entries/by-summoner/{summoner_id}?api_key={api_key}"
try:
response = requests.get(url_league, timeout=10)
response.raise_for_status() # HTTPError가 발생하면 예외 발생
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching league info: {e}")
return None
def get_match_ids(api_key, puuid):
"""PUUID로부터 유저의 매치 ID 목록을 조회합니다."""
url_match_ids = f"https://asia.api.riotgames.com/lol/match/v5/matches/by-puuid/{puuid}/ids?api_key={api_key}"
try:
response = requests.get(url_match_ids, timeout=10)
response.raise_for_status() # HTTPError가 발생하면 예외 발생
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching match IDs: {e}")
return None
def get_match_info(api_key, match_id):
"""매치 ID로부터 매치 정보를 조회합니다."""
url_match_info = f"https://asia.api.riotgames.com/lol/match/v5/matches/{match_id}?api_key={api_key}"
try:
response = requests.get(url_match_info, timeout=10)
response.raise_for_status() # HTTPError가 발생하면 예외 발생
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching match info: {e}")
return None
def get_user_preferred_position(api_key, puuid):
"""PUUID로부터 유저의 선호 포지션을 조회합니다."""
positions = []
match_ids = get_match_ids(api_key, puuid)
if not match_ids:
return "해당 유저의 매치 기록이 없습니다."
last_match_id = match_ids[0] # 가장 최근 매치 ID
match_info = get_match_info(api_key, last_match_id)
if not match_info:
return "매치 정보 조회 실패."
participants = match_info['info']['participants']
for player in participants:
if player['puuid'] == puuid:
positions.append(player['individualPosition'])
# 가장 많이 등장한 포지션 반환 (선호 포지션)
if positions:
return max(set(positions), key=positions.count)
return "포지션 정보 없음"
def get_top_champions(api_key, puuid):
"""유저의 상위 5개 챔피언 ID를 조회합니다."""
url_top_champions = f"https://kr.api.riotgames.com/lol/champion-mastery/v4/champion-masteries/by-puuid/{puuid}/top?count=5&api_key={api_key}"
try:
response = requests.get(url_top_champions, timeout=10)
response.raise_for_status() # HTTPError가 발생하면 예외 발생
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching top champions: {e}")
return []
def get_champion_name(champion_id):
"""주어진 챔피언 ID로 챔피언 이름을 조회합니다."""
url_champion_data = "https://ddragon.leagueoflegends.com/cdn/14.20.1/data/ko_KR/champion.json"
try:
response = requests.get(url_champion_data, timeout=10)
response.raise_for_status()
champions = response.json()["data"]
for champion in champions.values():
if champion["key"] == str(champion_id):
return champion["id"], champion["name"] # (챔피언 ID, 챔피언 이름)
except requests.exceptions.RequestException as e:
print(f"Error fetching champion data: {e}")
return None, None
def get_user_info(api_key, riot_id, tag_line):
"""유저의 정보를 종합적으로 조회합니다."""
puuid = get_user_puuid(api_key, riot_id, tag_line)
if not puuid:
return {"error": "해당 유저는 존재하지 않습니다."}
profile_data = get_user_profile(api_key, puuid)
if not profile_data:
return {"error": "프로필 정보를 가져오는 데 실패했습니다."}
summoner_id = profile_data['id']
league_data = get_user_league(api_key, summoner_id)
preferred_position = get_user_preferred_position(api_key, puuid)
# 프로필 아이콘 URL 생성
profile_icon_link = f"https://raw.communitydragon.org/latest/game/assets/ux/summonericons/profileicon{profile_data['profileIconId']}.png"
# 상위 5개 챔피언 ID 조회
top_champions = get_top_champions(api_key, puuid)
champion_info = []
for champion in top_champions:
champion_id = champion['championId']
champion_name, _ = get_champion_name(champion_id)
if champion_name: # 챔피언 이름이 유효한 경우
champion_image_link = f"https://ddragon.leagueoflegends.com/cdn/14.20.1/img/champion/{champion_name}.png"
champion_info.append({
"championId": champion_id,
"championName": champion_name,
"championImage": champion_image_link
})
# 리턴할 정보 구성
user_info = {
"profileIconId": profile_data['profileIconId'],
"profileIconLink": profile_icon_link,
"summonerLevel": profile_data['summonerLevel'],
"revisionDate": profile_data['revisionDate'],
"league": [],
"preferredPosition": preferred_position, # 유저의 선호 포지션 추가
"topChampions": champion_info # 유저의 상위 챔피언 정보 추가
}
# 리그 정보에서 'RANKED_SOLO_5x5' 큐 타입만 필터링하여 추가
if league_data:
for entry in league_data:
if entry['queueType'] == 'RANKED_SOLO_5x5':
league_info = {
"tier": entry['tier'],
"rank": entry['rank'],
"leaguePoints": entry['leaguePoints'],
"wins": entry['wins'],
"losses": entry['losses'],
"veteran": entry['veteran'],
"inactive": entry['inactive'],
"freshBlood": entry['freshBlood'],
"hotStreak": entry['hotStreak']
}
user_info["league"].append(league_info)
return user_info
# 함수 호출 예시
# riot_id = '미밀면' # 유저 이름
# tag_line = 'KR1' # 태그라인
# user_info = get_user_info(api_key, riot_id, tag_line)
# print(user_info)
# 리턴예시
# {'profileIconId': 6631, 'profileIconLink': 'https://raw.communitydragon.org/latest/game/assets/ux/summonericons/profileicon6631.png', 'summonerLevel': 125, 'revisionDate': 1728712811941, 'league': [{'tier': 'GOLD', 'rank': 'III', 'leaguePoints': 3, 'wins': 12, 'losses': 8, 'veteran': False, 'inactive': False, 'freshBlood': False, 'hotStreak': False}], 'preferredPosition': 'JUNGLE', 'topChampions': [{'championId': 233, 'championName': 'Briar', 'championImage': 'https://ddragon.leagueoflegends.com/cdn/14.20.1/img/champion/Briar.png'}, {'championId': 78, 'championName': 'Poppy', 'championImage': 'https://ddragon.leagueoflegends.com/cdn/14.20.1/img/champion/Poppy.png'}, {'championId': 32, 'championName': 'Amumu', 'championImage': 'https://ddragon.leagueoflegends.com/cdn/14.20.1/img/champion/Amumu.png'}, {'championId': 163, 'championName': 'Taliyah', 'championImage': 'https://ddragon.leagueoflegends.com/cdn/14.20.1/img/champion/Taliyah.png'}, {'championId': 14, 'championName': 'Sion', 'championImage': 'https://ddragon.leagueoflegends.com/cdn/14.20.1/img/champion/Sion.png'}]}
내 라이엇 AI 활용 첫번째 포스팅부터 모든 것을 합친 코드이다!
유저네임, 유저태그를 통해 → puuid를 불러오고
→ puuid를 통해 프로필 정보(소환사 레벨, 프로필 아이콘, summoner ID)
→ summoner ID를 통해 리그정보(티어, 랭크, 승패 수 등) 조회,
→ puuid로 매치정보 조회 → 얻은 매치 Id로 선호 포지션 조회
→ puuid로 챔피언 마스터리 정보 조회
→ 상위 5개 선호 챔피언 조회
→ 챔피언 Id로 ddragon sdn에서 챔피언 이름,이미지 가져오기
장고 전체 코드 (html, urls.py)
profiles/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('riotPage/', views.RiotPageView.as_view(), name='user-index'),
path('riot/', views.GetRiotInfoView.as_view(), name='user-profile'),
]
urls.py
from django.urls import path, include
urlpatterns = [
path('api/profile/', include('profiles.urls')),
]
profiles/views.py
from wpgg.settings import RIOT_API_KEY
class RiotPageView(generic.TemplateView):
template_name = 'profiles/riot.html'
class GetRiotInfoView(APIView):
def get(self, request):
riot_username = request.query_params.get('riot_id')
tag_line = request.query_params.get('tag_line')
if not riot_username or not tag_line:
return Response({"message": "유효하지 않은 요청입니다."}, status=status.HTTP_400_BAD_REQUEST)
user_info = get_user_info(RIOT_API_KEY, riot_username, tag_line)
if 'error' in user_info:
return Response({"message": "소환사에 대한 정보를 찾을 수 없습니다."}, status=status.HTTP_404_NOT_FOUND)
return Response(user_info, status=status.HTTP_200_OK)
wpgg는 내 프로젝트 앱 이름이다.
profiles/templates/profiles/riot.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Riot 유저 프로필</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<h1>리그 오브 레전드 유저 정보 조회</h1>
<form id="riotForm" onsubmit="fetchUserInfo(event)">
<label for="riotId">유저 이름:</label>
<input type="text" id="riotId" required>
<br>
<label for="tagLine">태그라인:</label>
<input type="text" id="tagLine" required>
<br>
<button type="submit">조회</button>
</form>
<div id="result" style="margin-top: 20px;"></div>
<script>
async function fetchUserInfo(event) {
event.preventDefault(); // 기본 폼 제출 방지
const riotId = document.getElementById("riotId").value;
const tagLine = document.getElementById("tagLine").value;
try {
const response = await fetch(`http://127.0.0.1:8000/api/profile/riot/?riot_id=${encodeURIComponent(riotId)}&tag_line=${encodeURIComponent(tagLine)}`, {
method: 'GET', // GET 메서드로 변경
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error('네트워크 응답이 좋지 않습니다.');
}
const data = await response.json();
displayUserInfo(data);
} catch (error) {
document.getElementById("result").innerText = error.message;
}
}
function displayUserInfo(data) {
const resultDiv = document.getElementById("result");
resultDiv.innerHTML = ""; // 이전 결과 지우기
if (data.message) {
resultDiv.innerText = data.message;
return;
}
// 프로필 아이콘 표시
const profileImg = document.createElement("img");
profileImg.src = data.profileIconLink;
profileImg.alt = "프로필 아이콘";
profileImg.style.width = "50px";
profileImg.style.height = "50px";
resultDiv.appendChild(profileImg);
// 유저 정보 표시
const userInfoHtml = `
<h2>${data.summonerLevel} 레벨</h2>
<p>최종 수정일: ${new Date(data.revisionDate).toLocaleString()}</p>
<h3>리그 정보</h3>
<ul>
${data.league.map(entry => `
<li>${entry.tier} ${entry.rank} - 승: ${entry.wins}, 패: ${entry.losses}</li>
`).join('')}
</ul>
<p>선호 포지션: ${data.preferredPosition}</p>
<h3>상위 챔피언</h3>
<ul>
${data.topChampions.map(champion => `
<li>
<img src="${champion.championImage}" alt="${champion.championName}" style="width: 30px; height: 30px;">
${champion.championName}
</li>
`).join('')}
</ul>
`;
resultDiv.innerHTML += userInfoHtml;
}
</script>
</body>
</html>
실행 화면
Riot API Key 관리하는법
참고로 Riot api key는 외부에 절대 노출되면 안되기 때문에
settings.py에 config.py라는 파일을 만들어서
config.py
RIOT_API_KEY = 'your_riot_key_here'
settings.py
from . import config
RIOT_API_KEY = config.RIOT_API_KEY
.gitignore
config.py
깃허브에 노출되면 안되기 때문에 이런식으로 관리하였다.
관련 게시글
https://kimwoolina.tistory.com/136
https://kimwoolina.tistory.com/137
https://kimwoolina.tistory.com/138
https://kimwoolina.tistory.com/139