메이플 스토리 랭킹 스크래핑과 Tableau를 이용해 대시보드 만들기

안녕하세요!

최근 Tableau Desktop Specialist 자격증을 취득하고, Tableau를 통해 대시보드를 하나 만들어볼 계획이었는데요! 최근 자주 즐겨하던 메이플스토리의 랭킹을 한번 스크래핑해보고 이를 대시보드로 만들어보았습니다.

스크래핑을 자주 하진 않았지만, 뭐 어떻게든 해보았는데요..!

예전에 배울땐 되게 어려웠는데, 중간에 html이나 css를 이용해 홈페이지를 만든 적이 있는데 이런 소스에 대한 이해가 있으니까 훨씬 더 쉽게 느껴지긴 했습니다!

스크래핑 코드입니다.

import requests
from bs4 import BeautifulSoup
import re
import pandas as pd
import random
import time

i = 1
MAX_SLEEP_TIME = 3
while True : 
    
    url = "https://maplestory.nexon.com/Ranking/World/Total?page=" + str(i)
    session = requests.Session()
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
    }
    html = session.get(url, headers=headers).content

    soup = BeautifulSoup(html, 'html.parser')

    title = soup.find('tbody')
    i += 1
    
    if i%10000== 0:
        temp = pd.DataFrame({'user_name': user_name,'job':job,'lvl' : lvl, 'server':server, 'guild' :guild})
        temp.to_csv('C:/Python/Maple_rank/Rank_maple'+str(i)+'.csv', index = False)
        job = [] ; lvl = [] ; server = []; user_name = []; guild = []
        
    
    
    for k in range(10):
        ranker_info = title.find_all('tr')[k]
        job.append(ranker_info.find('dd').get_text()) 
        lvl.append(int(re.findall(r'[0-9]+',ranker_info.find_all('td')[2].get_text())[0]))
        user_name.append(ranker_info.find_all('td')[1].find('a').get_text())
        guild.append(ranker_info.find_all('td')[-1].get_text())
        server.append(re.findall(r'icon_[0-9]*', title.find_all('tr')[k].find('dt').find('img')['src'])[0])
        
    rand_value = random.randint(1, MAX_SLEEP_TIME)
    
    time.sleep(rand_value)
    
    if i%1000== 0:
        print(i)
        
    if lvl[-1]< 220:
        temp = pd.DataFrame({'user_name': user_name,'job':job,'lvl' : lvl, 'server':server, 'guild' :guild})
        temp.to_csv('C:/Python/Maple_rank/Rank_maple'+str(i)+'.csv', index = False)
        job = [] ; lvl = [] ; server = []; user_name = [] ; guild = []
        break

메이플스토리 랭킹 페이지는 각 페이지마다 "https://maplestory.nexon.com/Ranking/World/Total?page="에 숫자가 붙습니다.
즉, 첫번째 페이지 (1위부터 10위까지)는 "https://maplestory.nexon.com/Ranking/World/Total?page=1",
두번째 페이지 (11위부터 20위까지)는 "https://maplestory.nexon.com/Ranking/World/Total?page=2" 입니다.

그래서 url 변수에 "https://maplestory.nexon.com/Ranking/World/Total?page=" 를 넣고 거기에 숫자를 하나씩늘려 페이지를 순차적으로 스크래핑해보았습니다.

여기서 주의할 점은 너무 빨리 긁어오게되면 홈페이지에서 밴을 먹입니다.. 그래서 저는 MAX_SLEEP_TIME이라는 값을 주고 한 페이지의 스크래핑이 끝나면 1~3초정도 랜덤으로 쉬도록 설정해 주었습니다.(이것때문에 굉장히 오래걸립니다..)

그리고 제 플레이 경험상 220까지는 이벤트가 많아서 220부터가 상시 이용유저라고 생각하기 때문에 220이상의 유저만 스크래핑했습니다.

또, 중간에 header로 정의된 부분이 있는데 이건 제가 request를 통해 홈페이지를 접속한 것이 아니라 구글 크롬이용자로 접속한 것으로 표시하는(?) 부분입니다. 이 부분까지 해줘야하는지 모르겠지만 일단 해놨습니다!

그리고 스크래핑 하는 부분의 코드를 간략하게 설명드리면, 소스객체에 find_all 메서드를 이용하면 입력한 태그들을 리스트로 나타내줍니다. 쉽게 말하면 "<a> 1 </a><b>2</b> <a>3</a>"이라는 소스에 .find_all('a')를 하게 되면 [<a> 1 </a>,<a>3</a>] 이라는 리스트를 얻을 수 있습니다! 그리고 get_text는 태그를 풀고 안에있는 내용을 받을 수 있는 메서드 입니다.

저는 아직 초보기때문에 이런 간단한 방법들로 랭킹을 스크래핑 해봤습니다.

아! 그리고 서버는 그림으로만 나오기때문에 그림 파일 이름을 긁어와서 하나하나 매칭했습니다.. 그것밖에 방법이 없더라구요..!

이렇게 긁어온 데이터를 태블로로 시각화해봤습니다.

일주일 전에 만든것이라 랭킹정보가 조금 다를 수 있습니다!

아래 링크를 들어가시면 Tableau public에 대시보드를 업로드해 두었습니다!

https://public.tableau.com/app/profile/sion.park/viz/Maple_rank_dashboard/1_1

요런식으로 버섯마크도 하나 넣어 주고 월드, 직업, 전직마다 필터링해서 레벨 분포를 볼 수 있게 나타내봤어요! 시트는 6개 정도 만들었는데 능숙하신분들이면 진짜 10분 정도면 만드실 수 있을 것 같아요!

여기서 재밌는 점은 5레벨마다 봉우리가 있다는 것인데요. 뭐 새로운 컨텐츠가 5레벨마다 나오기도하고 아마 5레벨 단위로 필요한 경험치가 엄청 늘어난다는 점도 한 몫하지 않을까 합니다.

위 사진은 아델 직업군의 레벨 분포입니다. 여기서 재밌는 점은 전체 레벨 빈도를 보면 220이 가장 많은데, 아델 직업군의 경우 220에 해당하는 비율이 다른 직업군에 비해서 낮다는 것입니다! 아마도 아델이라는 직업군이 조작하기 쉽고 강하기 때문에 220이상 키우는 사람이 많은 것이 아닌가.. 하는 생각이 드네요!

아무튼! 이렇게 대시보드를 한 번 만들어 봤습니다. 뭔가 메이플스토리에서 더 많은 데이터를 제공해주면 이것저것 재밌게 해볼수 있을텐데 많이 공개가 안되 있는 것 같아 아쉽네요...

혹시나 제가 모르는 루트로 데이터를 얻을 수 있다면 알려주세요!

좋은 웹페이지 즐겨찾기