JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。易于阅读和编写,同时也易于机器解析和生成。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。目前有许多API服务提供了JSON的数据格式。
如果我们要在R语言中处理json数据,可以采用的扩展包有rjson和rjsonio两个包。从本人感觉来看,rjsonio包要更为友好一些,读取之后可以直接转为简单的list格式,方便调用数据。rjson的话也可以转为list,但其中层次关系复杂,不大方便处理。下面我们用一个例子来看看如何用RJSONIO包调用数据。我们希望编一个函数从wunderground的API调用本地城市的天气预报。其基本步骤如下:
- 若用户未输入城市名,则根据本机IP地址来返回当地天气;
- 若用户输入了城市名,则先用google API得到城市经纬度;
- 再用经纬度作查询参数,来返回该城市天气。
运行函数的结果看起来就象下面这样:
> getweather('wuhan') $城市 [1] "武漢市, Hubei" $当前 [1] "20°C 晴" $明天 [1] "27°C-18°C 可能有雨"
Google也有提供天气预报的API,但是数据不是很丰富。wunderground提供的数据则相当丰富,它的天气API也被数据源手册所推荐。该API也可以采用城市名称作为输入,但有时候不大灵光,所以转而用经纬度作输入参数。使用这个API还要注意一点,其免费账户的限制是每分钟10次调用,超出会有警告邮件发出来。
R代码如下:(RSS用户看不到代码,是因为代码存放在gist.github.com上,然后以js形式放在博客中,你可以点这里观看。另外如果要运行这个程度,需要将yourkey换成你自己申请的key,输入的城市名两边要加引号)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 加载所需扩展包 | |
library(RCurl) | |
library(RJSONIO) | |
library(XML) | |
# 建立一个根据网址提取天气预报的子函数 | |
fromurl<- function(finalurl) { | |
# 先读取网页,再解析JSON数据存在raw中 | |
web <- getURL(finalurl) | |
raw <-fromJSON(web) | |
high <- raw$forecast$simpleforecast$forecastday[[2]]$high['celsius'] | |
low <- raw$forecast$simpleforecast$forecastday[[2]]$low['celsius'] | |
condition <- raw$forecast$simpleforecast$forecastday[[2]]$conditions | |
currenttemp <- raw$current_observation$temp_c | |
currentweather <- raw$current_observation$weather | |
city <- as.character(raw$current_observation$display_location['full']) | |
result <-list(city=city,current=paste(currenttemp,'°C ',currentweather,sep=''), | |
tomorrow=paste(high,'°C','-',low,'°C ',condition,sep='')) | |
names(result) <-c('城市','当前', '明天') | |
return(result) | |
} | |
# 提取天气预报的主函数 | |
getweather <- function(city='') { | |
# 如果用户输入为空,则根据IP地址来查询 | |
if (city == '') { | |
finalurl <- 'http://api.wunderground.com/api/yourkey/conditions/ | |
forecast/lang:CN/q/autoip.json' | |
return(fromurl(finalurl)) | |
# 否则就调用google API,这时需要用XML包来解析数据得到经纬度 | |
} else { | |
requestUrl<-paste("http://maps.googleapis.com/maps/api/geocode/xml?address=" | |
,city,"&sensor=false", sep="") | |
xmlResult<-xmlTreeParse(requestUrl,isURL=TRUE) | |
root <- xmlRoot(xmlResult) | |
lat <-xmlValue(root[['result']][['geometry']][['location']][['lat']]) | |
lon <-xmlValue(root[['result']][['geometry']][['location']][['lng']]) | |
url <- 'http://api.wunderground.com/api/yourkey/conditions/forecast/lang:CN/q/' | |
# 将经纬度与其它信息相结合,形成查询地址 | |
finalurl <- paste(url,as.character(lat),',',as.character(lon),'.json',sep='') | |
return(fromurl(finalurl)) | |
} | |
} |
我有个问题 在不输入城市的时候,发现服务端没有正确返回,但是通过浏览器去请求的时候,发现是有数据返回的,我在想是不是因为RCurl 需要设置请求头等信息?
回复删除这个API有可能改过了,目前的程序不一定适用,不过对于这种简单的静态页面应该不需要设置请求头信息。
删除