Добавление внешних зависимостей - это хорошо, но на самом деле это должно быть последнее средство (IMO).
Если вы не знакомы с представлением «Инструменты разработчика» в браузерах, пожалуйста, поинтересуйтесь этим перед тем, как приступить к ответу.Перед тем, как перейти на страницу поиска, вам нужно запустить его в новом сеансе браузера, чтобы действительно увидеть поток.
GET
не работал, потому что это HTML-форма и <form>
элементы используют POST
запросы (которые отображаются как XHR
запросов в большинстве панелей инструментов разработчика Network
).Тем не менее, это плохо созданный сайт, который слишком сложен для собственной пользы ( почти хуже, чем сайт Microsoft SharePoint), и существует некоторая начальная настройка состояния, когда вы переходите на начальную страницу поиска и поддерживаетсяво всем остальном потоке.
Я использовал curlconverter
для сортировки запросов POST
XHR
.Для этого TLDR щелкните правой кнопкой мыши на любом запросе POST
XHR
, найдите пункт меню «Копировать как cURL» и выберите его.Затем, оставив это в буфере обмена, следуйте инструкциям на README и страницах справочника curlconverter, чтобы вернуть действительные функции httr
.Я не могу обещать, что проведу вас через эту часть или отвечу на curlconverter
вопросы здесь.
В любом случае, чтобы получить httr
/ curl
, чтобы сохранить некоторые файлы cookie для вас и чтобы получить ключевую переменную сеанса, вам нужно будет передавать каждый вызов, который мы должны начать с нового сеанса R, и «прокачать» процесс очистки с помощью GET
для основного URL-адреса поиска:
library(stringi) # Iprefer this for extracting matched strings
library(rvest)
library(httr)
primer <- httr::GET("https://jurispub.admin.ch/publiws/pub/search.jsf")
Теперь нам нужно извлечь строку сеанса в javascript на этой странице:
httr::content(primer, as="text") %>%
stri_match_first_regex("session: '([[:alnum:]]+)'") %>%
.[,2] -> ice_session
Теперь мы притворяемся, что отправляем форму.Все эти скрытые переменные могут не понадобиться, но это то, что отправил браузер.Я обычно стараюсь сводить их к тому, что нужно, но это ваш проект, поэтому получайте удовольствие, если хотите:
httr::POST(
url = "https://jurispub.admin.ch/publiws/block/send-receive-updates",
body = list(
`$ice.submit.partial` = "true",
ice.event.target = "form:_id64",
ice.event.captured = "form:_id63first",
ice.event.type = "onclick",
ice.event.alt = "false",
ice.event.ctrl = "false",
ice.event.shift = "false",
ice.event.meta = "false",
ice.event.x = "51",
ice.event.y = "336",
ice.event.left = "true",
ice.event.right = "false",
form = "form",
icefacesCssUpdates = "",
`form:_id63` = "first",
`form:_idcl` = "form:_id63first",
ice.session = ice_session,
ice.view = "1",
ice.focus = "form:_id63first",
rand = "0.38654987905551663\\n\\n"
),
encode = "form"
) -> first_pg
Теперь, когда у нас есть первая страница, нам нужны данные с нее.Я не собираюсь решать это полностью, но вы должны быть в состоянии экстраполировать из того, что ниже.Запрос POST
возвращает XML, который javascript на странице превращает в ужасно выглядящую таблицу.Мы собираемся извлечь эту таблицу:
httr::content(first_pg) %>%
xml_find_first("//updates/update/content") %>%
xml_text() %>%
read_html() -> pg_tbl
data_tbl <- html_node(pg_tbl, xpath=".//table[contains(., 'Dossiernummer')]")
Однако, это ужасное использование HTML (у программистов не было УДАЛЕНО подсказки, как правильно делать веб-вещи), и вы не можете просто использовать html_table()
на нем (и вы бы не захотели в любом случае, так как вы, вероятно, хотите ссылки на PDF-файлы или что-то нет).Итак, мы можем извлекать столбцы по желанию:
html_nodes(data_tbl, xpath=".//td[1]/a") %>%
html_text()
## [1] "A-3930/2013" "D-7885/2009" "E-5869/2012" "C-651/2011" "F-2439/2017" "D-7416/2009"
## [7] "D-838/2011" "C-859/2011" "E-1927/2017" "E-2606/2011"
html_nodes(data_tbl, xpath=".//td[2]/a") %>%
html_attr("href")
## [1] "/publiws/download?decisionId=0002b1f8-ea53-40bb-8e38-402d9f3fdfa9"
## [2] "/publiws/download?decisionId=0002da8f-306e-4395-8eed-0b168df8634b"
## [3] "/publiws/download?decisionId=0003ec45-50be-45b2-8a56-5c0d866c2603"
## [4] "/publiws/download?decisionId=000508c2-c852-4aef-bc32-3385ddbbe88a"
## [5] "/publiws/download?decisionId=0006fbb9-228a-4bdc-ac8c-52db67df3b34"
## [6] "/publiws/download?decisionId=0008a971-6795-434d-90d4-7aeb1961606b"
## [7] "/publiws/download?decisionId=00099619-519c-4c8f-9cea-a16ed9ab9fd8"
## [8] "/publiws/download?decisionId=0009ac38-f2b0-4733-b379-05682473b5d9"
## [9] "/publiws/download?decisionId=000a4e0f-b2a2-483b-a49f-6ad12f4b7849"
## [10] "/publiws/download?decisionId=000be307-37b1-4d46-b651-223ceec9e533"
Мыть, полоскать, повторять для любых других столбцов, но вам может потребоваться проделать некоторую работу, чтобы получить их так же хорошо, и это упражнение осталось для вас (т.е. я не буду отвечать на вопросы о нем).
И вы захотите узнать, где вы находитесь в процессе очистки, поэтому нам нужно взять эту строку в нижней части таблицы:
html_node(pg_tbl, xpath=".//span[contains(@class, 'iceOutFrmt')]") %>%
html_text()
## [1] "57,294 Entscheide gefunden, zeige 1 bis 10. Seite 1 von 5,730. Resultat sortiert nach: Relevanz"
Синтаксис этого в # результата и на той странице, на которой вы находитесь, является упражнением, оставленным читателю.
Теперь нам нужно программно нажать «Следующая страница», пока не закончим.Я собираюсь сделать две ручные итерации, чтобы доказать, что это работает, чтобы попытаться предотвратить комментарии «это не работает».Вы должны написать итератор или цикл, чтобы пройти по всем следующим страницам и сохранить данные так, как вы хотите.
Следующая страница (первая итерация):
httr::POST(
url = "https://jurispub.admin.ch/publiws/block/send-receive-updates",
body = list(
`$ice.submit.partial` = "true",
ice.event.target = "form:_id67",
ice.event.captured = "form:_id63next",
ice.event.type = "onclick",
ice.event.alt = "false",
ice.event.ctrl = "false",
ice.event.shift = "false",
ice.event.meta = "false",
ice.event.x = "330",
ice.event.y = "559",
ice.event.left = "true",
ice.event.right = "false",
form = "",
icefacesCssUpdates = "",
`form:_id63` = "next",
`form:_idcl` = "form:_id63next",
iceTooltipInfo = "tooltip_id=form:resultTable:7:tt_ps; tooltip_src_id=form:resultTable:7:_id57; tooltip_state=hide; tooltip_x=846; tooltip_y=433; cntxValue=",
ice.session = ice_session,
ice.view = "1",
ice.focus = "form:_id63next",
rand = "0.17641832791084566\\n\\n"
),
encode = "form"
) -> next_pg
httr::content(next_pg) %>%
xml_find_first("//updates/update/content") %>%
xml_text() %>%
read_html() -> pg_tbl
data_tbl <- html_node(pg_tbl, xpath=".//table[contains(., 'Dossiernummer')]")
html_nodes(data_tbl, xpath=".//td[1]/a") %>%
html_text()
## [1] "D-4059/2011" "D-4389/2006" "E-4019/2006" "D-4291/2008" "E-5642/2012" "E-7752/2010"
## [7] "D-7010/2014" "D-1551/2013" "C-7715/2010" "E-3187/2013"
html_nodes(data_tbl, xpath=".//td[2]/a") %>%
html_attr("href")
## [1] "/publiws/download?decisionId=000bfd02-4da5-4bb2-a5d0-e9977bf8e464"
## [2] "/publiws/download?decisionId=000e2be1-6da8-47ff-b707-4a3537320a82"
## [3] "/publiws/download?decisionId=000fa961-ecb4-47d2-8ca3-72e8824c2c6b"
## [4] "/publiws/download?decisionId=0010a089-4f19-433e-b106-6d75833fae9a"
## [5] "/publiws/download?decisionId=00111bfc-3522-4a32-9e7a-fa2d9f171427"
## [6] "/publiws/download?decisionId=00126b65-b345-4988-826b-b213080caa45"
## [7] "/publiws/download?decisionId=00127944-5c88-43f6-9ef1-3c822288b0c7"
## [8] "/publiws/download?decisionId=00135a17-f1eb-4b61-9171-ac1d27fd3910"
## [9] "/publiws/download?decisionId=0014c6ea-c229-4129-bbe0-7411d34d9743"
## [10] "/publiws/download?decisionId=00167998-54d2-40a5-b02b-0c4546ac4760"
html_node(pg_tbl, xpath=".//span[contains(@class, 'iceOutFrmt')]") %>%
html_text()
## [1] "57,294 Entscheide gefunden, zeige 11 bis 20. Seite 2 von 5,730. Resultat sortiert nach: Relevanz"
Обратите внимание, что значения столбцов различны иТекст прогресса отличается.Также обратите внимание, что нам повезло, и у некомпетентных программистов на сайте действительно было «следующее» событие против нас, заставляющих нас выяснить числа нумерации страниц и координаты X / Y.
Следующая страница (второй и последний пример итерации):
httr::POST(
url = "https://jurispub.admin.ch/publiws/block/send-receive-updates",
body = list(
`$ice.submit.partial` = "true",
ice.event.target = "form:_id67",
ice.event.captured = "form:_id63next",
ice.event.type = "onclick",
ice.event.alt = "false",
ice.event.ctrl = "false",
ice.event.shift = "false",
ice.event.meta = "false",
ice.event.x = "330",
ice.event.y = "559",
ice.event.left = "true",
ice.event.right = "false",
form = "",
icefacesCssUpdates = "",
`form:_id63` = "next",
`form:_idcl` = "form:_id63next",
iceTooltipInfo = "tooltip_id=form:resultTable:7:tt_ps; tooltip_src_id=form:resultTable:7:_id57; tooltip_state=hide; tooltip_x=846; tooltip_y=433; cntxValue=",
ice.session = ice_session,
ice.view = "1",
ice.focus = "form:_id63next",
rand = "0.17641832791084566\\n\\n"
),
encode = "form"
) -> next_pg
httr::content(next_pg) %>%
xml_find_first("//updates/update/content") %>%
xml_text() %>%
read_html() -> pg_tbl
data_tbl <- html_node(pg_tbl, xpath=".//table[contains(., 'Dossiernummer')]")
html_nodes(data_tbl, xpath=".//td[1]/a") %>%
html_text()
## [1] "D-3974/2010" "D-5847/2009" "D-4241/2015" "E-3043/2010" "D-602/2016" "C-2065/2008"
## [7] "D-2753/2007" "E-2446/2010" "C-1124/2015" "B-7400/2006"
html_nodes(data_tbl, xpath=".//td[2]/a") %>%
html_attr("href")
## [1] "/publiws/download?decisionId=00173ef1-2900-49d4-b7d3-39246e552a70"
## [2] "/publiws/download?decisionId=001a344c-86b7-4f32-97f7-94d30669a583"
## [3] "/publiws/download?decisionId=001ae810-300d-4291-8fd0-35de720a6678"
## [4] "/publiws/download?decisionId=001c2025-57dd-4bc6-8bd6-eedbd719a6e3"
## [5] "/publiws/download?decisionId=001c44ba-e605-455d-9609-ed7dffb17adc"
## [6] "/publiws/download?decisionId=001c6040-4b81-4137-a6ee-bad5a5019e71"
## [7] "/publiws/download?decisionId=001d0811-a5c2-4856-aef3-51a44f7f2b0e"
## [8] "/publiws/download?decisionId=001dbf61-b1b8-468d-936e-30b174a8bec9"
## [9] "/publiws/download?decisionId=001ea85a-0765-4a1f-9b81-3cecb9f36b31"
## [10] "/publiws/download?decisionId=001f2e34-9718-4ef7-a60c-e6bbe208003b"
html_node(pg_tbl, xpath=".//span[contains(@class, 'iceOutFrmt')]") %>%
html_text()
## [1] "57,294 Entscheide gefunden, zeige 21 bis 30. Seite 3 von 5,730. Resultat sortiert nach: Relevanz"
В идеале вы должны заключить POST
в функцию, которую вы можете вызвать, и вернуть кадры данных, которые вы можете rbind
или bind_rows
, в большой кадр данных.
Если вы сделали это далеко, альтернативой является использование RSelenium для организации щелчков по страницам в селекторе «следующая страница» и получения HTML-кода назад (таблица все равно будет ужасна, и вам нужно будет использовать таргетинг на столбцы илинекоторая другая магия выбора HTML, чтобы получить полезную информацию из-за вышеупомянутых неумелых программистов).RSelenium вводит внешнюю зависимость, которая - как вы увидите, если будете выполнять поиск по SO - многим пользователям R трудно работать, особенно в такой же унылой унаследованной операционной системе, как Windows.Если вы можете запустить Selenium и RSelenium работать с ним, в долгосрочной перспективе может быть проще, если все вышеперечисленное кажется пугающим (в какой-то момент вам все равно придется прогуливать Developer Tools, так что вышеописанное может стоить боли в любом случае)и вам понадобится целевой объект HTML-селектора для различных кнопок для Selenium).
Я бы серьезно избегал фантомов, поскольку теперь он находится в состоянии «наилучшего усилия», и вам придется выяснить, каксделать вышеупомянутое с JavaScript против R.