netkeibaのレース条件のスクレイピング結果から、race_idを取り出して、その値をもとに、「競馬新聞&スピード指数(無料)」のサイトからスピード指数をスクレイピングしています。
スクレイピングを始める前に
Rでスクレイピングをするならrvestパッケージを使うのが簡単です。また、スクレイピングをするためにはHTML/CSSの理解も必要。とりあえず、これだけ知っていればスクレイピングは始められます。
Rでスクレイピングするならrvest 表もリンクもテキストも
Rでスクレイピングをするならrvestパッケージを使うのがベスト。表データ、リンク先URL、テキストなどのデータを簡単に入手できます。netkeibaのレース結果を題材にrvestパッケージの使い方をまとめています。
スクレイピングに必要な最低限のHTML/CSSの知識
スクレイピングでデータを収集するためには、HTMLで書かれたWebページの文書構造を理解し、どこに目的のデータが記載されているかをコンピュータに教えてやる必要があります。このページではスクレイピングに最低限必要なHTML/CSSの知識をまとめています。
スピード指数を取得する
このページは以下の記事に対応するRのソースコードを記載しています。
データサイエンスで競馬に挑戦!Rでスピード指数をスクレイピング
ソースコード
library(tidyverse)
library(lubridate)
library(rvest)
get_speed_index <- function(race_id){
#urlの設定
race_id2 <- substr(race_id, 3, 12)
url_base <- "http://jiro8.sakura.ne.jp/index.php?code="
url <- paste0(url_base, race_id2)
#スクレイピング
df.speed <- read_html(url, encoding = "CP932") %>%
html_element(css = "table.c1") %>%
html_table()
Sys.sleep(1)
#取得したデータの後処理
#必要な行の抽出
n_start <- str_which(df.speed$X1, "[牡|牝|せ]")
df.speed2 <- df.speed[c(2, n_start:nrow(df.speed)), ]
df.speed3 <- df.speed2[1:15, ]
#必要な列の抽出
n_col <- df.speed3[1,] %>%
as.character() %>%
str_which("馬番")
n_col <- n_col -1
df.speed4 <- df.speed3[, 1:n_col]
#行と列の入れ替え(転置)
df.speed5 <- t(df.speed4)
df.speed5 <- data.frame(df.speed5)
#データ形式の整理
df.speed6 <- df.speed5 %>%
mutate(race_id = race_id,
X1 = as.integer(X1),
X12 = as.numeric(X12),
X13 = as.numeric(X13),
X14 = as.numeric(X14),
X15 = as.numeric(X15),
X6 = as.integer(str_remove(X6, "着"))
) %>%
relocate(race_id,)
#行名、列名の整理
rownames(df.speed6) <- NULL
colnames(df.speed6) <- c("race_id", "馬番", "性齢", "斤量2",
"騎手", "調教師", "着順", "オッズ",
"レース結果", "ペース/脚質/上3F",
"通過順", "馬体重", "先行指数",
"ペース指数", "上がり指数", "スピード指数")
df.speed6 <- df.speed6 %>%
arrange(着順) %>%
relocate(着順, .after = race_id)
df.speed6
}
df.race.cond <- readRDS("df.race.cond.2012to2021.rds")
race_ids <- df.race.cond$race_id
filename.speed_index <- "df.speed_index.rds"
#####################################################
# 1回目の場合(df.speed_indexが存在しない場合)
#####################################################
#
i <- 1
race_id <- race_ids[i]
df.speed_index <- get_speed_index(race_id)
saveRDS(df.speed_index, filename.speed_index)
###############################################################
# 2回め以降(filename.speed_indexで指定したファイルがある場合はここから)
###############################################################
df.speed_index <- readRDS(filename.speed_index)
(n_done <- length(unique(df.speed_index$race_id)))
i <- 0
id_count <- 0
tmp.df.speed_index <- NULL
tmp.filename.speed_index <- "tmp.df.speed_index.rds"
(id_max <- length(race_ids))
(max_id_to_calc <- min(n_done + 200000, id_max)) #最大処理回数(途中の確認用)
system.time({
while(id_count < max_id_to_calc){
i <- i + 1
id_count <- n_done + i
cat(paste("id_count =", id_count,
"(",
floor(id_count/id_max*100*10) / 10,
"%)",
format(Sys.time(), "%H:%M:%S \n"),
sep = " "
)
)
race_id <- race_ids[id_count]
# tmpファイルの処理
if( is.null(tmp.df.speed_index)){
tmp.df.speed_index <- get_speed_index(race_id)
}else{
tmp.df.speed_index <- rbind(tmp.df.speed_index,
get_speed_index(race_id))
}
if(id_count %% 100 == 0 | id_count == max_id_to_calc){
cat("Save\n")
df.speed_index <- rbind(df.speed_index, tmp.df.speed_index)
saveRDS(df.speed_index, tmp.filename.speed_index)
tmp.df.speed_index <- NULL
i <- 0
n_done <- length(unique(df.speed_index$race_id))
}
}
})
(n_done <- length(unique(df.speed_index$race_id)))
saveRDS(df.speed_index, filename.speed_index)