rvest:Return 给定多个列表的空节点的 NA

rvest: Return NAs for empty nodes given multiple listings

我是 R 的新手(尤其是将其用于网络抓取),因此非常感谢您的帮助。我目前正在尝试挖掘一个包含多个门票列表的网页,并列出其中一些的其他详细信息(例如视野受损或仅供儿童使用的门票)。我想提取此数据,为不包含这些详细信息的票证列表留下空格或 NA。

由于原始网站需要使用 RSelenium,我尝试以更简单的形式复制 HTML。如果缺少任何信息,请告诉我,我会尽力提供。谢谢!

到目前为止,我已尝试采用此处提供的解决方案:rvest missing nodes --> NA and ,但无法为我的示例复制它们,因为我收到错误消息

Error in UseMethod("xml_find_all") : no applicable method for 'xml_find_all' applied to an object of class "character"

我想我确实需要 rvest 和 lapply 的组合,但我似乎无法让它工作。

library(XML)
library(rvest)

html <- '<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class = "listing" id = "listing_1">
<em> 
<span class="listing_sub3">
Limited view
</span>
</em>
</div>
<div class = "listing" id = "listing_2">
<em> 
<span class="listing_sub2">
Other text I am not interested in
</span>
</em>
</div>
<div class = "listing" id = "listing_3">
<div>
<em> 
<span class="listing_sub3">
Limited view
</span>
</em>
</div>
<div>
<span class="listing_sub1">
Ticket for a child
</span>
</div>
</div>
</body>
</html>'


page_html <- read_html(html)
child <- html_nodes(page_html, xpath ="//*[@class='listing_sub1']") %>%
  html_text()
viewLim <- html_nodes(page_html, xpath ="//*[@class='listing_sub3']") %>%
  html_text()
id <- html_nodes(page_html, xpath = "//*[@class='listing']") %>% 
  html_attr( ,name = "id") 

我希望得到一个看起来像这样的table:

listing  child   viewLim
1        F       T       
2        F       F      
3        T       T  

此解决方案中的策略是为每个列表节点创建一个节点列表,然后在每个节点中搜索所需的信息、子节点和视图限制。

使用 html_node 而不是 html_nodes 将始终 return 一个值(即使它只是 NA)这确保向量长度相同。

此外,对于 rvest,我更喜欢使用 CSS 语法而不是 xpath。在大多数情况下,CSS 比 xpath 表达式更易于使用。

library(rvest)

page_html <- read_html(html)
#find the listing nodes and id of each node
listings<-html_nodes(page_html, "div.listing")
listing<-html_attr(listings ,name = "id") 

#search each listing node for the child ticket and limit view criteria
child<-sapply(listings, function(x) {html_node(x, "span.listing_sub1") %>% html_text()} ) 
viewLim<-sapply(listings, function(x) {html_node(x, "span.listing_sub3") %>% html_text()}) 

#create dataframe
df<-data.frame(listing, child=!is.na(child), viewLim=!is.na(viewLim))

# df
#    listing child viewLim
#1 listing_1 FALSE    TRUE
#2 listing_2 FALSE   FALSE
#3 listing_3  TRUE    TRUE