在XML
包中的?htmlParse
示例 部分中,有以下函数getLinks()
。
getLinks <- function() {
links <- character()
list(a = function(node, ...) {
links <<- c(links, xmlGetAttr(node, "href"))
node
},
links = function()links)
}
使用它之后,然后盯着它看了一会儿,我仍然无法绕过函数体内发生的事件序列。
> bod <- as.list(body(getLinks))
> c(bod, rapply(bod, as.list))
[[1]]
`{`
[[2]]
links <- character()
[[3]]
list(a = function(node, ...) {
links <<- c(links, xmlGetAttr(node, "href"))
node
}, links = function() links)
$a
function (node, ...)
{
links <<- c(links, xmlGetAttr(node, "href"))
node
}
<environment: 0x595f7f0>
$links
function ()
links
<environment: 0x595f7f0>
有人可以提供此功能中发生的事件链的详细说明吗?
对于示例,请运行以下代码:
> library(XML)
> URL <- "http://www.retrosheet.org/game.htm"
> h1 <- getLinks()
> htmlTreeParse(URL, handlers = h1)
> h1$links()
答案 0 :(得分:8)
就它自己来说,这个功能真的没什么用。它实际上只在htmlTreeParse
的上下文中有用。它做的是两件事。首先,它创建一个机箱/环境,其中将收集链接向量。其次,它返回一个列表,可以在handler=
中用作htmlTreeParse
。根据文档,处理程序是
用于将不同XML节点映射到R对象的可选函数集合。通常,这是一个命名的函数列表,闭包可用于提供本地数据。这提供了一种过滤树在R中创建,添加或删除节点的方法,并且通常在C代码中构造它们时对它们进行处理。
因此htmlTreeParse
将在列表中查找与HTML文件中元素的节点名称匹配的名称。因此,由于列表具有“a”元素,因此将为文档中的每个<a>
(链接)标记调用该函数。该函数只提取存储URL的href
属性,并将其添加到机箱中的links
数组中。
最后,解析完成后,您需要一种方法来访问闭包内的links
向量。因此该列表还定义了“链接”元素。这是一个只返回受保护矢量的函数。只要它与HTML文档中的标记名称不匹配,您就可以调用此函数。
所以这个getLinks()
函数只返回一个可以用作处理程序的列表。大多数实际工作都是在htmlTreeParse
函数中完成的。
答案 1 :(得分:2)
除了对Flick先生的出色解释之外,这里还简单演示了这个功能是如何工作的:
getLinks <- function() {
links <- character()
list(a = function(node, ...) {
links <<- c(links, node) ## I omit the call to XMLGetAttr
node
},
links = function()links)
}
h1 = getLinks()
现在我只是多次调用该函数,并在每次调用时打印结果链接:
for (i in 1:3 ){
print(h1$links())
h1$a(paste0("node",i))
}
如您所见,链接只是一个列表,在每次调用getlinks
时会被找到的新链接增加:
character(0)
[1] "node1"
[1] "node1" "node2"