Цикл и загрузка csvs с сайта с несколькими выпадающими меню с использованием rselenium и docker - PullRequest
0 голосов
/ 19 февраля 2020

это мой первый вопрос здесь. Я и мой коллега некоторое время искали и читали некоторые решения, но не нашли ничего, что, по-видимому, могло бы иметь отношение к проблеме, с которой мы имеем дело.

Мы пытаемся собрать CSV с этого сайта:

https://sit.trabalho.gov.br/radar/

на вкладке FGTS слева.

Мы хотели бы загрузить один CSV для каждой комбинации города (муниципалитета) и экономики c (CNAE) за все доступные годы (ano). На сайте каждый CSV для каждой комбинации города и сектора может быть загружен и затем загружен после выбора города в третьем раскрывающемся меню вниз и затем выбора каждого сектора из четвертого раскрывающегося меню вниз (игнорируя два верхних раскрывающихся меню, так как мы не заинтересованы в указании c лет). Это создает график в нижней части страницы и всплывающее меню в правом верхнем углу графика с возможностью сохранения базовых данных в формате CSV (Salvar em ... CSV). На данный момент мы написали следующий код с использованием rselenium в Rstudio и docker desktop на Win 10 Pro:

packages <- c("magrittr", "XML", "RCurl", "RSelenium", "stringr", "xml2")
to.install <- setdiff(packages, rownames(installed.packages()))
if (length(to.install) > 0) {
  install.packages(to.install, dependencies = T )
}
lapply(packages, library, character.only = TRUE)

custom_firefox <- makeFirefoxProfile(
  list(
    "browser.download.dir" = "~/Downloads",
    "browser.download.folderList" = 2L,
    "browser.download.manager.showWhenStarting" = FALSE,
    "browser.helperApps.neverAsk.openFile" = "multipart/x-zip,application/zip,application/x-zip-compressed,application/x-compressed,application/msword,application/csv,text/csv,image/png ,image/jpeg, application/pdf, text/html,text/plain,  application/excel, application/vnd.ms-excel, application/x-excel, application/x-msexcel, application/octet-stream",
    "browser.helperApps.neverAsk.saveToDisk" = "multipart/x-zip,application/zip,application/x-zip-compressed,application/x-compressed,application/msword,application/csv,text/csv,image/png ,image/jpeg, application/pdf, text/html,text/plain,  application/excel, application/vnd.ms-excel, application/x-excel, application/x-msexcel, application/octet-stream")
)

## Start server and go to web page

shell('docker pull selenium/standalone-chrome')
shell('docker run -d -p 4445:4444 selenium/standalone-chrome')

remDr <- remoteDriver(remoteServerAddr = 'localhost', 
                      port = 4445L, 
                      #browser = "firefox", 
                      #extraCapabilities = custom_firefox
                      browser = "chrome", 
                      extraCapabilities = custom_chrome
)

remDr$open()
remDr$navigate('https://sit.trabalho.gov.br/radar/')

# check whether we are in the right place
remDr$getTitle()
# [[1]]
# [1] "SIT Abas"

## take screenshot

#' at any point in time can take a screenshot to see where we are
remDr$screenshot(display = T)

# Click on FGST tab
# ~~~~~~~~~~~~~~~~~~~~~~~
fgst <- remDr$findElement(using = 'xpath', "//*[@id='fgts-tab']")
class(fgst)
fgst$clickElement()


# Selecione o Ano:
# ~~~~~~~~~~~~~~~~~~~~~~~
#' if i am not mistaken we can keep the default "Todos os Anos"


# Selecione a Competencia:
# ~~~~~~~~~~~~~~~~~~~~~~~
#' if i am not mistaken we can keep the default "Todas as Competência"


# Selecione o Municipio: 
# ~~~~~~~~~~~~~~~~~~~~~~~

#' We will have to loop through all of the names, therefore need the names and the value
#' We do this by reading the html source with the package XML2 and then by using Xpaths

doc <- xml2::read_html(remDr$getPageSource()[[1]])

muni_list <- data.frame( "municipio" = xml_find_all(doc, "//*[@id='combo2_te']/option") %>% xml_text(),
                         "municipio_value" = xml_find_all(doc, "//*[@id='combo2_te']/option") %>% xml_attr(., "value"),
                         stringsAsFactors = F)

for(i in muni_list$municipio_value){

  # select the municipio
  xpath_muni <- paste0("//*[@id='combo2_te']/option[@value = '", i, "']" )
  muni <- remDr$findElement(using = 'xpath', xpath_muni)
  class(muni)
  muni$clickElement()
  Sys.sleep(15)

  #' CNAE
  #' This drop down is conditional on the selection of the previous dropdown, therefore need to get 
  #' the set of possible options
  #' here the values are strings, not numbers

  doc_CNAE <- xml2::read_html(remDr$getPageSource()[[1]])
  tmp_CNAE <- data.frame( "cnae" = xml_find_all(doc_CNAE, "//*[@id='combo2_fgts']/option") %>% xml_attr(., "value"),
                          "municipio_value" = i,
                           stringsAsFactors = F)

  for(j in tmp_CNAE$cnae){
    # debug: j <- tmp_CNAE$cnae[2]

    # First we select the option
    xpath <- paste0("//*[@id='combo2_fgts']/option[@value = '", j, "']")
    cnae <- remDr$findElement(using = 'xpath', xpath)
    class(cnae)
    cnae$clickElement()
    Sys.sleep(15)
    #' Download the data:

    xpath_csv <- "//*[@id='chartdiv_fgts']/div/div[3]/ul/li/ul/li[2]/ul/li[1]/a/span"
    csv <- remDr$findElement(using = 'xpath', xpath_csv)
    csv$clickElement()
    Sys.sleep(15)
  }
}

Пока что у нас есть код, работающий до такой степени, что он может циклически проходить через каждую комбинацию город и сектор, но rselenium не может щелкнуть и загрузить файл csv, прежде чем перейти к следующей комбинации города и сектора. Мы видим, что процесс циклически перебирает комбинации городов и секторов, потому что если мы остановим процесс в RStudio, город и сектор в кадре среды изменятся в зависимости от того, когда мы остановим процесс. Одним из возможных решений, о котором мы думали, было то, что нам просто нужно было убедиться, что опция автоматического сохранения загруженных файлов в указанный каталог c была отмечена в параметрах firefox. Но после этого шага мы все еще не можем загрузить CSV. Мы также попробовали этот подход, используя Chrome, но столкнулись с той же проблемой. Мы не получаем никаких сообщений об ошибках в R, поэтому мы не знаем, каким может быть следующий лучший шаг или лучшее решение. Кто-нибудь может помочь нам с этой проблемой?

...