Last active
November 28, 2022 22:40
-
-
Save nozma/7a6eceb463d89f5dd9155901e20944cb to your computer and use it in GitHub Desktop.
stat.inkからSplatoon 3の戦歴データを取得する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
title: "stat.inkからSplatoon 3の戦歴データを取得する" | |
author: '@nozma' | |
date: "2022-11-29" | |
output: html_document | |
--- | |
```{r setup, include=FALSE} | |
knitr::opts_chunk$set(echo = TRUE) | |
library(rvest) | |
library(dplyr) | |
library(lubridate) | |
library(tidyr) | |
library(ggplot2) | |
library(jsonlite) | |
library(tidyjson) | |
library(stringr) | |
theme_set(theme_bw(base_family = "IPAexGothic")) | |
``` | |
# 戦歴取得 | |
```{r} | |
#| message=FALSE | |
# param ---- | |
user_name <- "@nozma" | |
base_url <- glue::glue("https://stat.ink/{user_name}/spl3?page=") | |
max_page <- 7 # TODO:合計バトル数から自動計算 | |
# init df ---- | |
result_raw <- tibble() | |
# get data ---- | |
for(i in seq_len(max_page)){ | |
read_html(paste0(base_url, i)) %>% | |
html_nodes("table") %>% | |
html_table() %>% | |
.[[1]] %>% | |
as_tibble(.name_repair = "unique") %>% | |
# 軽い前処理 | |
filter(`...1` == "Detail") %>% # 日付行の除外 | |
select(!matches("^\\.")) %>% # 空白カラムの除外 | |
# 切断ありフラグを追加(trのclassから取得) | |
bind_cols( | |
read_html(paste0(base_url, i)) %>% | |
html_nodes("table") %>% | |
html_nodes("tr") %>% | |
html_attr("class") %>% | |
tibble(class = .) %>% | |
filter(grepl("battle-row", class)) %>% | |
transmute(disconnected = grepl("disconnected", class)) | |
) %>% | |
bind_rows(result_raw) -> result_raw | |
Sys.sleep(1) # 落ち着く | |
} | |
``` | |
# API情報取得 | |
ref. [Spl3 API: Battle - Post · fetus-hina/stat.ink Wiki](https://github.com/fetus-hina/stat.ink/wiki/Spl3-API:-Battle-%EF%BC%8D-Post) | |
```{r} | |
# ロビー | |
read_html("https://stat.ink/api/v3/lobby") %>% | |
html_element("p") %>% | |
html_text() %>% | |
fromJSON() %>% | |
unnest(name) -> lobby_info | |
# ルール | |
read_html("https://stat.ink/api/v3/rule") %>% | |
html_element("p") %>% | |
html_text() %>% | |
fromJSON() %>% | |
unnest(c(aliases, name, short_name), names_sep = "_") -> rule_info | |
# ステージ | |
read_html("https://stat.ink/api/v3/stage") %>% | |
html_element("p") %>% | |
html_text() %>% | |
fromJSON() %>% | |
unnest(c(aliases, name, short_name, release_at), names_sep = "_") -> stage_info | |
# ブキ | |
read_html("https://stat.ink/api/v3/weapon") %>% | |
html_element("p") %>% | |
html_text() %>% | |
gather_array() %>% | |
spread_all() %>% as_tibble() -> weapon_info | |
``` | |
# 前処理 | |
```{r} | |
result_raw %>% | |
rename_all(.funs = ~tolower(gsub(" ", "_", .))) %>% | |
transmute( | |
lobby, mode, stage, | |
weapon, | |
sub_weapon, special, rank, judge, result, | |
#`k/d`, ratio, rate, | |
#`kill_or_assist`, | |
specials = as.integer(specials), | |
inked = as.numeric(sub(",", "", inked)), | |
rank_in_team = as.integer(rank_in_team), | |
elapsed = as.numeric(elapsed...22), # カラムの追加・削除があると動かなくなる可能性あり | |
date_time = mdy_hm(date_time), | |
disconnected, | |
# 変数追加 | |
simple_result = if_else(grepl("Victory", result), "Victory", "Defeat"), # 勝ち負け | |
knockout = judge == "KNOCKOUT", | |
judge_friend = case_when( # 味方カウント | |
knockout ~ NA_character_, | |
simple_result == "Victory" ~ str_extract(judge, "^\\d{2}(\\.\\d)?"), | |
simple_result == "Defeat" ~ case_when( | |
nchar(judge) >= 4 ~ str_extract(judge, "^\\d{2}(\\.\\d)?"), | |
nchar(judge) == 3 ~ str_extract(judge, "^\\d{1}"), | |
nchar(judge) <= 2 ~ "0" | |
), | |
TRUE ~ NA_character_ | |
) %>% as.numeric(), | |
judge_opponent = case_when( # 敵カウント | |
knockout ~ NA_character_, | |
simple_result == "Defeat" ~ str_extract(judge, "(\\d{2}(\\.\\d)?)%?$") %>% gsub("%", "", .), | |
simple_result == "Victory" ~ case_when( | |
nchar(judge) >= 4 ~ str_extract(judge, "(\\d{2}(\\.\\d)?)%?$") %>% gsub("%", "", .), | |
nchar(judge) == 3 ~ str_extract(judge, "\\d{1}$"), | |
nchar(judge) <= 2 ~ judge | |
), | |
TRUE ~ NA_character_ | |
) %>% as.numeric(), | |
exempted = grepl("Exempted", result), # 免除フラグ | |
kill = as.integer(stringr::str_extract(`k/d`, "^\\d{1,2}")), # キル | |
assist = as.integer(kill_or_assist) - kill, # アシスト | |
kill_assist = kill + assist, # キル+アシスト | |
death = as.integer(stringr::str_extract(`k/d`, "\\s(\\d{1,2})\\s")) # デス | |
) %>% | |
# 回線落ち除外 | |
filter(judge != "") %>% | |
#日本語化 ---- | |
# ロビー | |
left_join( | |
lobby_info %>% select(en_US, ja_JP) %>% distinct(), | |
by = c("lobby" = "en_US") | |
) %>% | |
select(!lobby) %>% rename(lobby = ja_JP) %>% | |
# ルール | |
left_join( | |
rule_info %>% select(name_en_US, short_name_ja_JP) %>% distinct(), | |
by = c("mode" = "name_en_US") | |
) %>% | |
select(!mode) %>% rename(mode = short_name_ja_JP) %>% | |
# ステージ | |
left_join( | |
stage_info %>% select(name_en_US, short_name_ja_JP) %>% distinct(), | |
by = c("stage" = "name_en_US") | |
) %>% | |
select(!stage) %>% rename(stage = short_name_ja_JP) %>% | |
# ブキ | |
left_join( | |
weapon_info %>% select(name.en_US, name.ja_JP) %>% distinct(), | |
by = c("weapon" = "name.en_US") | |
) %>% | |
select(!weapon) %>% rename(weapon = name.ja_JP) %>% | |
# サブウェポン | |
left_join( | |
weapon_info %>% select(sub.name.en_US, sub.name.ja_JP) %>% distinct(), | |
by = c("sub_weapon" = "sub.name.en_US") | |
) %>% | |
select(!sub_weapon) %>% rename(sub_weapon = sub.name.ja_JP) %>% | |
# スペシャル | |
left_join( | |
weapon_info %>% select(special.name.en_US, special.name.ja_JP) %>% distinct(), | |
by = c("special" = "special.name.en_US") | |
) %>% | |
select(!special) %>% rename(special = special.name.ja_JP) %>% | |
arrange(desc(date_time)) %>% | |
# 不要な列の削除 | |
select(!c(judge, result)) -> result | |
``` | |
出力サンプル: https://gist.github.com/nozma/e7fab790288b067b1b867572fa6e703a |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment