[OPGG] 특정 유저, 시즌별 챔피언 정보
Updated:
1. 시즌 챔피언 정보
앞서 배웠던 웹 스크래핑 내용을 토대로 특정 유저의 특정 시즌 랭크 플레이 챔피언 정보를 스크래핑 해보았다.
import time
import pandas as pd
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
# headless selenium
options = webdriver.ChromeOptions()
options.add_argument('headless')
options.add_argument('window-size=1920x1080')
def my_champion(userName, season):
# 빈 데이터 프레임
data = pd.DataFrame()
# 띄어쓰기 있는 유저이면 +로 구분
userName2 = "+".join(userName.split())
# 유저별 검색 결과 url
url = f"https://www.op.gg/summoner/userName={userName2}"
# driver 실행
# driver = webdriver.Chrome("./chromedriver")
driver = webdriver.Chrome("./chromedriver", options= options)
driver.get(url)
time.sleep(1)
# 챔피언 클릭 후 다음 창 로드까지 잠시 대기
driver.find_element_by_id("left_champion").find_element_by_css_selector("a").click()
time.sleep(1)
# 원하는 시즌 설정 (xpath의 li[index]를 사용: index가 1부터 시작)
# 시즌이 추가될 때마다 수정해주어야 함
season_dict = {
2021:"tabItem season-17",
2020:"tabItem season-15",
2019:"tabItem season-13",
2018:"tabItem season-11",
2017:"tabItem season-7",
2016:"tabItem season-6",
2015:"tabItem season-5",
2014:"tabItem season-4",
2013:"tabItem season-3",
2012:"tabItem season-2",
2011:"tabItem season-1"
}
season2 = list(season_dict.keys()).index(season) + 1
# 시즌 클릭 (모두 클릭해야 정보가 나타나므로)
for i in range(len(season_dict)):
driver.find_element_by_xpath(f"//*[@id='champion_season']/li[{i+1}]/a").click()
# url 정보 저장
soup = BeautifulSoup(driver.page_source, "lxml")
driver.quit()
# 플레이한 챔피언 데이터 테이블
champ_info = soup.find("div", attrs= {"class":f"{season_dict[season]}"})
champ_info2 = champ_info.find("tbody", attrs= {"class":"Body"})
champ_info2 = champ_info2.find_all("tr")
# 각 태그 지정해서 원하는 정보 추출
for i in range(len(champ_info2)):
lst = []
# 챔피언 이름
lst.append(champ_info2[i].find("td", attrs= {"class":"ChampionName Cell"}).get_text().strip())
# 승/패 (단, 한번도 이기거나 진적이 없으면 해당 class가 없음)
if champ_info2[i].find("div", attrs= {"class":"Text Left"}) == None:
lst.append(0)
else:
lst.append(champ_info2[i].find("div", attrs= {"class":"Text Left"}).get_text().strip()[:-1])
if champ_info2[i].find("div", attrs= {"class":"Text Right"}) == None:
lst.append(0)
else:
lst.append(champ_info2[i].find("div", attrs= {"class":"Text Right"}).get_text().strip()[:-1])
# K/D/A
KDA = champ_info2[i].find("div", attrs= {"class":"KDA"}).get_text().strip().split()
lst.append(KDA[0])
lst.append(KDA[2])
lst.append(KDA[4])
# 기타 정보
else_info = champ_info2[i].find_all("td", attrs={"class":"Value Cell"})
for i in else_info:
info = i.get_text().strip().split()
if len(info) == 0:
lst.append(0)
else:
lst.append(info[0])
# 데이터 프레임
champ_df = pd.DataFrame(lst)
data = pd.concat([data, champ_df], axis=1)
# 데이터 프레임 형태, 타입 설정
data = data.T
data.index = range(data.shape[0])
data.columns = [
"champion", "win", "lose", "kill", "death", "assist",
"gold", "cs", "max_kill", "max_death", "avg_damage", "avg_damaged", "double", "triple", "quadra", "penta"
]
data["win"] = data["win"].astype(int)
data["lose"] = data["lose"].astype(int)
data["kill"] = data["kill"].astype(float)
data["death"] = data["death"].astype(float)
data["assist"] = data["assist"].astype(float)
data["gold"] = data["gold"].apply(lambda x: int(x.replace(",","")))
data["cs"] = data["cs"].astype(float)
data["max_kill"] = data["max_kill"].astype(int)
data["max_death"] = data["max_death"].astype(int)
data["avg_damage"] = data["avg_damage"].apply(lambda x: int(x.replace(",","")))
data["avg_damaged"] = data["avg_damaged"].apply(lambda x: int(x.replace(",","")))
data["double"] = data["double"].astype(int)
data["triple"] = data["triple"].astype(int)
data["quadra"] = data["quadra"].astype(int)
data["penta"] = data["penta"].astype(int)
return data
-
유저 이름에 띄어쓰기가 있으면 검색시 URL이
userName=Hide+on+bush
과 같이 +로 구분되어 이를 반영 -
챔피언 탭 클릭 후 각 시즌을 모두 클릭해야만 해당 정보가 생성되므로 모두 클릭(노말 제외)
-
시즌 입력시 연도로 입력하고 이를 URL 반영하기 위해 dictionary를 생성
-
만약 특정 챔피언이 모두 승이거나 모두 패이면 해당 class를 가지는 div 태그가 없음
-
더블킬, 트리플킬 등의 경우는 없으면 해당 class의 태그는 존재하지만 텍스트가 빈 값으로 입력되있음
OP.GG: 현재 리그오브레전드 공식 API 서버의 문제로 인해 최근 게임 데이터 갱신이 조금 늦을 수 있습니다.
위 메시지 이후로 챔피언 탭 클릭 명령어
driver.find_element_by_id("left_champion").find_element_by_css_selector("a").click()
가 될 때도 있고 안 될때도 있음 (확실한 이유는..?)
# 원하는 유저의 특정 시즌 챔피언 정보
userName = "Hide on bush"
season = 2020
result = my_champion(userName, season)
result
champion | win | lose | kill | death | assist | gold | cs | max_kill | max_death | avg_damage | avg_damaged | double | triple | quadra | penta | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 사일러스 | 55 | 60 | 6.0 | 4.3 | 5.6 | 11307 | 202.5 | 16 | 13 | 124393 | 25284 | 78 | 14 | 4 | 0 |
1 | 조이 | 54 | 50 | 5.7 | 3.3 | 6.8 | 11623 | 210.0 | 19 | 9 | 136912 | 13779 | 53 | 6 | 2 | 1 |
2 | 루시안 | 53 | 51 | 5.0 | 4.1 | 5.3 | 12133 | 234.6 | 15 | 11 | 156282 | 16874 | 44 | 5 | 2 | 0 |
3 | 아칼리 | 37 | 47 | 6.5 | 4.0 | 4.2 | 11326 | 209.8 | 24 | 9 | 121981 | 21255 | 65 | 9 | 0 | 0 |
4 | 세트 | 47 | 26 | 4.5 | 3.0 | 6.5 | 10649 | 187.1 | 13 | 7 | 112374 | 24356 | 30 | 3 | 0 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
95 | 신 짜오 | 0 | 1 | 7.0 | 8.0 | 15.0 | 13612 | 177.0 | 7 | 8 | 181530 | 52539 | 1 | 0 | 0 | 0 |
96 | 룰루 | 0 | 1 | 2.0 | 6.0 | 20.0 | 11502 | 183.0 | 2 | 6 | 107024 | 21541 | 0 | 0 | 0 | 0 |
97 | 퀸 | 0 | 1 | 0.0 | 3.0 | 0.0 | 5193 | 119.0 | 0 | 3 | 37514 | 8179 | 0 | 0 | 0 | 0 |
98 | 스웨인 | 0 | 1 | 8.0 | 5.0 | 7.0 | 14101 | 213.0 | 8 | 5 | 140346 | 36175 | 2 | 0 | 0 | 0 |
99 | 제라스 | 0 | 1 | 4.0 | 6.0 | 10.0 | 9509 | 33.0 | 4 | 6 | 62670 | 16061 | 0 | 0 | 0 | 0 |
100 rows × 16 columns
Leave a comment