是这样的-为了业务需求,产品要求在某页加上天气信息,且根据日落日出时间来提醒行程时间在日落后的人打开车灯。由于业务都在国外,像国家气象中心就凉了,产品极力推荐使用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不可用,也不知道这两个能做到什么时候-