JAVA查询天气预报

来源:互联网 发布:销售软件零税率 编辑:程序博客网 时间:2024/05/16 15:29

网上关于查询天气预报的资料有很多,我在这里就算总结一下吧。

主要有几种方法:

1.webservice请求

2.解析网页,获取天气信息

中央气象台抛出API接口:

http://www.weather.com.cn/data/sk/101010100.html 
http://www.weather.com.cn/data/cityinfo/101010100.html 
http://m.weather.com.cn/data/101010100.html  

我的需求是根据经纬度查询城市信息,根据城市信息获取实时天气状况。

经纬度的格式是HH°mm′ss.sss″,我是通过百度的geocoder来获取城市信息的,这里需要经经纬度装换为小数格式

/** * 经纬度的格式为HH°mm′ss.sss″,转换为小数形式 * @param value * @return */public static double parseHMStoNum(String value){String h = value.substring(0,value.indexOf("°"));String m = value.substring(value.indexOf("°")+1,value.indexOf("′"));String s = value.substring(value.indexOf("′")+1,value.indexOf("″"));double result = Integer.parseInt(h)+(Double.parseDouble(s)/60 + Integer.parseInt(m))/60;return result;}

通过转换后的经纬度信息通过百度GEOCODER API获取城市信息,定义接收POJO

/** * Copyright (c) 2014, alax * All Rights Reserved. */package chaptertwo.weather.pojo;/** * * @author    alax_app@yeah.net * @Date  2014-3-27 下午12:44:42 * */public class GeocoderSearchResponse {private String status;private GeocoderResult geocoderResult;public String getStatus() {return status;}public void setStatus(String status) {this.status = status;}public GeocoderResult getGeocoderResult() {return geocoderResult;}public void setGeocoderResult(GeocoderResult geocoderResult) {this.geocoderResult = geocoderResult;}}

/** * Copyright (c) 2014, alax * All Rights Reserved. */package chaptertwo.weather.pojo;/** * * @author    alax_app@yeah.net * @Date  2014-3-27 下午12:37:22 * */public class GeocoderResult {private Location location;private String formatted_address;private String business;private AddressComponent addressComponent;private String cityCode;public Location getLocation() {return location;}public void setLocation(Location location) {this.location = location;}public String getFormatted_address() {return formatted_address;}public void setFormatted_address(String formatted_address) {this.formatted_address = formatted_address;}public String getBusiness() {return business;}public void setBusiness(String business) {this.business = business;}public AddressComponent getAddressComponent() {return addressComponent;}public void setAddressComponent(AddressComponent addressComponent) {this.addressComponent = addressComponent;}public String getCityCode() {return cityCode;}public void setCityCode(String cityCode) {this.cityCode = cityCode;}}

/** * Copyright (c) 2014, alax * All Rights Reserved. */package chaptertwo.weather.pojo;/** * * @author    alax_app@yeah.net * @Date  2014-3-27 下午12:40:05 * */public class AddressComponent {private String streetNumber;private String street;private String district;private String city;private String province;public AddressComponent(){}public AddressComponent(String streetNumber, String street,String district, String city, String province) {super();this.streetNumber = streetNumber;this.street = street;this.district = district;this.city = city;this.province = province;}public String getStreetNumber() {return streetNumber;}public void setStreetNumber(String streetNumber) {this.streetNumber = streetNumber;}public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}public String getDistrict() {return district;}public void setDistrict(String district) {this.district = district;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}}

/** * Copyright (c) 2014, alax * All Rights Reserved. */package chaptertwo.weather.pojo;/** * * @author    alax_app@yeah.net * @Date  2014-3-27 下午12:39:20 * */public class Location {private String lat;private String lng;public Location() {super();}public Location(String lat, String lng) {super();this.lat = lat;this.lng = lng;}public String getLat() {return lat;}public void setLat(String lat) {this.lat = lat;}public String getLng() {return lng;}public void setLng(String lng) {this.lng = lng;}}

请求百度接口

