Magic: The Gatheringの大会記録をスクレイピングした

有名な米国産カードゲームでMagic: The Gatheringというのがあります(通称MTG)。 Youtubeでよく対戦動画を観たりなどするのですが、ふと「データ分析してみたい」と思いました。

とはいえオープンデータな棋譜が存在するわけでもないので、手に入りやすいデータ資源ってなんだろうと考えると

  • 大会TOP8のデッキレシピおよびプレイヤー名
  • カードのテキスト

あたりが現実的です。 本記事ではステップ1として、大会top8の戦績が公開されているMTG Decks Databaseから大会TOP8のデッキをスクレイピングしてみたときの記録を残します。
※なお、本コードを書くことよりもMTG分析の先行事例を探したりしてネタを練ることの方に時間がかかりました。

コード

R言語にてrvestというパッケージを使ってスクレイピングしました。
スクレイピング先のページ構成を調べきれていないので、まずは「エラー起きたら無視して次のページを読みに行く」というスタンスで作りました。

# まずは自作関数の定義。
# 大会の戦績ページにアクセスして、TOP8のプレイヤー名・デッキ名 etc... をまとめたmatrixを得る。
list_best_decks <- function(event.id){
  tryCatch({
    event.url <- paste0("https://mtgtop8.com/event?e=", event.id)
    event <- read_html(event.url)
    event.exist <- event %>%
      html_node(xpath = "/html/body/div[4]/div/div") %>%
      html_text()
    if (event.exist == "No event could be found."){
      return(c())
    }
    
    event.decks <- event %>%
      html_nodes(xpath = "/html/body/div[4]/div/table/tr/td[1]/div/div")
    event.titles <- event %>%
      html_node(xpath = "/html/body/div[4]/div/div/table") %>%
      html_children()
    event.about <- event %>% 
      html_node(xpath = "/html/body/div[4]/div/table/tr/td[1]/div/table/tr/td/text()[2]") %>% 
      html_text()
    
    decks <- c()
    for (deck in event.decks){
      deck.detail <- html_children(deck)
      
      decks <- rbind(
        decks,
        c(
          event.id,
          event.titles[1] %>% html_text(),
          event.about %>% str_extract("[0-9]{2}/[0-9]{2}/[0-9]{2}"),
          event.about %>% str_extract("^[0-9]+ players") %>% str_extract("[0-9]+"),
          deck.detail[1] %>% html_text(),# rank
          deck.detail[2] %>% html_text(),# name
          deck.detail[3] %>% html_text(),# player
          deck.detail[2] %>% html_nodes("a") %>% html_attr("href") %>%
            str_extract("d=[0-9]+") %>% str_remove("d="), # deck_id
          deck.detail[2] %>% html_nodes("a") %>% html_attr("href") %>%
            str_extract("f=[0-9A-Za-z]+") %>% str_remove("f=") # format
        )
      )
    }
    colnames(decks) <- c("id","title", "date", "n_players", "rank", "name", "player", "deck_id", "format")
  },
  error = function(e) {
    message("ERROR!")
    message(e)           
    decks <- c()
  },
  silent = TRUE)
  return(decks)
}

decks <- c()
for(i in (整数):(整数)){ # スクレイピング先のサイトはeパラメータに大会のidを指定してページを分けているので、ここでその範囲を指定する。
  tryCatch({
    decks <- rbind(
      decks,
      list_best_decks(i)
    )
  },
  error = function(e) {
    message("ERROR!")
    message(e)           
  },
  silent = TRUE)
  
  Sys.sleep(1)
}

参考文献はRの宇宙本です。

www.amazon.co.jp

上記コードを実行した結果

以上によって、まずは2015年10月〜2018年2月の期間で、3万件程度の大会上位デッキのリストを獲得しました。

概観1:レガシーのデータが一番多い

取得したデータの範囲では、レガシーの大会のデータが最も多かったです。

# A tibble: 13 x 2
   format   cnt
   <chr>  <int>
 1 BL         1
 2 CHL       12
 3 EDH      478
 4 EDHM     243
 5 EX         6
 6 HIGH      60
 7 LE      1406 # レガシー
 8 LI       191
 9 MO      1302 # モダン
10 PAU      337
11 PEA      333
12 ST      1097 # スタン
13 VI       609 # ヴィンテージ

概観2:その中でも最人気はグリデル

レガシーフォーマットの中でTOP8ランクイン件数が多い順にデッキを並べるとグリクシスデルバーが一番でした。

# A tibble: 902 x 2
   name            cnt
   <chr>         <int>
 1 Grixis Delver   569
 2 Miracles        312
 3 UW Miracles     307
 4 Eldrazi Aggro   288
 5 Elves           275
 6 Death & Taxes   265
 7 Storm           250
 8 Lands           200
 9 Burn            175
10 Shardless BUG   173

というわけで、戦績データを集めることが出来ました。これを元に何かプレイヤーの意思決定に資する分析成果を出せるよう料理していこうと思います。

需要があるかどうか分からないので、分析成果を読んでやるぞというプレイヤーの方がもしいらっしゃれば大変ありがたい、