G'day Everyone,
我有一个很长的地名列表(~15,000),我想用它来查找维基页面并从中提取数据。不幸的是,并非所有地方都有维基页面,当htmlParse()命中它们时,它会停止该函数并返回错误。
Error: failed to load HTTP resource
我无法通过并删除创建不存在的网址的每个地名,因此我想知道是否有办法让该功能跳过没有维基页的地方?
# Town names to be used
towns <- data.frame('recID' = c('G62', 'G63', 'G64', 'G65'),
'state' = c('Queensland', 'South_Australia', 'Victoria', 'Western_Australia'),
'name' = c('Balgal Beach', 'Balhannah', 'Ballan', 'Yunderup'),
'feature' = c('POPL', 'POPL', 'POPL', 'POPL'))
towns$state <- as.character(towns$state)
towns$name <- sub(' ', '_', as.character(towns$name))
# Function that extract data from wiki
wiki.tables <- function(towns) {
require(RJSONIO)
require(XML)
u <- paste('http://en.wikipedia.org/wiki/',
sep = '', towns[,1], ',_', towns[,2])
res <- lapply(u, function(x) htmlParse(x))
tabs <- lapply(sapply(res, getNodeSet, path = '//*[@class="infobox vcard"]')
, readHTMLTable)
return(tabs)
}
# Now to run the function. Yunderup will produce a URL that
# doesn't exist. So this will result in the error.
test <- wiki.tables(towns[,c('name', 'state')])
# It works if I don't include the place that produces a non-existent URL.
test <- wiki.tables(towns[1:3,c('name', 'state')])
有没有办法识别这些不存在的网址,并跳过或删除它们?
谢谢你的帮助!
干杯, 亚当
答案 0 :(得分:3)
You can use the 'url.exists' function from `RCurl`
require(RCurl)
u <- paste('http://en.wikipedia.org/wiki/',
sep = '', towns[,'name'], ',_', towns[,'state'])
> sapply(u, url.exists)
http://en.wikipedia.org/wiki/Balgal_Beach,_Queensland
TRUE
http://en.wikipedia.org/wiki/Balhannah,_South_Australia
TRUE
http://en.wikipedia.org/wiki/Ballan,_Victoria
TRUE
http://en.wikipedia.org/wiki/Yunderup,_Western_Australia
TRUE
答案 1 :(得分:2)
这是使用httr
包的另一个选项。 (顺便说一句:你不需要RJSONIO
)。将wiki.tables(...)
函数替换为:
wiki.tables <- function(towns) {
require(httr)
require(XML)
get.HTML<- function(url){
resp <- GET(url)
if (resp$status_code==200) return(htmlParse(content(resp,type="text")))
}
u <- paste('http://en.wikipedia.org/wiki/',
sep = '', towns[,1], ',_', towns[,2])
res <- lapply(u, get.HTML)
res <- res[sapply(res,function(x)!is.null(x))] # remove NULLs
tabs <- lapply(sapply(res, getNodeSet, path = '//*[@class="infobox vcard"]')
, readHTMLTable)
return(tabs)
}
这会运行一个GET请求并测试状态代码。 url.exists(...)
的缺点是你必须两次查询每个网址:一次查看是否存在,再次获取数据。
顺便说一句,当我尝试你的代码时,Yunderup url确实存在吗?