R/helpers.R

Defines functions chrome_compatible update_chromedriver chromedriver_version chrome_version clear_all_sessions

Documented in chrome_compatible chromedriver_version chrome_version clear_all_sessions update_chromedriver

#' Clear all RSelenium sessions originating from the current R session
#'
#' @name clear_all_sessions
#'
#' @usage clear_all_sessions()
#'
#' @export
#'
#' @examples
#' \dontrun{
#'   clear_all_sessions()
#' }
#'
clear_all_sessions <- function() {

  # Retreives a list of all objects from the global environment
  all_objects <- sapply(ls(a=TRUE, envir = .GlobalEnv), function(x) { class(get(x)) } )

  # Identifies which objects are of class rsClientServer
  logical <- unname(sapply(all_objects, function(x) { x[1] == "rsClientServer"  }))
  rsClientServerObjects <- names(all_objects[logical])

  # Removes all objects in the global environment whose class is rsClientServer
  if(length(rsClientServerObjects) > 0) { rm(list = rsClientServerObjects, envir = .GlobalEnv) }

  # Collects garbage
  invisible(gc())
  # reset_config()

  print(paste0(length(rsClientServerObjects), " RSelenium sessions cleared"))
}







#' Return the version of Google Chrome
#'
#' @name chrome_version
#'
#' @usage chrome_version()
#'
#' @export
#'
#' @examples
#' \dontrun{
#'   chrome_version()
#' }
#'


chrome_version <- function() {
  os <- Sys.info()['sysname']

  switch(os,
         Windows = {
           # print("retriving windows")
           # From: https://stackoverflow.com/questions/44975653/find-version-of-chrome-browser-in-registry
           strsplit(system("powershell -command \"(Get-Item (Get-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe').'(Default)').VersionInfo\"",
                           intern = T)[4], " ")[[1]][1]
         },

         # Default behaviour (confirmed working from Darwin)

         {
           # print("retriving darwin")
           # From: https://superuser.com/questions/1144651/get-chrome-version-from-commandline-in-mac
           strsplit(system("/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --version",
                           intern = TRUE), " ")[[1]][3]
         }


  )

}





#' Return the version of Chromedriver
#'
#' @name chromedriver_version
#'
#' @usage chromedriver_version()
#'
#' @export
#'
#' @examples
#' \dontrun{
#'   chromedriver_version()
#' }
#'


chromedriver_version <- function() {

  os <- Sys.info()['sysname']

  switch(os,

         Windows = {
           strsplit(system("powershell -command \"chromedriver --version\"", intern = TRUE), " ")[[1]][2]
         },

         # Default behaviour (confirmed working from Darwin)
         {
           tryCatch({

             # Note: mac may return different result through system() than same command from terminal
             strsplit(system("chromedriver --version", intern = TRUE), " ")[[1]][2]
           },
           error = function(e) {
             cat(paste("Issues finding chromedriver binaries - try running 'which chromedriver'",
                          "to locate versions"))
           }) # End tryCatch
         }

  )

}



#' Attempt to install latest version of chromedriver
#'
#' @name update_chromedriver
#' @description This will attempt to update chromedriver to the latest version using homebrew for
#'     macOS. There is currently no equivalent functionality for Windows.
#' @usage update_chromedriver()
#'
#' @export
#'
#' @examples
#' \dontrun{
#'   update_chromedriver()
#' }
#'

