Skip to content

Instantly share code, notes, and snippets.

@nozma
Last active November 28, 2022 22:40
Show Gist options
  • Save nozma/7a6eceb463d89f5dd9155901e20944cb to your computer and use it in GitHub Desktop.
Save nozma/7a6eceb463d89f5dd9155901e20944cb to your computer and use it in GitHub Desktop.
stat.inkからSplatoon 3の戦歴データを取得する
---
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