是这样的-为了业务需求,产品要求在某页加上天气信息,且根据日落日出时间来提醒行程时间在日落后的人打开车灯。由于业务都在国外,像国家气象中心就凉了,产品极力推荐使用Yahoo Weather。然后折腾了一整日大概摸清了Yahoo的Weather API。
Yahoo的公共接口实行YSQL的办法,让天气数据可像SQL一样查询。而目前还存活的表为 :geo.places 和weather.forecast。在这之前还有好多表,但出于一些不为人知的原因,雅虎停用了这些表和非常好用的YSQL Console。比如通过经纬度查询Woeid,就会出现需要Api_key的状况,而雅虎则是更新到Oath2.0验证,让你调用也要通过AK来走,而获取动态token的过程又是请求url的,又是拿码办事的,在实际开发直接拉天气(其实是我不会写Java SSL怎么处理)。在这种大环境下只能通过以下的办法来实现:
//获取woeid和Yahoo Location
//第一轮准确获取 所得数据基本正确
public YahooWeather getYahooCity(YahooWeather city){
YahooWeather Yahoocity = new YahooWeather();
String baseUrl = "https://query.yahooapis.com/v1/public/yql?q=select woeid,locality1,centroid from geo.places(1) where placetype= \"Town LocalAdmin Prefecture\" and text=\"";
String useUrl = baseUrl + city.getCityName() +" "+city.getCountryName()+"\"&format=json";
String woeid = null, loaction = null;
try {
String url = UriUtils.encodeQuery(useUrl, "UTF-8");
SimpleClientHttpRequestFactory cilentfactory = new SimpleClientHttpRequestFactory();
StringBuffer endCh = new StringBuffer();
URI uri = URI.create(url);
ClientHttpRequest req = cilentfactory.createRequest(uri, HttpMethod.GET);
ClientHttpResponse res = req.execute();
BufferedReader br = new BufferedReader(new InputStreamReader(res.getBody(),Charset.forName("UTF-8")));
String line = null;
while( (line = br.readLine()) != null){
endCh.append(line);
}
//解析JSON
JSONObject jsonObject = (JSONObject) JSON.parseObject(endCh.toString(),new TypeReference<Map<String,Object>>(){}).get("query");
JSONObject results = (JSONObject) JSON.parseObject(jsonObject.toJSONString(),new TypeReference<Map<String,Object>>(){}).get("results");
if(results!=null){
JSONObject place = (JSONObject) JSON.parseObject(results.toJSONString(),new TypeReference<Map<String,Object>>(){}).get("place");
JSONObject centroid = (JSONObject) JSON.parseObject(place.toJSONString(),new TypeReference<Map<String,Object>>(){}).get("centroid");
JSONObject locality1 = (JSONObject) JSON.parseObject(place.toJSONString(),new TypeReference<Map<String,Object>>(){}).get("locality1");
System.out.println(locality1);
if(locality1==null){
System.out.println("["+city.getCityName()+"--"+city.getCountryName()+"] 在雅虎不可查询,无结果返回");
woeid = "0";
}else{
woeid = (String) locality1.get("woeid");
loaction = centroid.get("latitude")+","+centroid.get("longitude");
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Yahoocity.setCityId(city.getCityId());
// Yahoocity.setCityName(city.getCityName());
// Yahoocity.setCountryName(city.getCountryName());
// Yahoocity.setCountryId(city.getCountryId());
Yahoocity.setLocation(loaction);
Yahoocity.setWoeid(Integer.parseInt(woeid));
return Yahoocity;
}
其中也没什么值得注意的地方,而其API因为查询是YSQL的形式出现,多了几个参数:比如placetype。placetype是返回的数据当中的一个key。他写作是placetypeName。而我们普通的城市一般是作为Town出现,当然地级市有Admin的形式,也有State这种,比如日本还有道,县。在上面我为了提高精确度稍微限制了一下,而请求的值也是城市名加国家的办法,除此之外也可以通过经纬度 就是以(api_key,lon,lat)的形式出现在Where语句当中,当前测试可用的网址还有:
https://query.yahooapis.com/v1/public/yql?q=select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="北京 中国") and u='c'&format=json
https://query.yahooapis.com/v1/public/yql?q=select * from weather.forecast where woeid=2488802 and u='c'&format=json
以上是通过地名直接获取天气和通过woeid获取天气,是最为常用的两种办法。而Yahoo官方本身所提供的API文档和开发者中心(用处不大)当中好多数据都已经废弃,而且部分URL不可用,也不知道这两个能做到什么时候-