論理の流刑地

地獄の底を、爆笑しながら闊歩する

各選手の先発ポジションを取得する

ほしいもの

過去記事などで触れたようにSofaScoreから各選手の試合別スタッツは取得できる。
ronri-rukeichi.hatenablog.com

だが、若干分析上不便であるのが、ポジションがGK/DF/FW/MFの4区分でしか取得*1できないことである。
集計・グループ分けしてポジション別に比較をしたい、となったときCBとSBがごっちゃになったりボランチとトップ下とSHが一緒くたになるのは都合が悪い。

そこで活用できるのがFootBoolLABの選手別ページ(例:森下の2021年版となる)

f:id:ronri_rukeichi:20211211102001p:plain
名古屋グランパス・森下選手の先発ポジション分布

上のように、その選手の先発ポジションの分布が年別に表示されている。
このページを見れば、ある選手がある年にSBで何試合、CBで何試合出たのかといったことが分かる。

このページからのデータ取得を試みる

How to

個別選手について

先発ポジ分布図について、Google Chromeの検証ツールをみて構造を確認すると、以下のように表示されている。

f:id:ronri_rukeichi:20211211110319p:plain
Chromeの検証ツール

dlタグ配下のdtタグがポジション名を、ddタグが先発試合数を表わす
ということで、以下のコードのような関数をかけば取得できる

getPosition <- function( url ){
  tgt_pg <- read_html( url)
  #Position情報を含むNodeを検出する
 pos_nodes <- html_nodes(tgt_pg, css = ".playerPos dl")

  pos_info <- lapply( pos_nodes , function(pos_node){
    pos_name <- pos_node %>>% html_node("dt") %>>% html_text()
    pos_n <- pos_node %>>% html_node("dd") %>>% html_text()
    return( data.frame( Name = pos_name , N = pos_n))
  })
  ret_df <- do.call( bind_rows , args = pos_info)
  
  return(ret_df)
} #func

#森下選手のURL
mori_url <- "https://www.football-lab.jp/player/1629426/?year=2021"
#森下選手のポジション分布を取得
mori_pos <- getPosition(mori_url)

実際に、データは以下のような形で取得できる。

f:id:ronri_rukeichi:20211211112736p:plain

クラブ単位での取得

さて、最終的にはこれを全選手について取得したデータベースを作りたい、というのが目指すところである。
各クラブ別に所属選手を全取得したDBを自動的に生成できるようにすれば、リーグ全体のDBも容易に作成できる。

方針としては、クラブごとのサマリページ(例:名古屋のページ)から
各選手ページへのリンクを取得し、そこから先ほどの関数を適用して選手別データをひろってくる。

getClubPos <- function(club_name, year = 2021){
  #対象URLを取得
  tgt_url <- paste0( "https://www.football-lab.jp/" ,club_name,"/?year=", year)
  cat(tgt_url)
  clb_page <- read_html( tgt_url)
  
  #選手名, 背番号, 個別ページへのリンクを取得
  player_links <- html_nodes(clb_page,css = ".statsTbl10 a") %>>% sapply( function(x){html_attr( x, name= "href")})
  player_names <- html_nodes(clb_page , css = ".statsTbl10 a") %>>% sapply( html_text)
  player_no <-  html_nodes(clb_page ,css = ".statsTbl10 tr td:first-child+td") %>% sapply( html_text) %>>% as.numeric
  
  
  #選手ごとのループを回す
  player_dfs <- lapply( player_links , function(p_chr){
    full_url <- paste0(  "https://www.football-lab.jp", p_chr, "?year=", year)
    player_df <- getPosition( full_url)
    
    #タテからヨコに
    df_w <- pivot_wider( player_df ,names_from= "Name", values_from="N")
    return(df_w)
  } ) #player_dfs


  #横になったものをタテにつなげる
  ret_df <- do.call(bind_rows   , args = player_dfs )
  #選手名、背番号の列を追加
  ret_df <- data.frame(PlayerName = player_names , ShirtNo = player_no ) %>>% bind_cols( ret_df)


  return( ret_df)
} #function

ngePosInfo <- getClubPos("nago")

Hadley神が創りし神関数であるtidyr::pivot_wider()を利用して、タテからヨコにデータを溶かしているのが肝です。
確認すると、以下のような形でデータができている

f:id:ronri_rukeichi:20211211134540p:plain

あとは、J1の全チームに同じ処理を回して、タテにつなげればよい。
これで、「SBとして15試合以上先発している選手」どうしの比較などができるようになった。



www.youtube.com


Enjoy!!

*1:スクレイピングをおこなうさいは、politeパッケージなどを利用して(参考URL)迷惑がかからないようにしましょう。