我正在尝试在R中的XML包中使用xpathApply函数从html文件中提取某些数据。 但是,在html文档的某些父节点上使用xpathApply后,生成的对象的类变为XMLNodeSet,我无法在此类对象上进一步使用xpathApply,因为出现此错误消息:“UseMethod(”xpathApply“)中的错误:没有适用于'xpathApply'的方法应用于类“XMLNodeSet”“
的对象这是我试图复制我的问题的R脚本(这个例子只是一个简单的表,我知道我可以使用readHTMLtable函数,但我需要使用更多的低级函数来工作,因为我的实际html更复杂比这个简单的表格):
library(XML)
y <- htmlParse(htmlfile)
x <- xpathApply(y, "//table/tr")
z <- xpathApply(x, "/td")
这是“htmlfile”:
<table>
<tr>
<td> Test1.1 </td> <td> Test1.2 </td>
</tr>
<tr>
<td> Test1.3 </td> <td> Test1.4 </td>
</tr>
</table>
使用xpathApply后,是否有任何方法可以在节点上进一步工作?或者还有其他好的选择来解决节点中的数据吗?
答案 0 :(得分:2)
获得节点列表后,可以在其上应用函数来提取节点。功能如xmlValue
或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结构(以相同的顺序获得tr和td),那么OP就好像是这是方式,我认为不是更有效的方式......
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的数量都相同,则可以将lapply
替换为sapply
,然后得到:
[,1] [,2]
[1,] " Test1.1 " " Test1.3 "
[2,] " Test1.2 " " Test1.4 "
但我认为在这种情况下readHtmlTable更好..
答案 1 :(得分: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)
})
答案 2 :(得分: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:我不确定为什么它会搜索x
列表的所有元素,而不仅仅是x[[1]]
。看起来像一个错误。