在 R 中使用 Rvest 从网站中提取 <p> 和 <span> 元素时卡住了

Stuck while using Rvest in R to extract <p> and <span> elements from a website

我一直在使用 Rvest 尝试构建 NBA 仪表板,在 R 中进行一些网络抓取。在过去,我已经能够很容易地从 basketball-reference.com 中抓取时间表,因为它的网络结构设置为 HTML table。最近发现有一个NBA交易页面,名字叫
https://www.basketball-reference.com/leagues/NBA_2020_transactions.html,我想从中抓取数据并将其放在我的仪表板上。

下面是网页的图片,我需要的数据,以及它的页面结构。可以看到日期存储在 <.span> 对象中,并且在该特定日期发生的每个事件都有 <.p> 对象。我基本上只想将所有这些数据提取到 R 中的 2 个主要列中,将跨度数据转换为日期列,将 p 数据转换为事件列。

下面是我目前得到的一些代码,读取 url,将其转换为可读的 html,然后找到我需要的数据。我缺少几个步骤来获取我之前提到的格式的数据,但我不知道它们是什么。我可以通过使用 separate & gsub 手动操作数据的艰难方式来做到这一点,但这感觉是一个我希望避免的非常乏味的过程。

library(tidyverse)
library(rvest)
library(xml2)

url <- paste0('https://www.basketball-reference.com/leagues/NBA_2020_transactions.html')
webpage <- read_html(url)

# this returns a nested list of the data i want, but i dont know what to do from there
prac5 <- webpage %>% 
  html_nodes("div#content > ul > li")

# this returns a data frame of the data i want but it's all jumbled together 
prac6 <- webpage %>% 
  html_nodes("div#content > ul > li") %>%
  html_text() %>%
  as.data.frame()


昨天,我发现了一个代码片段,有人试图做类似的事情,他们使用了下面的方法,但我无法正确地调整它以适应我想要的。

bb <- html_nodes(webpage, "div#content > ul > li") %>% 
  map_df(~{
    data_frame(
      date = html_node(.x, "span") %>% html_text(trim=TRUE),
      event = html_nodes(.x, "ul > li") %>% html_text(trim=TRUE)
    )
  }) 

如果有人能提供任何帮助或见解,我将不胜感激!

如果像在 prac6 中那样删除所有 HTML 标签,事情会变得一团糟,所以您可以在这样做之前停下来:

prac6 <- webpage %>%
  html_nodes("div#content > ul > li")

然后将 <span><p> 内容解析到新的 dataframe/tibble 中的单独列中。由于每个日期可以包含多个事件,我们为每个日期创建一个新的 df,然后将它们连接在一起:

prac7 <- lapply(prac6, function(node) {
  tibble(date = html_node(node, "span") %>% html_text(trim=TRUE),
         event = html_nodes(node, "p") %>% html_text(trim=TRUE))
})

prac8 <- bind_rows(prac7)

这会产生:

# A tibble: 1,796 x 2
   date               event                                                         
   <chr>              <chr>                                                         
 1 November 11, 2020  The Oklahoma City Thunder hired Mark Daigneault as Head Coach.
 2 October 31, 2020   The Houston Rockets hired Stephen Silas as Head Coach.        
 3 October 22, 2020   The New Orleans Pelicans hired Stan Van Gundy as Head Coach.  
 4 October 20, 2020   The Indiana Pacers hired Nate Bjorkgren as Head Coach.        
 5 October 20, 2020   The Los Angeles Clippers hired Tyronn Lue as Head Coach.      
 6 October 15, 2020   Daryl Morey resigns as GM for Houston Rockets.                
 7 October 15, 2020   The Houston Rockets appointed Rafael Stone as GM.             
 8 October 3, 2020    The Philadelphia 76ers hired Doc Rivers as Head Coach.        
 9 September 28, 2020 The Los Angeles Clippers fired Doc Rivers as Head Coach.      
10 September 22, 2020 The Chicago Bulls hired Billy Donovan as Head Coach.          
# ... with 1,786 more rows
...    

你很接近,你需要html_nodes(.x, "p")

这是一个使用 lapply 而不是 map 的解决方案:

prac5 <- webpage %>% 
   html_nodes("div#content > ul > li")

dfs <- lapply(prac5, function(node) {
      date = html_node(node, "span") %>% html_text(trim=TRUE)
      event = html_nodes(node, "p") %>% html_text(trim=TRUE)
   data.frame(date, event)
})
answer <- bind_rows(dfs)