필요한 라이브러리
- BeautifulSoup(정적 크롤링) or Selenium(동적 크롤링) 둘다 구현 함
- tqdm - for문 내의 진척을 알기위한 라이브러리
- numpy
- pandas
from selenium import webdriver
import requests
from bs4 import BeautifulSoup
import csv
import json
import time
import pandas as pd
import tqdm
import numpy as np
from tqdm import tqdm
from tqdm import trange
from tqdm import notebook
gameId 크롤링(1)
gameId를 가져오기 위한 함수들
# startinfo 불러오기
def startinfo_read(path_csv):
data = pd.read_csv(path_csv)
for i in range(0,len(data)):
user_list.append(data['num'][i][32:40])
startinfo_list.append(data['num'][i][10:20])
return startinfo_list, user_list
# op.gg내의 게임 ID추출 함수
def Crawling_gameid(url):
page = requests.get(url)
soup = BeautifulSoup(page.content, "html.parser")
jsons = json.loads(page.text)
jsons = jsons['html']
soup_html = BeautifulSoup(jsons)
game_info = soup_html.find_all('div',attrs={'class':'GameItemWrap'})
size_info = len(game_info)
Lose_num = []
Win_num = []
for i in range(0,size_info):
info = str(game_info[i])
if info.find("Lose") > 30 and info.find("Lose") < 70:
Lose_num.append(i)
elif info.find("Win") > 30 and info.find("Win") < 70:
Win_num.append(i)
# Win, GameID추출
win_game = []
lose_game = []
# gameid의 값과, 승패를 잘라서 리스트에 삽입
for i in Win_num:
game = str(game_info[i])
win_game.append(game[67:77])
for i in Lose_num:
game = str(game_info[i])
lose_game.append(game[68:78])
# print(win_game)
return win_game, lose_game
- startinfo_list - 20게임의 정보가 담긴 시작점 리스트
- user_list - 사용자 ID 리스트
startinfo_list = []
user_list = []
# 한번만 실행해합니다.
startinfo, userinfo = startinfo_read("./startinfonum1,2,3.csv")
1) startinfo_read 함수를 통해서 전에 분석한 웹URL을 불러와 전처리 진행
20게임의 시작값과, 소환사 ID값만 가져올 수 있게 전처리
Startinfo, Userinfo를 확인해본 결과
gameId 크롤링(2)
Crawling_gameid(url) 함수를 통해서 gameId요소 수집
※ 시간이 조금 걸릴 수 있다.
# tot_sum=0
# for i in trange(10):
# time.sleep(1)
# tot_sum+=i
win_data = []
lose_data = []
user_reset = []
if __name__ =="__main__":
for i,j in zip(tqdm(startinfo),tqdm(userinfo)):
try:
win,lose = Crawling_gameid('https://www.op.gg/summoner/matches/ajax/averageAndList/startInfo=' + str(i) + '&summonerId=' + str(j) +'&type=soloranked')
win_data.append(win)
lose_data.append(lose)
user_reset.append(j)
except:
print('페이지오류')
※ 해당 작업 완료시, 수집한 소환사의 게임ID를 수집가능
수집한 gameId전처리
- gameId내의 이상치(동일ID, 'me-id xxxx') 값들은 0으로 치환한다
- 높은 티어의 큐에서는 같은 사용자들간 동일한 게임이 잡혔을 수 있기 때문에, 동일한 gameId가 있을 수 있으므로 제거가 필요하다.
- 그리고, gameid를 수집하면서 이상하게 "me-id 45124" 같은 데이터들도 껴있길래 처리를 위해서 방해가 되는 요소라고 생각해 그냥 제거시켰다(많지는 않음).
def get_occurrence_count(my_list):
new_list = {}
for i in my_list:
try: new_list[i] += 1
except: new_list[i] = 1
return(new_list)
# 위에 함수 동일한 값 갯수 찾기 테스트
# test = get_occurrence_count(win_fla)
# print(test)
# 2개 이상인 데이터
def duplicate_eliminate(data):
win_flatten = []
same_value = []
where = []
for i in tqdm(range(0, len(data))):
for j in range(0,len(data[i])):
if data[i][j] in str(win_flatten):
same_value.append(data[i][j])
where.append([i,j])
else:
win_flatten.append(data[i][j])
return same_value, where
#리스트 안에 동일값 모두 0 으로 바꿈 del쓰면 리스트가 줄어들어서 인덱싱이 안됌
def remove_samedata(data, index):
for i in index:
data[i[0]][i[1]] = 0
def delete_meid(data):
for i in range(0,len(data)):
for j in range(0,len(data[i])):
if "me-id" in str(data[i][j]):
data[i][j] = 0
승리한 데이터와 패배한 데이터를 다시 합쳤다...합칠꺼면 뭐하러 나눴냐 라는 의문이 들 수 있다.
처음에는 탑-정글-미드-서폿-원딜 조합 데이터에 따라 뽑아서 학습을 시켜볼까 해서 데이터를 뽑아 통계를 내봤는데
조합에 대한 경우의 수가 너무 많아 이게 의미가 있을까..하는 생각에 포기했다.
그래서 탑-정글 / 미드-정글 / 원딜-서폿 으로 조합을 나누기로 결정했다.
# win gamd, lose game 합침
all_data = win_data + lose_data
중복 게임ID값, 'me-id xxxx 데이터 삭제
# win + lose 데이터 중 중복된 게임 인덱스 위치와, 그 인덱스의 user_id 추출
all_same_value, all_index_where = duplicate_eliminate(all_data)
# win + lose 데이터 중 중복된 게임 모두 0으로 변경
remove_samedata(all_data, all_index_where)
# 결측값 제거 - lose_data에 "game - id값이 잘못된 값 제거"
delete_meid(all_data)
사용자 데이터도 합친 데이터에 맞게 정리
user_reset = user_reset + user_reset
#1 정적 크롤링 (BeautifulSoup 사용)
'Victory' 이면 왼쪽 2개의 조합이 승리, 'Defeat' 이면 오른쪽 2개의 조합이 패배
Ex) Akali, Udyr, Aatrox, Graves, Defeat 경우 -> 아트록스, 그레이브즈 조합 승리
champ_df = pd.DataFrame(columns = ['champ1','champ2','champ3','champ4','game'])
for a in tqdm(range(0,len(all_data))):
for i in all_data[a]:
j = user_reset[a]
if int(i) > 0 :
response = requests.get('https://www.op.gg/summoner/matches/ajax/detail/gameId='+ str(i) +'&summonerId=' + str(j) + '&gameTime=1620985874')
# print(i,j)
if response.status_code == 200:
html = response.text
soup = BeautifulSoup(html)
try:
tb = soup.select('div > div.MatchDetailContent.tabItems > div > div > table')
tb1 = tb[0]
tb2 = tb[1]
score = tb1.select('thead > tr > th:nth-child(1) > span')[0].text
name1 = tb1.select('tbody > tr:nth-child(1) > td.ChampionImage.Cell > a > div')[0].text
name2 = tb1.select('tbody > tr:nth-child(2) > td.ChampionImage.Cell > a > div')[0].text
name3 = tb1.select('tbody > tr:nth-child(3) > td.ChampionImage.Cell > a > div')[0].text
name4 = tb1.select('tbody > tr:nth-child(4) > td.ChampionImage.Cell > a > div')[0].text
name5 = tb1.select('tbody > tr:nth-child(5) > td.ChampionImage.Cell > a > div')[0].text
# score2 = tb2.select('thead > tr > th:nth-child(1) > span')[0].text
name6 = tb2.select('tbody > tr:nth-child(1) > td.ChampionImage.Cell > a > div')[0].text
name7 = tb2.select('tbody > tr:nth-child(2) > td.ChampionImage.Cell > a > div')[0].text
name8 = tb2.select('tbody > tr:nth-child(3) > td.ChampionImage.Cell > a > div')[0].text
name9 = tb2.select('tbody > tr:nth-child(4) > td.ChampionImage.Cell > a > div')[0].text
name10 = tb2.select('tbody > tr:nth-child(5) > td.ChampionImage.Cell > a > div')[0].text
# top-jug, mid-jug, ad-sup 조합 game이 victory이면 왼쪽 2개 조합 승, defeat이면 오른쪽 조합 승
top_jug = {
'champ1':name1,
'champ2':name2,
'champ3':name6,
'champ4':name7,
'game':score[10:17],
}
mid_jug = {
'champ1':name3,
'champ2':name2,
'champ3':name8,
'champ4':name7,
'game':score[10:17],
}
ad_sup = {
'champ1':name4,
'champ2':name5,
'champ3':name9,
'champ4':name10,
'game':score[10:17],
}
champ_df = champ_df.append(top_jug, ignore_index=True)
champ_df = champ_df.append(mid_jug, ignore_index=True)
champ_df = champ_df.append(ad_sup, ignore_index=True)
except:
print("크롤링 오류")
else :
print(response.status_code)
else:
print("중복값 입니다")
#2 동적 크롤링 사용(selenium 사용)
※동적 크롤링은 탑-정글-미드-원딜-서폿-승패로 수집이 됩니다.
champ_df = pd.DataFrame(columns = ['top','jug','mid','ad','sup','game'])
def data_crawl(data):
for a in tqdm(range(0,len(all_data))):
for i in all_data[a]:
j = userinfo[a]
if int(i) > 0 :
options = webdriver.ChromeOptions()
options.add_argument('window-size=1920,1080')
driver = webdriver.Chrome('chromedriver', options=options)
driver.get('https://www.op.gg/summoner/matches/ajax/detail/gameId='+ str(i) +'&summonerId=' + str(j) + '&gameTime=1620985874')
try:
score = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/table/thead/tr/th[1]/span').get_attribute('textContent')
name1 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/table/tbody/tr[1]/td[1]/a/div[1]').get_attribute('textContent')
name2 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/table/tbody/tr[2]/td[1]/a/div[1]').get_attribute('textContent')
name3 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/table/tbody/tr[3]/td[1]/a/div[1]').get_attribute('textContent')
name4 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/table/tbody/tr[4]/td[1]/a/div[1]').get_attribute('textContent')
name5 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/table/tbody/tr[5]/td[1]/a/div[1]').get_attribute('textContent')
score2 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/div[1]/div[3]/table/thead/tr/th[1]/span').get_attribute('textContent')
name6 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/div[1]/div[3]/table/tbody/tr[1]/td[1]/a/div[1]').get_attribute('textContent')
name7 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/div[1]/div[3]/table/tbody/tr[2]/td[1]/a/div[1]').get_attribute('textContent')
name8 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/div[1]/div[3]/table/tbody/tr[3]/td[1]/a/div[1]').get_attribute('textContent')
name9 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/div[1]/div[3]/table/tbody/tr[4]/td[1]/a/div[1]').get_attribute('textContent')
name10 = driver.find_element_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/div[1]/div[3]/table/tbody/tr[5]/td[1]/a/div[1]').get_attribute('textContent')
data1 = {
'top':name1,
'jug':name2,
'mid':name3,
'ad':name4,
'sup':name5,
'game':score[10:12],
}
data2 = {
'top':name6,
'jug':name7,
'mid':name8,
'ad':name9,
'sup':name10,
'game':score2[10:12],
}
champ_df = champ_df.append(data1, ignore_index=True)
champ_df = champ_df.append(data2, ignore_index=True)
print(champ_df)
except:
print("크롤링 오류")
else:
print("중복값 입니다")
time.sleep(2)
driver.quit()
해당 데이터 csv로 저장
champ_df.to_csv("이름.csv", encoding='utf-8')
'머신러닝 > 머신러닝 프로젝트' 카테고리의 다른 글
#2-2 롤(LOL) 게임 데이터 요소를 이용한 승리예측 - [머신러닝 프로젝트] (4) | 2021.07.05 |
---|---|
#2-1 롤(LOL) 라이엇 API사용하여 롤 데이터 크롤링(API사용) - [머신러닝 프로젝트] (0) | 2021.07.05 |
#1 롤(LOL) 챔피언 조합 데이터 크롤링(OP.GG 페이지 분석) - [머신러닝 프로젝트] (0) | 2021.06.07 |