相当于刮刮?

时间:2017-01-17 23:11:08

标签: r rvest

我尝试运行一些抓取操作,我在节点上执行的操作取决于节点的内容。

这应该是一个最小的例子:

XML =
'<td class="id-tag">
    <span title="Really Long Text">Really L...</span>
</td>
<td class="id-tag">Short</td>'

page = read_html(XML)

基本上,如果html_attr(x, "title")存在,我想提取<span>,否则只需获取html_text(x)

首先执行的代码是:

page %>% html_nodes(xpath = '//td[@class="id-tag"]/span') %>% html_attr("title")
# [1] "Really Long Text"

第二个代码是:

page %>% html_nodes(xpath = '//td[@class="id-tag"]') %>% html_text
# [1] "\n    Really L...\n" "Short"  

真正的问题是,html_attr方法并没有为不匹配的节点提供任何NA或类似内容(即使我让{{1}首先要确保xpath首先要确保我只缩小到相关节点。这会破坏顺序 - 我无法自动判断原始结构是否有{{1}在第一个或第二个节点。

(我想过做一个连接,但是缩写文本和全文之间的映射不是一对一/可逆的。)

This似乎是在正确的道路上 - '//td[@class="id-tag"]'中的if / else结构 - 但不起作用。

理想情况下我会得到输出:

"Really Long Text"

2 个答案:

答案 0 :(得分:3)

基于R Conditional evaluation when using the pipe operator %>%,您可以执行类似

的操作
page %>% 
   html_nodes(xpath='//td[@class="id-tag"]') %>% 
   {ifelse(is.na(html_node(.,xpath="span")), 
           html_text(.),
           {html_node(.,xpath="span") %>% html_attr("title")}
   )}

我认为放弃管道并保存沿途创建的一些对象可能很简单

nodes <- html_nodes(page, xpath='//td[@class="id-tag"]')
text <- html_text(nodes)
title <- html_attr(html_node(nodes,xpath='span'),"title")
value <- ifelse(is.na(html_node(nodes, xpath="span")), text ,title)

仅xpath方法可能是

page %>% 
 html_nodes(xpath='//td[@class="id-tag"]/span/@title|//td[@class="id-tag"][not(.//span)]') %>%
 html_text()

答案 1 :(得分:2)

另一种方法:

library(tidyverse)
library(rvest)

XML <- '
<td class="id-tag">
    <span title="Really Long Text">Really L...</span>
</td>
<td class="id-tag">Short</td>
'

pg <- read_html(XML)

html_nodes(pg, "td[class='id-tag']") %>%
  map_chr(function(x) {
    if (xml_find_first(x, "boolean(.//span)")) {
      x <- html_nodes(x, xpath=".//span/@title")
    }
    html_text(x)
  })

## [1] "Really Long Text" "Short"