我正在撰写对rNOMADS package的更新,以便将所有模型都包含在NOMADS网站上。为此,我必须在每个模型的html目录树中搜索。我不知道这棵树有多深,或者它含有多少分枝。因此,我正在编写一个简单的Web爬虫,以递归方式搜索首页的链接,跟踪每个链接,并返回没有链接的页面的URL。这样的页面是模型数据的下载页面。必须搜索的网址Here is an example。
我想获取此页下方所有网页的地址。 我试过这段代码:
library(XML)
url <- "http://nomads.ncep.noaa.gov/cgi-bin/filter_cmcens.pl"
WebCrawler <- function(url) {
doc <- htmlParse(url)
links <- xpathSApply(doc, "//a/@href")
free(doc)
if(is.null(links)) { #If there are no links, this is the page we want, return it!
return(url)
} else {
for(link in links) { #Call recursively on each link found
print(link)
return(WebCrawler(link))
}
}
}
但是,我还没有想出一个返回所有“死胡同”页面列表的好方法。 相反,此代码只返回一个模型页面,而不是它们的整个列表。 我可以声明一个全局变量并将URL保存到该变量,但我想知道是否有更好的方法来解决这个问题。我该如何构建这个函数来给我一个每一页的列表?
答案 0 :(得分:1)
你的错误在递归中:
## THIS IS INCORRECT
for(link in links) { #Call recursively on each link found
print(link)
return(WebCrawler(link)) <~~~ Specifically this line
}
这里没有递归属性,你只是在一个分支深处挖掘。
*
/ \
\
\
\
\
*
您不希望返回 WebCrawler(link)
的值。
而是希望捕获该值,然后返回值集合。
ret <- vector("list", length=length(links))
for(link in links) { #Call recursively on each link found
print(link)
ret[[link]] <- WebCrawler(link) <~~~ Specifically this line
}
return(ret) # or return(unlist(ret))
可能值得考虑您期望的最终输出?您将获得一个深层嵌套列表。如果你只想要终端节点,你可以unlist(.. recursive=TRUE, use.names=FALSE)
或者甚至可以在你进行时取消列出,但这可能会减慢你的速度。可能值得对它进行基准测试。