4

I am using RSelenium to navigate to sites and interact with the elements.

Question: using RSelenium, how can I read the list of options in a dropdown menu so that I can identify the latest month available and use that to set the dropdown to the correct value?

On a certain site a dropdown menu is provided for the user to set the month of the year, thus defining the end point of a date range used in turn to display or download monthly data. As additional months of data become available through the year, the options in the dropdown change.

Dropdown menu options

By the end of July the dropdown will have 6 options, January to June. Note that the data for a particular month is released about 4-6 weeks after the end of that month, so you do not get June's data until late July, and so on. I can set the values using numbers 1 to 12 without any problems, provided that the dropdown actually contains the corresponding option.

If, for example, the data for July has not yet been published (that is, if July has not yet appeared in the dropdown list of options) and if I try to set the dropdown to '7' I will get an error, which I want to avoid. The data does not appear on a regular schedule, so I cannot simply assume that the data for month X will appear on date Y.

I believe that with Selenium itself there is a helper class available, but I'm not sure whether I can access that through RSelenium.

Example code follows - may be a bit ropey as I'm still far from familiar with the package.

library(RSelenium)
RSelenium::checkForServer()
RSelenium::startServer()

remDr <- remoteDriver(remoteServerAddr = "localhost",
                      port = 4444,
                      browserName = "firefox"
                      )
remDr <- remoteDriver()
Sys.sleep(5)
remDr$open()
remDr$getStatus()

remDr$navigate("http://jamaserv.jama.or.jp/newdb/eng/index.html")

## Switch to left frame
frameElems <- remDr$findElements(using = "tag name", "frame")
sapply(frameElems, function(x){x$getElementAttribute("src")})
remDr$switchToFrame(frameElems[[1]])

webElem <- remDr$findElement(using = 'xpath', "//select[@name='txtTargetToMm']")

## Use javascript to set values
script <- paste0("arguments[0].value = '", 2, "'; arguments[0].onchange();") # set to February
remDr$executeScript(script, list(webElem))
webElem$getElementAttribute('value')    # check to see if it worked
Community
  • 1
  • 1
SlowLearner
  • 7,485
  • 9
  • 41
  • 76
  • Sometimes I like to pull the curl request directly from the development console and just wrap it in `system`. It's not pretty, but it almost always works. Open the console, switch to the network tab, perform your action, right click on element with your data, Copy as curl. – Brandon Bertelsen Jul 24 '15 at 17:56
  • Thanks for that; interesting tip. – SlowLearner Jul 24 '15 at 18:52

1 Answers1

6

You can use the selectTag method to interact with HTML select elements:

library(RSelenium)

rD <- rsDriver(verbose = F)
remDr <- rD$client
remDr$navigate("http://jamaserv.jama.or.jp/newdb/eng/index.html")

## Switch to left frame
frameElems <- remDr$findElements(using = "tag name", "frame")
sapply(frameElems, function(x){x$getElementAttribute("src")})
remDr$switchToFrame(frameElems[[1]])

webElem <- remDr$findElement(using = 'xpath', "//select[@name='txtTargetToMm']")
opts <- webElem$selectTag()

> opts$text
[1] "JANUARY"   "FEBRUARY"  "MARCH"     "APRIL"     "MAY"       "JUNE"      "JULY"      "AUGUST"   
[9] "SEPTEMBER" "OCTOBER"   "NOVEMBER"  "DECEMBER" 
> opts$value
[1] "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10" "11" "12"
> opts$selected
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

# select the third month (march)
opts$elements[[3]]$clickElement()

# check whether it is selected
opts <- webElem$selectTag()
opts$selected

> opts$selected
[1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

rm(rD)
gc()
jdharrison
  • 28,335
  • 4
  • 67
  • 86
  • 1
    If I try to run your code, but I get an error `Error: attempt to apply non-function` when trying to execute `opts$elements[[3]]$clickElement()`. – Til Hund Feb 21 '18 at 10:51