ОК, тогда я собираюсь перейти на Selenium, так как он не обязательно требует Docker (хотя я использую пример с Docker :-) Я уверен, что я мог бы заставить Splash / splashr сделать то же самое,но это включает в себя загрузку файлов, и я думаю, что есть проблемы с этим и серверной частью Splash.Как автор splashr
, я не буду сталкиваться с проблемами GitHub, если использую Selenium и для этого примера; -)
В любом случае, вам следует установить RSelenium
.Я не могу предоставить поддержку для этого, но это хорошо документировано, и люди rOpenSci очень полезны.Я настоятельно рекомендую запустить Docker в вашей системе или заставить ваш отдел настроить сервер Selenium, который вы все можете использовать.
Для этого варианта использования есть пара ошибок:
- Некоторые имена элементов, которые нам нужны для инструмента, генерируются динамически, поэтому нам нужно обойти это
- Это включает в себя загрузку файла CSV, поэтому нам нужно сопоставить путь файловой системы в Docker, чтобы он загружался правильно
- Это очень медленный сайт, поэтому вам нужно вычислять время ожидания после каждого взаимодействия (я не собираюсь этого делать, поскольку вы можете работать в более медленной или быстрой сети, и скорость сети играет здесь важную роль, хотя и не так много))
Я бы посоветовал проработать виньетки для RSelenium, прежде чем пытаться описать ниже, чтобы понять, как это работает.По сути, вы кодируете взаимодействия страниц человека.
Вам нужно будет запустить Docker с сопоставленным каталогом.См. файл загрузки с Rselenium & docker toolbox для получения всей информации, но вот как я это сделал на своем MacOS Box:
docker run -d -v /Users/hrbrmstr/Downloads://home/seluser/Downloads -p 4445:4444 selenium/standalone-firefox:2.53.1
, что делает Selenium доступным через порт 4445, использует Firefox (b/ c Chrome - зло) и отображает мой локальный каталог загрузок в каталог Firefox по умолчанию для пользователя selenium в контейнере Docker.Это означает, что well_authorizations_issued.csv
собирается туда (в конце концов).
Теперь нам нужно запустить R и подключить его к этому экземпляру Selenium.Нам нужно создать собственный профиль Firefox, так как мы сохраняем материал на диск и не хотим, чтобы браузер запрашивал у нас что-либо:
library(RSelenium)
makeFirefoxProfile(
list(
browser.download.dir = "home/seluser/Downloads",
browser.download.folderList = 2L,
browser.download.manager.showWhenStarting = FALSE,
browser.helperApps.neverAsk.saveToDisk = "text/csv"
)
) -> ffox_prof
remoteDriver(
browserName = "firefox", port = 4445L,
extraCapabilities = ffox_prof
) -> remDr
invisible(remDr$open())
remDr$navigate("https://reports.bcogc.ca/ogc/f?p=AMS_REPORTS:WA_ISSUED")
# Sys.sleep(###)
magick::image_read(openssl::base64_decode(remDr$screenshot()[[1]]))
Вам нужно раскомментировать Sys.sleep()
sи экспериментируйте с различными значениями времени ожидания между вызовами.Некоторые будут короткими (1-2 с), другие будут большими (20 с, 30 с или выше).
Я не отображаю вывод скриншотов здесь, но это один из способов выяснить время (т. Е. Продолжать генерировать скриншоты после взаимодействия элемента, пока не исчезнут серые прядильщики - и т. Д.) И вести мысленную заметкусколько секунд это было).
Теперь, один хитрый бит, отмеченный выше, определяет, где установлен флажок для отключения фильтра, поскольку он имеет динамический id
.Однако на самом деле мы не собираемся устанавливать флажок, потому что глупые дураки, создавшие это приложение, понятия не имеют, что они делают, и на самом деле событие click перехватывается элементом span
, который его окружает, поэтому мынеобходимо найти элемент li
, содержащий текст метки флажка, затем перейти к элементу span
и щелкнуть по нему.
box <- remDr$findElement(using = "xpath", value = "//li[contains(., 'Approval Date is in the last')]/span")
box$clickElement()
# Sys.sleep(###)
magick::image_read(openssl::base64_decode(remDr$screenshot()[[1]]))
^^ определенно нужна задержка (вы, вероятно, видели, как она нажимает на себя, когда вы нажимаете на себя, чтобы вы могли посчитать это и добавить несколько буферных секунд).
Затем,мы нажимаем на выпадающее «меню» (на самом деле это button
):
btn1 <- remDr$findElement(using = "css", "button#WA_ISSUED_actions_button")
btn1$clickElement()
# Sys.sleep(###)
magick::image_read(openssl::base64_decode(remDr$screenshot()[[1]]))
Затем загружаем пункт «меню» (на самом деле это button
:
btn2 <- remDr$findElement(using = "css", "button#WA_ISSUED_actions_menu_14i")
btn2$clickElement()
# Sys.sleep(###)
magick::image_read(openssl::base64_decode(remDr$screenshot()[[1]]))
^^ также нужна задержка, потому что «диалогу» загрузки требуется несколько секунд для запуска (по крайней мере, для меня).
Теперь найдите поле CSV, которое на самом деле a
tag:
lnk <- remDr$findElement(using = "css", "a#WA_ISSUED_download_CSV")
lnk$clickElement()
### WAIT A WHILE
magick::image_read(openssl::base64_decode(remDr$screenshot()[[1]]))
Этот последний бит - это то, с чем вам придется поэкспериментировать. Потребуется некоторое время , чтобы обработать запрос и затем передать файл ~ 9 МБ.rmDr$screenshot()
фактически ожидает завершения загрузки, так что вы можете удалить код отображения и декодирования и присвоить вывод переменной и использовать ее в качестве автоматического "ожидания".
Я пробовал это 3x на 2 разныхMacOS системы, и она работала нормально. YMMV.
Полагаю, что в конечном итоге вы захотите автоматизировать это, чтобы вы могли сделать system()
вызов в верхней части скрипта, который запускает контейнер Selenium Docker, затем выполняет оставшиеся биты и затем выдает другой system()
вызов, чтобы закрыть контейнер Docker.
В качестве альтернативы https://github.com/richfitz/stevedore теперь используется в CRAN, поэтому это чистый интерфейс R для запуска / остановки контейнеров Docker (среди многих других вещей), так что вы можете использовать его вместо вызовов system()
.
Если вы не можете использовать Docker, вам необходимо установить исполняемый файл «webdriver» для Firefox на вашем Windows-устройстве, а также получить архив Selenium Java, убедиться, что у вас установлена Java, а затем выполнить различные ручные заклинания, чтобы получитьэто происходит (что выходит за рамки этого ответа).
Вот сокращенная, непрерывная версия вышеупомянутого:
library(RSelenium)
# start Selenium before doing this
makeFirefoxProfile(
list(
browser.download.dir = "home/seluser/Downloads",
browser.download.folderList = 2L,
browser.download.manager.showWhenStarting = FALSE,
browser.helperApps.neverAsk.saveToDisk = "text/csv"
)
) -> ffox_prof
remoteDriver(
browserName = "firefox", port = 4445L,
extraCapabilities = ffox_prof
) -> remDr
invisible(remDr$open())
remDr$navigate("https://reports.bcogc.ca/ogc/f?p=AMS_REPORTS:WA_ISSUED")
# Sys.sleep(###)
box <- remDr$findElement(using = "xpath", value = "//li[contains(., 'Approval Date is in the last')]/span")
box$clickElement()
# Sys.sleep(###)
btn1 <- remDr$findElement(using = "css", "button#WA_ISSUED_actions_button")
btn1$clickElement()
# Sys.sleep(###)
btn2 <- remDr$findElement(using = "css", "button#WA_ISSUED_actions_menu_14i")
btn2$clickElement()
# Sys.sleep(###)
lnk <- remDr$findElement(using = "css", "a#WA_ISSUED_download_CSV")
lnk$clickElement()
### WAIT A WHILE
done <- remDr$screenshot()
# stop Selenium