update_chromedriver <- function() {

  os <- Sys.info()['sysname']

  switch(os,
         Windows = {
          print("Sorry, this doesn't work for windows")
         },

         # Default behaviour (Mac / Linux)

         {

           # Prompt for user input just to double check
           user_input <- readline("This may remove your existing chromedriver and install the latest
                                   version using homebrew. Do you wish to continue? (y/n)")
           if(user_input != 'y') stop()

           print("Attempting to remove existing chromedriver and install new version")
           print("This may take a minute or two..")
           print("If you're on macOS, try updating chromedriver with update_chromedriver()")
           system("rm $(which chromedriver)") # /usr/local/bin/chromedriver
           system("brew cask install chromedriver")
           system("brew reinstall chromedriver")

          if(grepl("Catalina", utils:::.osVersion()) | grepl("Mojave", utils:::.osVersion())){
           # This deals with permissions on Catalina and Mojave
           # See: “chromedriver” cannot be opened because the developer cannot be verified. error
           # Here: https://stackoverflow.com/a/60374958
           # And here: https://stackoverflow.com/a/60362134/
           system("xattr -d com.apple.quarantine $(which chromedriver)")
          }
         }
  )
}






#' Determine whether Chrome and Chromedriver are compatible
#'
#' @name chrome_compatible
#'
#' @usage chrome_compatible()
#'
#' @export
#' @return Logical vector of length 1
#'
#' @examples
#' \dontrun{
#'   chrome_compatible()
#' }
#'


chrome_compatible <- function() {

  # Awesome info: https://stackoverflow.com/questions/41133391/which-chromedriver-version-is-compatible-with-which-chrome-browser-version/49618567#49618567

  full_chrome_version <- chrome_version()
  full_chromedriver_version <- chromedriver_version()

  chrome_major <- strsplit(full_chrome_version, "\\.")[[1]][1]
  chromedriver_major <- strsplit(full_chromedriver_version ,"\\.")[[1]][1]

  if(chrome_major == chromedriver_major) {
    cat(paste0("Chrome version (",
               full_chrome_version,
               ") and Chromedriver version (",
               full_chromedriver_version,
               ") appear to be compatible\n"))
    return(TRUE)
  }


  if(chrome_major != chromedriver_major) {
    warning(paste0("Chrome (",
                   full_chrome_version,
                   ") and Chromedriver version (",
                   full_chromedriver_version,
                   ") may be **incompatible**\n"))
    return(FALSE)
  }

}






#' Retrieve HTML in fashion similar to rvest's read_html()
#'
#' @name read_html_selenium
#'
#' @usage read_html_selenium()
#'
#' @export
#' @return Logical vector of length 1
#'
#' @import xml2 dplyr
#' @examples
#' \dontrun{
#'   library(RSelenium)
#'   library(netstat)
#'   rD <- rsDriver(browser=c("chrome"), verbose = TRUE, port=free_port(), chromever = chromedriver_version())
#'   remDr <- rD$client
#'   read_html_selenium("https://cran.r-project.org/web/packages/available_packages_by_name.html",
#'   driver = "remDr")
#' }
#'


read_html_selenium <- function (page_url, driver, sleep) {
  # Assume remote_driver input is an object called remDr in the global environment, unless something else is supplied
  if (missing(driver)) {
      driver <- remDr
  }

  if (missing(sleep)) {
    sleep <- 0
  }

  tmp <- page_url %>% remDr$navigate(.)
  Sys.sleep(sleep)
  tmp %>%
    remDr$getPageSource(.) %>%
    .[[1]] %>% .[1] %>% read_html(.)
}




#' Retrieves HTML for given URL and opens the source in Chrome or specified application. A critical
#'     difference between a function like this and one like read_html() is that this one reads the
#'     page HTML -after- the page has finished loading, including running of execution of javascript.
#'
#' @name open_interactive_url
#'
#' @usage open_interactive_url(link, application)
#'
#' @export
#' @return Character vector of length 1, which is subsequently opened with the specified application
#'
#' @import  dplyr
#' @examples
#' \dontrun{
#'
#' # Open HTML in Chrome
#' open_interactive_url("https://cran.r-project.org/web/packages/available_packages_by_name.html")
#'
#' # Open in another application (e.g. Sublime Text)
#' open_interactive_url("https://cran.r-project.org/web/packages/available_packages_by_name.html",
#' "Sublime Text")
#' }
#'

open_interactive_url <- function(link, application) {

  if(missing(application)) {
    application <- "Google Chrome"
  }

  if(application == "Chrome"){
    application <- "Google Chrome"
  }

  temp_file <- tempfile()
  read_html_selenium(link) %>%
    as.character %>% writeLines(., temp_file)
  system(paste0('open -a "', application, '" ', temp_file))
}





#' Opens the HTML source (already retrieved via read_html() or read_html_selenium()
#'     in Chrome or specified application. A critical
#'     difference between a function like this and one like read_html() is that this one reads the
#'     page HTML -after- the page has finished loading, including running of execution of javascript.
#'
#' @name open_interactive_html_obj
#'
#' @usage open_interactive_html_obj()
#'
#' @export
#' @return Character vector of length 1, which is subsequently opened with the specified application
#'
#' @import  dplyr
#' @examples
#' \dontrun{
#'
#' # Open output of read_html() or read_html_selenium() in Chrome
#' page_html <- read_html_selenium("https://cran.r-project.org/web/packages/available_packages_by_name.html")
#' open_interactive_html_obj(page_html)
#'
#' # Open in another application (e.g. Sublime Text)
#' open_interactive_html_obj(page_html, "Sublime Text")
#' }
#'


open_interactive_html_obj <- function(page_html, application) {

  if(missing(application)) {
    application <- "Google Chrome"
  }

  if(application == "Chrome"){
    application <- "Google Chrome"
  }

  temp_file <- tempfile()
  page_html %>%
    as.character %>% writeLines(., temp_file)
  system(paste0('open -a "', application, '" ', temp_file))
}
stevecondylios/RSeleniumHelpers documentation built on Dec. 31, 2020, 7:34 a.m.