RSelenium
RSelenium copied to clipboard
RSelenium::rsDriver() should auto-detect proper ChromeDriver if `browser = "chrome"`
This is a suggestion to auto-detect the proper ChromeDriver version because it happens regularly that the default setting chromever = "latest"
selects a ChromeDriver version that's ahead of the current stable Chrome browser version.
I'd suggest something like the following to select the latest ChromeDriver version matching the major-minor-patch version number of the system's stable Google Chrome browser:
# Get installed stable Google Chrome version ...
if (xfun::is_unix()) {
chrome_driver_version <-
system2(command = ifelse(xfun::is_macos(),
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"google-chrome-stable"),
args = "--version",
stdout = TRUE,
stderr = TRUE) %>%
stringr::str_extract(pattern = "(?<=Chrome )(\\d+\\.){3}")
## on Windows a plattform-specific bug prevents us from calling the Google Chrome binary directly to get its version number
## cf. https://bugs.chromium.org/p/chromium/issues/detail?id=158372
} else if (xfun::is_windows()) {
chrome_driver_version <-
system2(command = "wmic",
args = 'datafile where name="C:\\\\Program Files (x86)\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe" get Version /value',
stdout = TRUE,
stderr = TRUE) %>%
stringr::str_extract(pattern = "(?<=Version=)(\\d+\\.){3}")
} else rlang::abort(message = "Your OS couldn't be determined (Linux, macOS, Windows) or is not supported.")
# ... and determine most recent ChromeDriver version matching it
chrome_driver_version %<>%
magrittr::extract(!is.na(.)) %>%
stringr::str_replace_all(pattern = "\\.",
replacement = "\\\\.") %>%
paste0("^", .) %>%
stringr::str_subset(string =
binman::list_versions(appname = "chromedriver") %>%
dplyr::last()) %>%
as.numeric_version() %>%
max() %>%
as.character()
This procedure should adhere to the official ChromeDriver versioning scheme. Quote:
- ChromeDriver uses the same version number scheme as Chrome (...)
- Each version of ChromeDriver supports Chrome with matching major, minor, and build version numbers. For example, ChromeDriver 73.0.3683.20 supports all Chrome versions that start with 73.0.3683.
Ideally, we'd check if Chrome is available on the system at all before running system2()
and also take the open-source Chromium into consideration (make it conditional on param browser
).
@juyeongkim Any comment on this?
I'd be willing to prepare a PR if you would provide some implementaion guidance (i.a. what pkgs I can use)...
Thanks for putting this together. It doesn't quite work on my MacOS system: because system2()
calls shQuote
on the command
argument, you shouldn't escape the spaces. Once that is fixed, it does appear to work.
It doesn't quite work on my MacOS system: because
system2()
callsshQuote
on thecommand
argument, you shouldn't escape the spaces. Once that is fixed, it does appear to work.
Thanks for the reminder! I've updated the first post accordingly.
Any developments on this issue? Having just run into this problem, then finding this issue, this looks like it would be an extremely valuable addition to RSelenium.
I've been using Salim's solution, and it's been working fine on MacOS.
Ah, I had the impression that the suggestion was to roll this solution into the rsDriver()
code itself.
Ah, I had the impression that the suggestion was to roll this solution into the
rsDriver()
code itself.
That was the idea when I filed this issue. But I've never heard back from @juyeongkim (or another project member)...
The code outlined above is not perfect. For example, we shouldn't rely on binman::list_versions()
since it just returns an error in case of a fresh install where no ChromeDriver versions had been downloaded before. Instead, https://chromedriver.storage.googleapis.com/index.html
should be parsed directly.
I'd just go ahead and prepare the PR, using your own judgment about what to use. At a minimum, that would make it easier for others to incorporate your suggestion (by forking) if the maintainer doesn't act on it.
I'd just go ahead and prepare the PR (...)
I've submitted #237. Until it gets merged (if at all), you can install it with
remotes::install_github("ropensci/RSelenium#237")
Then you can call rsDriver()
with the new chromever = "latest_compatible"
option like this:
RSelenium::rsDriver(browser = "chrome",
chromever = "latest_compatible")
Feedback welcome! I've only tested it on Linux so far but it should work on macOS and Windows since the code is based on earlier feedback from users of these systems (i.a. @dmurdoch 😄).
Hi, @salim-b . Your solution, unfortunately throws an error for me. The error is as follows:
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, :
arguments imply differing number of rows: 1, 0
The details of my system are:
_
platform x86_64-w64-mingw32
arch x86_64
os mingw32
system x86_64, mingw32
status
major 4
minor 0.2
year 2020
month 06
day 22
svn rev 78730
language R
version.string R version 4.0.2 (2020-06-22)
nickname Taking Off Again
I'm running Windows Server 2019, Version 1809, OS Build, 17763.1518. Chrome seems to launch however, but the error message is thrown nonetheless.
Any ideas how to fix this?
@mlamias Are you sure the error you've posted originates from launching rsDriver()
?
What happens if you just enter the following into an R prompt:
rd <- RSelenium::rsDriver(browser = "chrome",
chromever = "latest_compatible")
rd$client$close()
rd$server$stop()
@salim-b, thanks for your help. Indeed I have my code working now. I'm not sure what happened, but it seemed once I bounced our server the error resolved itself. I absolutely love this solution and saves me lots of headaches. Consider my issues resolved.
Thanks again! Great piece of code!
remotes::install_github("ropensci/RSelenium#237")
doesn't work for me to get the intermediate fix.
traceback() results in the following: 6: stop("Cannot find GitHub pull request ", params$username, "/", params$repo, "#", x, "\n", response$message) 5: github_resolve_ref.github_pull(meta$ref %||% ref, meta, host = host, auth_token = auth_token) 4: github_resolve_ref(meta$ref %||% ref, meta, host = host, auth_token = auth_token) 3: FUN(X[[i]], ...) 2: lapply(repo, github_remote, ref = ref, subdir = subdir, auth_token = auth_token, host = host) 1: remotes::install_github("ropensci/RSelenium#237")
If I run your entire code, the code itself doesn't throw any errors. However, calling
rD <- rsDriver(browser=c("chrome"), chromever="latest_compatible", port = 4444L)
results in
checking Selenium Server versions:
BEGIN: PREDOWNLOAD
BEGIN: DOWNLOAD
BEGIN: POSTDOWNLOAD
checking chromedriver versions:
BEGIN: PREDOWNLOAD
BEGIN: DOWNLOAD
BEGIN: POSTDOWNLOAD
Error in chrome_ver(chromecheck[["platform"]], chromever) :
version requested doesnt match versions available = 2.28,2.29,2.30,80.0.3987.106,81.0.4044.138,81.0.4044.20,81.0.4044.69,83.0.4103.14,83.0.4103.39,84.0.4147.30,85.0.4183.38,85.0.4183.83,85.0.4183.87,86.0.4240.22,87.0.4280.20,87.0.4280.88,88.0.4324.27
I'm having the issue this pull request is meant to fix: My installed Chrome version is 87.0.4280.88 but RSelenium appears to be using version 8, which is unstable.
Any advice?
If I follow those instructions it doesn't work for me either, but I've been using the code below based on the PR, and it works fine with the CRAN version of RSelenium:
rsStuff <- local({
rD <- NULL
driver <- function(port = 4567L, force = FALSE, verbose = FALSE) {
if (force)
rD <<- NULL
if (!is.null(rD))
return(rD)
versions <- binman::list_versions("chromedriver")
versions <- c(versions$mac64, getChromeDriverVersion(versions))
v <- length(versions) + 1
while (v && (is.null(rD) || inherits(rD, "condition"))) {
v <- v - 1 # Try each value
rD <<- tryCatch(rsDriver(verbose = verbose,
port = port + sample(0:1000, 1),
chromever=versions[v],
geckover = NULL,
phantomver = NULL), error = function(e) e,
message = function(m) m)
}
rD
}
kill <- function() {
try(rD$server$stop())
rD <<- NULL
}
list(driver = driver, kill = kill)
})
getrsDriver <- rsStuff$driver
killrsDriver <- rsStuff$kill
rm(rsStuff)
The idea is that I set remDr <- getrsDriver()$client
, and it works for me. There seems to be a bug in RSelenium; if I try to print getrsDriver()
, it dies with this error:
> getrsDriver()
$client
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, :
arguments imply differing number of rows: 1, 0
This is very frustrating (it worked just yesterday!) - but thank you for lending a hand.
When I use your code and call remDr <- getrsDriver()$client
, I get the following:
Error in getChromeDriverVersion(versions) :
could not find function "getChromeDriverVersion"
It seems like you might be on a Mac. Does that make a difference?
Sorry, I forgot that was part of my code. Here it is:
getChromeDriverVersion <- function(versions = binman::list_versions("chromedriver")) {
if ( xfun::is_unix() ) {
chrome_driver_version <-
system2(command = ifelse(xfun::is_macos(),
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"google-chrome-stable"),
args = "--version",
stdout = TRUE,
stderr = TRUE) %>%
stringr::str_extract(pattern = "(?<=Chrome )(\\d+\\.){3}")
## on Windows a plattform-specific bug prevents us from calling the Google Chrome binary directly to get its version number
## cf. https://bugs.chromium.org/p/chromium/issues/detail?id=158372
} else if ( xfun::is_windows() ) {
chrome_driver_version <-
system2(command = "wmic",
args = 'datafile where name="C:\\\\Program Files (x86)\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe" get Version /value',
stdout = TRUE,
stderr = TRUE) %>%
stringr::str_extract(pattern = "(?<=Version=)(\\d+\\.){3}")
} else rlang::abort(message = "Your OS couldn't be determined (Linux, macOS, Windows) or is not supported!")
# ... and determine most recent ChromeDriver version matching it
chrome_driver_version %>%
magrittr::extract(!is.na(.)) %>%
stringr::str_replace_all(pattern = "\\.",
replacement = "\\\\.") %>%
paste0("^", .) %>%
stringr::str_subset(string = dplyr::last(versions)) %>%
as.numeric_version() %>%
max() %>%
as.character()
}
That works! Very, very much appreciate it!
traceback() results in the following: 6: stop("Cannot find GitHub pull request ", params$username, "/", params$repo, "#", x, "\n", response$message) 5: github_resolve_ref.github_pull(meta$ref %||% ref, meta, host = host, auth_token = auth_token) 4: github_resolve_ref(meta$ref %||% ref, meta, host = host, auth_token = auth_token) 3: FUN(X[[i]], ...) 2: lapply(repo, github_remote, ref = ref, subdir = subdir, auth_token = auth_token, host = host) 1: remotes::install_github("#237")
(...)
Any advice?
The error message above seems to indicate you tried to install my PR branch's RSelenium version with remotes::install_github("#237")
instead of remotes::install_github("ropensci/RSelenium#237")
... ?
But anyways, technically remotes::install_github("ropensci/RSelenium#237")
should be equivalent to remotes::install_github(repo = "salim-b/RSelenium", ref = "chromedriver-detection")
. Does the latter work? (Maybe the "repo#ref" syntax was introduced only recently to the remotes::install_*
functions and your local version of the package is outdated?)
I was encountering an error about "SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 91"
Commenting to confirm that remotes::install_github("ropensci/RSelenium#237")
fixed this error running Chrome Version 90.0.4430.85 (Official Build) (64-bit)
(V 91 is still in beta) and is working with this session configuration:
R version 4.0.2 (2020-06-22)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19042)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods
[7] base
other attached packages:
[1] Rideshare2Vote_0.0.0.9000 RevoUtils_11.0.2
[3] RevoUtilsMath_11.0.0
loaded via a namespace (and not attached):
[1] xfun_0.22 tidyselect_1.1.0 remotes_2.2.0
[4] purrr_0.3.4 vctrs_0.3.6.9000 generics_0.1.0
[7] testthat_3.0.1 usethis_1.6.3 yaml_2.2.1
[10] utf8_1.2.1 blob_1.2.1 XML_3.99-0.6
[13] rlang_0.4.10 pkgbuild_1.2.0 pillar_1.5.1
[16] glue_1.4.2 withr_2.3.0 DBI_1.1.1
[19] rappdirs_0.3.3 semver_0.2.0 sessioninfo_1.1.1
[22] lifecycle_1.0.0 stringr_1.4.0 binman_0.1.2
[25] devtools_2.3.2 caTools_1.18.2 memoise_1.1.0
[28] wdman_0.2.5 callr_3.5.1 ps_1.6.0
[31] curl_4.3 fansi_0.4.2 Rcpp_1.0.6
[34] clipr_0.7.1 readr_1.4.0 openssl_1.4.3
[37] desc_1.2.0 pkgload_1.1.0 jsonlite_1.7.2
[40] RSelenium_1.7.7.9000 debugme_1.1.0 fs_1.5.0
[43] hms_0.5.3 askpass_1.1 digest_0.6.27
[46] stringi_1.5.3 processx_3.5.1 dplyr_1.0.5
[49] rprojroot_2.0.2 cli_2.3.1 tools_4.0.2
[52] bitops_1.0-6 magrittr_2.0.1 tibble_3.1.0
[55] crayon_1.4.1 tidyr_1.1.3 pkgconfig_2.0.3
[58] ellipsis_0.3.1 xml2_1.3.2 prettyunits_1.1.1
[61] assertthat_0.2.1 httr_1.4.2 rstudioapi_0.13
[64] R6_2.5.0 compiler_4.0.2
Thank you @salim-b!
Circling back to this because it looks like available ChromeDriver versions and available Chrome versions (92.0.4515.159) have de-synchronized making it such that there's no way to run RSelenium with Chrome (unless you happen to have a legacy version of Chrome).
Does anyone have a Chrome 32-bit installation MSI compatible with either of the current chromeDriver versions?
-
Latest beta release: ChromeDriver 93.0.4577.15
-
Latest stable release: ChromeDriver 92.0.4515.107