这是我之前提出的问题(如何从 rvest 抓取的网站创建数据框架,保留数据的嵌套结构)和 @stefan 的 answer 的后续问题。这个答案非常适合这个问题。
但是如果有额外的嵌套层怎么办?
library(rvest)
library(dplyr, warn = FALSE)
books <- minimal_html('
<div class="entry">
<div class="collection">Collection 1</div>
<div class="book">
<div class="booktitle">Book 1</div>
<div class="year">1999</div>
<div class="author">
<div class="name">Author 1</div>
<div class="city">Austin</div>
</div>
<div class="author">
<div class="name">Author 2</div>
<div class="city">Dallas</div>
</div>
<div class="author">
<div class="name">Author 3</div>
<div class="city">Memphis</div>
</div>
</div>
<div class="book">
<div class="booktitle">Book 2</div>
<div class="year">2022</div>
<div class="author">
<div class="name">Author 4</div>
<div class="city">Houston</div>
</div>
</div>
</div>
<div class="entry">
<div class="collection">Collection 2</div>
<div class="book">
<div class="booktitle">Book 3</div>
<div class="year">1845</div>
<div class="author">
<div class="name">Author 5</div>
</div>
<div class="author">
<div class="name">Author 6</div>
<div class="city">Dayton</div>
</div>
<div class="author">
<div class="name">Author 7</div>
<div class="city">Philadelphia</div>
</div>
</div>
</div>')
和以前一样,我希望事情处于作者级别,但作者的姓名和城市应该在同一行。另外,还有一个额外的外层,
collection
。 entry
中书籍的所有作者都应该有 entry
的藏书号。因此应该有七行,并且 Author 7
应该具有以下值:Collection 2
、Book 3
、1845
、Author 7
和 Philadelphia
。
另请注意,每位作者只有一个(或没有)姓名和一个(或没有 - 作者 5 没有城市)城市。并且
entry
总是恰好有一个 collection
。
如何从之前的答案中扩展此代码以获得我想要的解决方案?
data0 <- books %>%
html_elements(".book") |>
lapply(\(x) {
tibble(
title = x |> html_element(".booktitle") |> html_text2(),
year = x |> html_element(".year") |> html_text2(),
authors = x |> html_elements(".author") |> html_text2(),
)
}) |>
bind_rows()
由于作者和城市之间有一个换行符,您可以尝试 tidyr 包中的单独功能。
library(tidyr)
tidyr::separate(data0, authors, into=c("authors", "city"), sep="\\n")
对于更复杂的情况,很可能需要几个循环或递归。