6

我正在尝试使用 R 中 XML 包中的 xpathApply 函数从 html 文件中提取某些数据。但是,当我在 html 文档的某些父节点上使用 xpathApply 后,结果对象的类变为 XMLNodeSet,我无法在此类对象上进一步使用 xpathApply,因为出现此错误消息:“UseMethod("xpathApply") 中的错误:没有适用于“XMLNodeSet”类对象的“xpathApply”方法</p>

这是我试图复制我的问题的 R 脚本(这个例子只是一个简单的表,我知道我可以使用 readHTMLtable 函数,但我需要使用更底层的函数来工作,因为我的实际 html 比这个简单的更复杂桌子):

library(XML)
y <- htmlParse(htmlfile)
x <- xpathApply(y, "//table/tr")
z <- xpathApply(x, "/td")

这是“html文件”:

<table>
<tr>
<td> Test1.1 </td> <td> Test1.2 </td>
</tr>
<tr>
<td> Test1.3 </td> <td> Test1.4 </td>
</tr>
</table>

使用 xpathApply 后是否有任何方法可以在节点上进一步工作?或者还有其他好的选择来处理节点中的数据吗?

4

3 回答 3

2

尽管定义正确 xPath 的解决方案似乎更好,但您可以这样做:

library(XML)
y <- htmlParse(htmlfile)
x <- getNodeSet(y, "//table/tr")
z <- lapply(x, function(x){
                 subDoc <- xmlDoc(x)
                 r <- xpathApply(x, "/td")
                 free(subDoc) # not sure if necessary
                 return(r)
})
于 2015-02-18T14:12:26.310 回答
2

一旦你有了一个节点列表,你就可以在它上面应用函数来提取节点。函数如xmlValueor xmlGetAttr.... 例如:

x <- xpathApply(y, "//table/tr")
sapply(x,xmlValue)          ## it a list of nodes..
 " Test1.1  Test1.2 " " Test1.3  Test1.4 "

这相当于做:

xpathSApply(y,"//table/tr",xmlValue)
" Test1.1  Test1.2 " " Test1.3  Test1.4 "

编辑

我相信你的问题可以通过正确的 xpath 来解决。您应该像使用数据库一样学习使用 xml 文件。xpath 类似于 sql 查询。它速度很快,许多浏览器可以帮助您生成正确的 xpath。

例如 :

 xpathSApply(y,"//table/tr[2]/td[1]",xmlValue) #  second tr and first td
 [1] " Test1.3 "
 xpathSApply(y,"//table/tr[2]/td[3]",xmlValue) #  second tr and third td

编辑

如果他想复制 XML 结构,则 OP 看起来像(以相同的顺序获取 tr 和 td)

这是方法,我认为不是更有效的方法...

nn.trs <- length(xpathSApply(y,"//table/tr",I))
lapply(seq(nn.trs),function(i){
       xpathSApply(y,paste("//table/tr[",i,"]/td",sep=''),xmlValue)
})
[[1]]
[1] " Test1.1 " " Test1.2 "

[[2]]
[1] " Test1.3 " " Test1.4 "

如果每个 tr 中的 td 数都相同,则可以替换lapplysapply并得到:

    [,1]        [,2]       
[1,] " Test1.1 " " Test1.3 "
[2,] " Test1.2 " " Test1.4 "

但我认为在这种情况下 readHtmlTable 更好..

于 2013-02-19T13:08:31.100 回答
1

以下似乎工作。本质上,您必须搜索由返回的列表的元素xpathApply

> y <- htmlParse(htmlfile)
> x <- xpathApply(y, "//table/tr")
> x
[[1]]
<tr><td> Test1.1 </td> <td> Test1.2 </td>
</tr> 

[[2]]
<tr><td> Test1.3 </td> <td> Test1.4 </td>
</tr> 

attr(,"class")
[1] "XMLNodeSet"
> z <- xpathApply(x[[1]], "//td")
> z
[[1]]
<td> Test1.1 </td> 

[[2]]
<td> Test1.2 </td> 

[[3]]
<td> Test1.3 </td> 

[[4]]
<td> Test1.4 </td> 

attr(,"class")
[1] "XMLNodeSet"

PS:我不确定为什么它会搜索xlist 的所有元素而不仅仅是x[[1]]. 似乎是一个错误。

于 2013-02-19T13:14:30.543 回答