Steam에서 특정 사용자의 상위 2개 플레이 시간을 조회하는 기능을 구현하던 중, 기존 크롤링 방식을 사용했을 때 아래와 같은 문제에 직면했습니다.
크롤링 대신 Steam에서 공식적으로 제공하는 API 호출 방식으로 전환했습니다.
이를 통해 데이터를 보다 안정적으로, 효율적으로 가져올 수 있었습니다.
이전 코드에서는 Selenium을 사용하여 Steam 사용자 페이지에서 게임 정보를 크롤링했습니다.
def fetch_top2_playtime(self, driver, steam_id_str):
base_url = "https://steamcommunity.com/"
if steam_id_str.isdigit():
url = f"{base_url}profiles/{steam_id_str}/games/?tab=all"
else:
url = f"{base_url}id/{steam_id_str}/games/?tab=all"
try:
driver.get(url)
WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div._2-pQFn1G7dZ7667rrakcU3"))
)
rows = driver.find_elements(By.CSS_SELECTOR, "div._2-pQFn1G7dZ7667rrakcU3")
except:
return []
# 이후 코드 생략 (DOM 구조에서 데이터를 추출하는 방식)
이 방식은 위에서 언급한 로그인 문제, HTML 구조 변경 리스크 등으로 유지보수하기 어려웠습니다.
Steam의 GetOwnedGames API를 활용하여 데이터를 가져오도록 수정했습니다.
이 방식은 API 키와 SteamID64를 사용하며, 더 안전하고 효율적입니다.
def fetch_top2_playtime_api(self, api_key, steam_id_str):
# SteamID64 확인 및 변환
if not steam_id_str.isdigit():
steam_id_str = self.resolve_vanity_url(api_key, steam_id_str)
if not steam_id_str:
return []
# API 호출
url = "https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/"
params = {
"key": api_key,
"steamid": steam_id_str,
}
try:
resp = requests.get(url, params=params).json()
if "response" in resp and "games" in resp["response"]:
games = resp["response"]["games"]
data = [
{"app_id": game["appid"], "playtime": round(game["playtime_forever"] / 60, 2)}
for game in games
]
top2 = sorted(data, key=lambda x: x["playtime"], reverse=True)[:2]
return top2
except:
return []
크롤링 → API 호출:
SteamID64 변환 로직 추가:
resolve_vanity_url
메서드를 사용해 SteamID64로 변환했습니다.플레이 시간 계산 및 상위 2개 게임 정렬:
playtime_forever
값(분 단위)을 시간 단위로 변환하고, 내림차순으로 정렬하여 상위 2개의 게임 정보를 반환했습니다.신뢰성과 유지보수성 증가:
속도 향상:
데이터 정확성 개선:
로그인 문제 해결: