Я попробовал. При обработке исключений мне нравится использовать что-то вроде
check <- try(expression, silent = TRUE) # or suppressMessages(try(expression, silent = TRUE))
if (any(class(check) == "try-error")) {
# do stuff
}
Я считаю его удобным в использовании, и обычно он отлично работает, в том числе при использовании селена. Однако проблема, возникающая здесь, заключается в том, что нажатие на стрелку один раз всегда приводит меня к последним видимым листам - пропуская все посередине.
Альтернативное решение
Итак, вот альтернатива, которая решит задачу очистки таблиц , а не задачу обработки исключений в вышеприведенном смысле.
Код
# Alernative: -------------------------------------------------------------
remDr <- RSelenium::remoteDriver(
remoteServerAddr = "192.168.99.100",
port = 4445L
)
remDr$open(silent = TRUE)
# navigate to the main page
# needs no be done once before looping, else content is not available
remDr$navigate("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=690408156")
# I. Preliminaries:
#
# 1. build the links to all spreadsheets
# 2. define the function create_table
#
# 1.
# get page source
html <- remDr$getPageSource()[[1]]
# split it line by line
html <- unlist(strsplit(html, '\n'))
# restrict to script section
script <- grep('^\\s*var\\s+gidMatch', html, value = TRUE)
# split the script by semi-colon
script <- unlist(strsplit(script, ';'))
# retrieve information
sheet_months <- gsub('.*name:.{2}(.*?).{1},.*', '\\1',
grep('\\{name\\s*\\:', script, value = TRUE), perl = TRUE)
sheet_gid <- gsub('.*gid:.{2}(.*?).{1},.*', '\\1',
grep('\\gid\\s*\\:', script, value = TRUE), perl = TRUE)
sheet_url <- paste0('https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pubhtml/sheet?headers%5Cx3dfalse&gid=',
sheet_gid)
#
# 2.
# table yielding function
# just for readability in the loop
create_table <- function (remDr) {
# parse html with XML package
doc <- XML::htmlParse(remDr$getPageSource()[[1]])
Sys.sleep(3)
# Extract data from HTML table in HTML document
table_tmp <- XML::readHTMLTable(doc)
Sys.sleep(3)
# put this into a format you can use
table <- table_tmp[[1]][-2, -1]
# add a check-up for size mismatch
table_fields <- as.character(t(table[1,]))
if (! any(grepl("size", tolower(table_fields)))) {
table <- table[-1, ]
# rename the columns
colnames(table) <- c("team_name", "start_time", "end_time", "total_time", "puzzels_solved")
table$team_size <- NA_integer_
table <- table[,c("team_name", "team_size", "start_time", "end_time", "total_time", "puzzels_solved")]
} else {
table <- table[-1, ]
# rename the columns
colnames(table) <- c("team_name", "team_size", "start_time", "end_time", "total_time", "puzzels_solved")
}
# add city name to a column
table$city <- rep("Montreal", nrow(table))
# add the Month/Year this table was extracted from
today <- Sys.Date()
lubridate::month(today) <- lubridate::month(today)+1
table$date <- today
# returns the table
table
}
# II. Scrapping the content
#
# 1. selenium to generate the pages
# 2. use create_table to extract the table
#
big_df <- NULL
for (k in seq_along(sheet_url)) {
# 1. navigate to the page
remDr$navigate(sheet_url[k])
# remDr$screenshot(display = TRUE) maybe one wants to see progress
table <- create_table(remDr)
# 2. concatenate each table together
big_df <- dplyr::bind_rows(big_df, table)
# inform progress
cat(paste0('\nGathered table for: \t', sheet_months[k]))
}
# close session
remDr$close()
Результат
Здесь вы можете увидеть head
и tail
из big_df
head(big_df)
# team_name team_size start_time end_time total_time puzzels_solved city date
# 1 Tortoise Tortes 5 19:00 20:05 1:05 5 Montreal 2019-02-20
# 2 Mulholland Drives Over A Smelly Cat 4 7:25 8:48 1:23 5 Montreal 2019-02-20
# 3 B.R.O.O.K. 2 7:23 9:05 1:42 5 Montreal 2019-02-20
# 4 Motivate 4 18:53 20:37 1:44 5 Montreal 2019-02-20
# 5 Fighting Mongooses 3 6:31 8:20 1:49 5 Montreal 2019-02-20
# 6 B Lovers 3 6:40 8:30 1:50 5 Montreal 2019-02-20
tail(big_df)
# team_name team_size start_time end_time total_time puzzels_solved city date
# 545 Ale Mary <NA> 6:05 7:53 1:48 5 Montreal 2019-02-20
# 546 B.R.O.O.K. <NA> 18:45 20:37 1:52 5 Montreal 2019-02-20
# 547 Ridler Co. <NA> 6:30 8:45 2:15 5 Montreal 2019-02-20
# 548 B.R.O.O.K. <NA> 18:46 21:51 3:05 5 Montreal 2019-02-20
# 549 Rotating Puzzle Collective <NA> 18:45 21:51 3:06 5 Montreal 2019-02-20
# 550 Fire Team <NA> 19:00 22:11 3:11 5 Montreal 2019-02-20
Краткое объяснение
Чтобы выполнить задачу, я сначала создал ссылки на все электронные таблицы в документе. Для этого:
- Перейдите один раз к документу
- Извлечение исходного кода
- Извлеките листовые месяцы и URL-адреса (через
gid
цифру), используя regex
Как только это будет сделано, переберите URL-адреса, соберите и свяжите таблицы
Кроме того, для удобства чтения я создал небольшую функцию с именем create_table
, которая возвращает таблицу в правильном формате. В основном это код, включенный в ваш цикл. Я только добавил меру безопасности для количества столбцов (некоторые электронные таблицы не имеют поля team_size
- в этих случаях я установил его на NA_integer
).