Атрибут rowspan
позволит сделать сделку с этой таблицей довольно интересной. У вас есть несколько вариантов, два из которых являются:
- использование
html_table()
на цели <table>
использование fill=TRUE
и выполнить операцию на результирующем кадре данных
- атаковать его на
<tr>
-й и строить кадр данных из земля
Этот ответ делает последний.
library(rvest)
library(purrr)
Во-первых, мы получаем содержимое в виде мы можем выполнить XML/HTML операцию на:
content(res, as = 'text', encoding = 'utf-8') %>%
read_html() -> pg
Далее мы ориентируемся и извлечь узел таблицы с отчетом:
tab <- html_nodes(pg, "table#report1")
Вот трюк бит. Мы первая цель всех <tr>
элементов, которые имеют @rowspan
атрибуты, но не <td>
элементов с @colspan
атрибутом:
html_nodes(tab, xpath=".//tr[td[not(@colspan) and @rowspan]]") %>%
Далее, мы не обработаем те invidivually:
map_df(function(x) {
Мы получаем # строк в <tr>
пролетах :
html_nodes(x, xpath=".//td[@rowspan]") %>%
html_attr("rowspan") %>%
as.numeric() -> row_ct
Найти все одноуровневые <tr>
элементы и уменьшить установить на оставшихся в этом <tr>
«блока»:
rows <- html_nodes(x, xpath=".//following-sibling::tr")
rows <- rows[1:(row_ct-1)]
сделать кадр данных от первого блока строки
html_nodes(x, xpath=".//td") %>%
html_text() %>%
setNames(sprintf("X%d", 1:13)) %>%
as.list() %>%
flatten_df() -> first
пройти через все отфильтрованные строки двойников и сделать то же самое, оставляя место для заполнения в составном колонке:
map_df(rows, ~html_nodes(., xpath=".//td") %>%
html_text() %>%
setNames(c("X1", "X2", sprintf("X%d", 4:13))) %>%
as.list()) %>%
mutate(X3=first$X3) %>%
select(X1, X2, X3, everything()) -> rest
bind_rows(first, rest)
}) -> h2o_df
dplyr::glimpse(h2o_df)
Я не могу вставить вывод, что поскольку SO это Javascript текстовый фильтр так мозг мертв он считает, что сообщение является спамом только б/с ней час как персонажи кандзи.
Вот весь код в непрерывный кусок:
tab <- html_nodes(pg, "table#report1")
html_nodes(tab, xpath=".//tr[td[not(@colspan) and @rowspan]]") %>%
map_df(function(x) {
html_nodes(x, xpath=".//td[@rowspan]") %>%
html_attr("rowspan") %>%
as.numeric() -> row_ct
rows <- html_nodes(x, xpath=".//following-sibling::tr")
rows <- rows[1:(row_ct-1)]
html_nodes(x, xpath=".//td") %>%
html_text() %>%
setNames(sprintf("X%d", 1:13)) %>%
as.list() %>%
flatten_df() -> first
map_df(rows, ~html_nodes(., xpath=".//td") %>%
html_text() %>%
setNames(c("X1", "X2", sprintf("X%d", 4:13))) %>%
as.list()) %>%
mutate(X3=first$X3) %>%
select(X1, X2, X3, everything()) -> rest
bind_rows(first, rest)
}) -> h2o_df
Спасибо за подробный ответ! Раньше я использовал 'html_table()', но обычно функция автоматически определяет таблицу, но почему в этот раз таблица, которую я получил через 'html_table()', настолько запутанна, и когда я пытаюсь записать ее в файл, она говорит о различном числе из строк .... не могли бы вы рассказать мне, как это решить? – ycx
нет простого выхода из этого соскабливания. сайт использует 'colspan' и' rowspan' во многих '
ОК, вижу, спасибо! Я просто попробую 2-й путь! – ycx
Смежные вопросы