public static GeocoderSearchResponse getSearchResponse(String lat,String lng){String key ="改为你申请的key";String url = "http://api.map.baidu.com/geocoder?location="+lat+","+lng+"&output=xml&key="+key;CloseableHttpClient httpClient = HttpClients.createDefault();HttpGet httpGet = new HttpGet(url);try {//执行get请求HttpResponse response = httpClient.execute(httpGet);//获取响应实体HttpEntity entity = response.getEntity();    String content = EntityUtils.toString(entity);    System.out.println(content);    GeocoderSearchResponse searchResponse = parseXmlResponse(content);    return searchResponse;    } catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}/** * 解析百度GEO API 返回结果 * @param content * @return */public static GeocoderSearchResponse parseXmlResponse(String content){if(!StringUtils.hasText(content)){return null;}try {Document document = DocumentHelper.parseText(content);Element root = document.getRootElement();String status = "";String lng = "";String lat = "";String formatted_address = "";String business = "";String streetNumber = "";String street = "";String district = "";String city = "";String province = "";String cityCode = "";status = root.elementText("status");//获取地理位置 经纬度Element result = root.element("result");if(result != null){Element location = result.element("location");if(location != null){lng = location.elementText("lng");lat = location.elementText("lat");}formatted_address = result.elementText("formatted_address");business = result.elementText("business");Element addressComponent = result.element("addressComponent");if(addressComponent != null){streetNumber = addressComponent.elementText("streetNumber");street = addressComponent.elementText("street");district = addressComponent.elementText("district");city = addressComponent.elementText("city");province = addressComponent.elementText("province");}cityCode = result.elementText("cityCode");}GeocoderSearchResponse searchResponse = new GeocoderSearchResponse();searchResponse.setStatus(status);GeocoderResult geocoderResult = new GeocoderResult();//locationLocation loc = new Location(lat, lng);geocoderResult.setLocation(loc);//addressComponentAddressComponent component = new AddressComponent(streetNumber, street, district, city, province);geocoderResult.setCityCode(cityCode);geocoderResult.setAddressComponent(component);geocoderResult.setBusiness(business);geocoderResult.setFormatted_address(formatted_address);searchResponse.setGeocoderResult(geocoderResult);return searchResponse;} catch (DocumentException e) {e.printStackTrace();}return null;}

百度接口返回的xml格式如下图所示

接下来请求气象台接口获取实时天气状况

接收天气信息pojo

/** * Copyright (c) 2014, alax * All Rights Reserved. */package chaptertwo.weather.pojo;/** * * @author    alax_app@yeah.net * @Date  2014-3-28 上午10:28:43 * */public class Weatherinfo {private String city;//城市名称private String cityid;//城市编码private String temp;//温度private String WD;//风向private String WS;//风速private String SD;//湿度private String WSE;//降雨private String time;//检测时间private String isRadar;//是否有雷达图private String Radar;//雷达public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getCityid() {return cityid;}public void setCityid(String cityid) {this.cityid = cityid;}public String getTemp() {return temp;}public void setTemp(String temp) {this.temp = temp;}public String getWD() {return WD;}public void setWD(String wD) {WD = wD;}public String getWS() {return WS;}public void setWS(String wS) {WS = wS;}public String getSD() {return SD;}public void setSD(String sD) {SD = sD;}public String getWSE() {return WSE;}public void setWSE(String wSE) {WSE = wSE;}public String getTime() {return time;}public void setTime(String time) {this.time = time;}public String getIsRadar() {return isRadar;}public void setIsRadar(String isRadar) {this.isRadar = isRadar;}public String getRadar() {return Radar;}public void setRadar(String radar) {Radar = radar;}}

/** * Copyright (c) 2014, alax * All Rights Reserved. */package chaptertwo.weather.pojo;/** * * @author    alax_app@yeah.net * @Date  2014-3-28 上午10:35:30 * */public class WeatherinfoVo {private Weatherinfo weatherinfo;public Weatherinfo getWeatherinfo() {return weatherinfo;}public void setWeatherinfo(Weatherinfo weatherinfo) {this.weatherinfo = weatherinfo;}}

利用httpclient请求接口方法

public static WeatherinfoVo getWeather(String lat,String lng){GeocoderSearchResponse georeResponse = getSearchResponse(lat, lng);String cityName = "";if(georeResponse != null && georeResponse.getStatus().equals("OK")){cityName = georeResponse.getGeocoderResult().getAddressComponent().getCity();}String cityCode = getCityCode(cityName);//实时天气:http://www.weather.com.cn/data/sk/101220607.html //详细信息: http://m.weather.com.cn/data/101220607.html//http://www.weather.com.cn/data/cityinfo/101010100.htmlString url = "http://www.weather.com.cn/data/sk/"+cityCode+".html";CloseableHttpClient httpClient = HttpClients.createDefault();HttpGet httpGet = new HttpGet(url);try {//执行get请求HttpResponse response = httpClient.execute(httpGet);//获取响应实体HttpEntity entity = response.getEntity();    String content = EntityUtils.toString(entity);    if(StringUtils.hasText(content)){    WeatherinfoVo weatherinfoVo = JSON.parseObject(content,WeatherinfoVo.class);    return weatherinfoVo;    }            } catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}        public static String getCityCode(String cityName){    String cityCode = "101010100";    if(!StringUtils.hasText(cityName)){    return cityCode;    }    if(cityName.contains("市")){    cityName = cityName.substring(0,cityName.indexOf("市"));    }CommentedProperties properties = new CommentedProperties();    ClassLoader  loader  =  Thread.currentThread().getContextClassLoader();URL url = loader.getResource("citycode.properties");if(url == null){return cityCode;}try{FileInputStream fis = new FileInputStream(url.getPath());properties.load(fis,"utf-8");cityCode = properties.getProperty(cityName); //默认是北京市}catch(Exception e){e.printStackTrace();}return cityCode;    }

下面介绍解析html获取实时天气状况

通过查看气象台页面源码,发现实时天气状况是通过内部iframe加载的,url为

http://www.weather.gov.cn/publish/forecast/AAH/hefei_iframe.html

通过htmlunit请求url并解析html,提取天气信息




解析代码如下

public static HtmlPage getOntimeWeatherHtmlPage(String lat,String lng) throws Exception{GeocoderSearchResponse response = LatLngUtils.getSearchResponse(lat, lng);if(response != null && response.getStatus().equals("OK")){AddressComponent address = response.getGeocoderResult().getAddressComponent();String city = address.getCity();String province = address.getProvince();if(StringUtils.hasText(city)){if(city.contains("市")){city = city.substring(0,city.indexOf("市"));}city = HanyuToPinyin(city);if(province.contains("省")){province = province.substring(0,province.indexOf("省"));}province = getPinYinHeadChar(province);String url = "http://www.weather.gov.cn/publish/forecast/A"+province+"/"+city+"_iframe.html";System.out.println(url);WebClient webClient=new WebClient();webClient.getOptions().setCssEnabled(false);webClient.getOptions().setJavaScriptEnabled(false);HtmlPage page = webClient.getPage(url);return page;}}return null;}

//获取最新天气实况public static WeatherOnTime findOntimeWeather(HtmlPage htmlPage){ DomNodeList<DomElement> divs = htmlPage.getElementsByTagName("div"); DomElement target = null; for (DomElement domElement : divs) {if (domElement.getAttribute("class").equals("city_wind")) {target = domElement;break;} } DomNodeList<DomNode> childrens = target.getChildNodes(); DomNode domNode = childrens.get(1); childrens =  domNode.getChildNodes(); Map<String, String> map = new HashMap<String, String>(); int index = 0; for(int i = 1; i < childrens.size(); i+=3){ map.put(index+"", childrens.get(i).asText()); index++; } WeatherOnTime weatherOnTime = new WeatherOnTime( map.get("0"),map.get("1"),map.get("2"),map.get("3"), map.get("4"),map.get("5"),map.get("6")); return weatherOnTime;}

当然还可以解析页面获取逐6小时精细化预报。



本文采用的技术如下:

dom4j

apache httpclient

alibaba fastjson

htmlunit



注意:

中央气象台在凌晨的时候是没有逐6小时精细化预报,所以要做为空判断


CSDN下载地址:

http://download.csdn.net/detail/lovejiegirl/7115005




0 0
原创粉丝点击