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

时间:2019-02-01 11:03:02

标签: r web-scraping rvest

我对R相当陌生(尤其是用于Web抓取),因此非常感谢您的帮助。我目前正在尝试挖掘一个包含多个票证清单的网页,并列出其中一些的其他详细信息(例如,票证视野受损或仅用于儿童)。我想提取此数据,在不包含这些详细信息的故障单清单中保留空格或NA。

由于原始网站要求使用RSelenium,因此我尝试以一种更简单的形式复制HTML。如果缺少任何信息,请让我知道,我将尽力提供。谢谢!

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

  

UseMethod(“ xml_find_all”)中的错误:   没有将适用于“ xml_find_all”的适用方法应用于“字符”类的对象

我想我确实需要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") 

我希望获得一个与此表相似的表:

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

1 个答案:

答案 0 :(得分:1)

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

使用html_node而不是html_nodes将始终返回一个值(即使只是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