项目中需要查询天气,自己写了一段代码从中国天气网和MSN上查天气,中国天气网查中国天气,MSN查世界天气。
MSN用到的数据结构
1 /// <summary> 2 /// 根据城市名查询MSN天返回的城市编码信息类 3 /// </summary> 4 public class Location 5 { 6 //全名 例如 杭州,浙江,中国 7 public string FullName { get; set; } 8 9 //国家 10 public string Country { get; set; } 11 12 //州 13 public string State { get; set; } 14 15 //市 16 public string City { get; set; } 17 18 public int? ZipCode { get; set; } 19 20 //经度 21 public double? Longitude { get; set; } 22 23 //纬度 24 public double? Latitude { get; set; } 25 26 //地址在MSN天气中对应的编码 27 public string LocationCode { get; set; } 28 }
中国天气网用到的数据结构
1 /// <summary> 2 /// 天气信息,包含省市县区,温度,天气状况,以及天气图标Uri 3 /// </summary> 4 public class WeatherInfo 5 { 6 public WeatherInfo(string province,string city,string county) 7 { 8 this.Province = province; 9 this.City = city; 10 this.County = county; 11 } 12 13 //省份 14 public string Province { get; set; } 15 16 //市 17 public string City { get; set; } 18 19 //县区 20 public string County { get; set; } 21 22 //街道 23 public string District { get; set; } 24 25 //温度 26 private string temp; 27 public string Temp 28 { 29 get { return temp+"°C"; } 30 set { temp = value; } 31 } 32 33 //天气状况 34 public string Condition { get; set; } 35 36 //图标Uri 37 public string IconUri { get; set; } 38 }
查询中国天气的代码
1 /// <summary> 2 /// 私有类,通过中国天气网查询天气 3 /// </summary> 4 private class ChinaWeather 5 { 6 private string pyProvince, pyCity; 7 private string weatherQueryUrl, weatherIcon; 8 public DataBean.WeatherInfo myWeatherInfo; 9 10 11 /// <summary> 12 /// 构造函数,需要传入WeatherInfo参数,然后根据WeatherInfo里面的Province,City和County进行天气查询,然后修改里面的Temp,Condition和IconUrl 13 /// </summary> 14 /// <param name="WeatherInfo"></param> 15 public ChinaWeather(DataBean.WeatherInfo WeatherInfo) 16 { 17 //获取中国天气网查询接口 18 weatherQueryUrl = GlobalsVars.getSysParameter(Enums.SysParametersType.WEATHER_QUERY_CHINA_URL); 19 //获取中国天气网图标Url 20 weatherIcon = GlobalsVars.getSysParameter(Enums.SysParametersType.WEATHER_QUERY_CHINA_ICON); 21 22 myWeatherInfo = WeatherInfo; 23 } 24 25 26 /// <summary> 27 /// 查询天气。调用该方法后,会自动查询中国天气网,并更新WeatherInfo参数里面的属性和字段。 28 /// </summary> 29 /// <returns></returns> 30 public bool Query() 31 { 32 if(QueryProvinceInChina(myWeatherInfo.Province)==false) 33 { 34 //如果连省份的天气都没有查到,则查询失败 35 return false; 36 } 37 else 38 { 39 //省份天气查询成功后,再查具体的城市的天气 40 if (QueryCityInProvince(myWeatherInfo.City) == true) 41 { 42 //城市天气查询成功后,再查具体的县区的天气 43 QueryCountyInCity(myWeatherInfo.County); 44 } 45 } 46 //只要查到省份的天气,则认为查询是成功的。 47 return true; 48 } 49 50 51 /// <summary> 52 /// 下载全国天气信息,在里面查具体的省份的天气信息 53 /// </summary> 54 /// <param name="province">省的名字,例如“浙江”,“浙江省”都行</param> 55 /// <returns></returns> 56 private bool QueryProvinceInChina(string province) 57 { 58 string Url = string.Format(weatherQueryUrl, "china"); 59 string GetStr; 60 61 using (WebClient MyWeb = new WebClient()) 62 { 63 MyWeb.Credentials = CredentialCache.DefaultCredentials; 64 65 try 66 { 67 //下载全国各省的天气 68 GetStr = Encoding.UTF8.GetString(MyWeb.DownloadData(Url)); 69 } 70 catch (Exception err) 71 { 72 log.Error("下载全国XML天气失败", err); 73 return false; 74 } 75 } 76 77 try 78 { 79 XmlDocument dom = new XmlDocument(); 80 dom.LoadXml(GetStr); 81 //选择china主节点 82 XmlNode node = dom.SelectSingleNode("china"); 83 //要匹配的字符串模式 84 string patten; 85 Match m; 86 87 foreach (XmlNode n in node.ChildNodes) 88 { 89 //用全国每一个省的中文名去匹配想要查询的省。这样的话,如果想要查询杭州的天气,输入杭州、杭州市、浙江省杭州市等等,只要包含杭州,就可以查到 90 patten = n.Attributes["quName"].Value; 91 m = Regex.Match(province, patten); 92 93 if (m.Success) 94 { 95 //如果匹配上了,也就是查询到该省的天气了,记录该省的天气,返回TRUE 96 pyProvince = n.Attributes["pyName"].Value; 97 //myWeatherInfo.Province = n.Attributes["cityname"].Value; 98 myWeatherInfo.Temp = n.Attributes["tem1"].Value; 99 myWeatherInfo.Condition = n.Attributes["stateDetailed"].Value; 100 myWeatherInfo.IconUri = string.Format(weatherIcon, n.Attributes["state1"].Value); 101 return true; 102 } 103 } 104 } 105 catch (Exception err) 106 { 107 log.Error("解析全国XML天气失败", err); 108 } 109 110 return false; 111 } 112 113 114 /// <summary> 115 /// 下载具体的省份的信息,在里面查具体的城市的天气信息 116 /// </summary> 117 /// <param name="city">要查的城市的名字,例如“杭州”,“杭州市”都行</param> 118 /// <returns></returns> 119 private bool QueryCityInProvince(string city) 120 { 121 string Url = string.Format(GlobalsVars.getSysParameter(Enums.SysParametersType.WEATHER_QUERY_CHINA_URL), pyProvince); 122 string GetStr; 123 124 using (WebClient MyWeb = new WebClient()) 125 { 126 MyWeb.Credentials = CredentialCache.DefaultCredentials; 127 128 try 129 { 130 //下载具体的省份的天气信息。xml格式 131 GetStr = Encoding.UTF8.GetString(MyWeb.DownloadData(Url)); 132 } 133 catch (Exception err) 134 { 135 log.Error("下载省XML天气失败", err); 136 return false; 137 } 138 } 139 140 //解析下载的xml信息 141 try 142 { 143 XmlDocument dom = new XmlDocument(); 144 dom.LoadXml(GetStr); 145 //选择XML中的主节点 146 XmlNode node = dom.SelectSingleNode(pyProvince); 147 string patten; 148 Match m; 149 150 foreach (XmlNode n in node.ChildNodes) 151 { 152 //利用xml中包含的城市名去匹配想要查询的城市名 153 patten = n.Attributes["cityname"].Value; 154 m = Regex.Match(city, patten); 155 156 if (m.Success) 157 { 158 //查询到了,利用城市名中的属性去查县区天气 159 pyCity = n.Attributes["pyName"].Value; 160 //myWeatherInfo.City = n.Attributes["cityname"].Value; 161 myWeatherInfo.Temp = n.Attributes["temNow"].Value; 162 myWeatherInfo.Condition = n.Attributes["stateDetailed"].Value; 163 myWeatherInfo.IconUri = string.Format(weatherIcon, n.Attributes["state1"].Value); 164 return true; 165 } 166 } 167 } 168 catch (Exception err) 169 { 170 log.Error("解析省XML天气失败", err); 171 } 172 return false; 173 } 174 175 176 /// <summary> 177 /// 下载具体的城市的天气信息,在里面查具体的县区的天气信息 178 /// </summary> 179 /// <param name="county">要查的县区的名字</param> 180 /// <returns></returns> 181 private bool QueryCountyInCity(string county) 182 { 183 string Url = string.Format(GlobalsVars.getSysParameter(Enums.SysParametersType.WEATHER_QUERY_CHINA_URL), pyCity); 184 string GetStr; 185 186 using (WebClient MyWeb = new WebClient()) 187 { 188 MyWeb.Credentials = CredentialCache.DefaultCredentials; 189 190 try 191 { 192 //下载具体的城市的详细天气信息,xml格式 193 GetStr = Encoding.UTF8.GetString(MyWeb.DownloadData(Url)); 194 } 195 catch (Exception err) 196 { 197 log.Error("下载市XML天气失败", err); 198 return false; 199 } 200 } 201 202 //解析xml格式的城市天气 203 try 204 { 205 XmlDocument dom = new XmlDocument(); 206 dom.LoadXml(GetStr); 207 //选择主节点 208 XmlNode node = dom.SelectSingleNode(pyCity); 209 string patten; 210 Match m; 211 212 foreach (XmlNode n in node.ChildNodes) 213 { 214 //利用xml中包含的各县区的名称去匹配想要查询天气的县区 215 patten = n.Attributes["cityname"].Value; 216 m = Regex.Match(county, patten); 217 218 if (m.Success) 219 { 220 //查询到了,更新WeatherInfo 221 //myWeatherInfo.County = n.Attributes["cityname"].Value; 222 myWeatherInfo.Temp = n.Attributes["temNow"].Value; 223 myWeatherInfo.Condition = n.Attributes["stateDetailed"].Value; 224 myWeatherInfo.IconUri = string.Format(weatherIcon, n.Attributes["state1"].Value); 225 return true; 226 } 227 } 228 } 229 catch (Exception err) 230 { 231 log.Error("解析市XML天气失败", err); 232 } 233 return false; 234 } 235 }
查世界天气的代码
1 /// <summary> 2 /// 私有类,通过MSN查询天气 3 /// </summary> 4 private class MsnWeather 5 { 6 public DataBean.WeatherInfo myWeatherInfo; 7 private string weatherQueryLocation, weatherQueryUrl, weatherQueryIcon; 8 9 10 /// <summary> 11 /// 构造函数,需要传入DataBean.WeatherInfo参数。然后根据该参数中的City字段查询天气。然后会更新该参数中的Temp,Condition和IconUrl 12 /// </summary> 13 /// <param name="WeatherInfo"></param> 14 public MsnWeather(DataBean.WeatherInfo WeatherInfo) 15 { 16 myWeatherInfo = WeatherInfo; 17 18 //获取MSN城市编码接口 19 weatherQueryLocation=GlobalsVars.getSysParameter(Enums.SysParametersType.WEATHER_QUERY_FOREIGN_LOCATION); 20 //获取MSN天气查询接口 21 weatherQueryUrl = GlobalsVars.getSysParameter(Enums.SysParametersType.WEATHER_QUERY_FOREIGN_URL); 22 //获取本地天气图标路径 23 weatherQueryIcon = GlobalsVars.getSysParameter(Enums.SysParametersType.WEATHER_QUERY_FOREIGN_ICON); 24 } 25 26 27 /// <summary> 28 /// 调用该方法会根据WeatherInfo中的City进行查询 29 /// </summary> 30 /// <returns></returns> 31 public bool Query() 32 { 33 //定义Location列表,因为城市编码查询是模糊查询,会返回匹配的所有编码 34 List<DataBean.Location> mylist = new List<DataBean.Location>(); 35 //查找该城市在MSN上的编码 36 mylist = QueryLocations(myWeatherInfo.City); 37 if (mylist.Count > 0) 38 { 39 //查到有编码,利用匹配到的第一个编码来查询天气 40 if (GetLatestWeatherReport(mylist[0]) == true) 41 return true; 42 } 43 44 return false; 45 } 46 47 48 /// <summary> 49 /// 根据提供的城市名称查询该城市的编码,利用该编码才能在MSN上查询天气 50 /// </summary> 51 /// <param name="query"></param> 52 /// <returns></returns> 53 private List<DataBean.Location> QueryLocations(string query) 54 { 55 if (query == "" || query.Length < 2) 56 return null; 57 List<DataBean.Location> results = new List<DataBean.Location>(); 58 string searchUrl = weatherQueryLocation + query; 59 60 using (XmlTextReader reader = new XmlTextReader(searchUrl)) 61 { 62 try 63 { 64 //读到XML结尾才结束 65 while (reader.Read()) 66 { 67 //读到的是节点,而且节点的名字是weather,那么就是我们需要的天气节点 68 if (reader.NodeType == XmlNodeType.Element && reader.Name.Equals("weather")) 69 { 70 string weatherLocationName, city, state = "", country = "", locationCode; 71 int zipcode; 72 double longitude, latitude; 73 74 //城市名称 格式:城市,国家 75 reader.MoveToAttribute("weatherfullname"); 76 weatherLocationName = reader.Value; 77 78 reader.MoveToAttribute("zipcode"); 79 bool isZipCodeValid = int.TryParse(reader.Value, out zipcode); 80 81 //经度 82 reader.MoveToAttribute("lon"); 83 bool isLongitudeValid = double.TryParse(reader.Value, out longitude); 84 85 //纬度 86 reader.MoveToAttribute("lat"); 87 bool isLatitudeValid = double.TryParse(reader.Value, out latitude); 88 89 //将fullname分解成城市和国家 90 char[] splitter = { ',' }; 91 string[] cityAndCountry = weatherLocationName.Split(splitter); 92 for (int i = 0; i < cityAndCountry.Length; i++) 93 if (cityAndCountry[i][0] == ' ') 94 cityAndCountry[i] = cityAndCountry[i].Substring(1); 95 city = cityAndCountry[0]; 96 if (cityAndCountry.Length == 2) 97 { 98 country = cityAndCountry[1]; 99 } 100 else if (cityAndCountry.Length == 3) 101 { 102 state = cityAndCountry[1]; 103 country = cityAndCountry[2]; 104 } 105 106 //需要查询城市的城市编码,利用这个去MSN上查天气 107 reader.MoveToAttribute("weatherlocationcode"); 108 locationCode = reader.Value; 109 110 DataBean.Location location = new DataBean.Location(); 111 location.City = city; 112 location.Country = country; 113 location.FullName = weatherLocationName; 114 location.Latitude = (isLatitudeValid) ? latitude : (double?)null; 115 location.Longitude = (isLongitudeValid) ? longitude : (double?)null; 116 location.State = state; 117 location.ZipCode = (isZipCodeValid) ? zipcode : (int?)null; 118 location.LocationCode = locationCode; 119 120 results.Add(location); 121 } 122 } 123 } 124 catch (Exception err) 125 { 126 log.Error("查询MSN地址信息失败", err); 127 } 128 129 } 130 131 return results; 132 } 133 134 135 /// <summary> 136 /// 根据查询到的城市编码查询天气 137 /// </summary> 138 /// <param name="location"></param> 139 /// <returns></returns> 140 private bool GetLatestWeatherReport(DataBean.Location location) 141 { 142 string feedUrl = weatherQueryUrl + location.LocationCode; 143 144 using (XmlTextReader reader = new XmlTextReader(feedUrl)) 145 { 146 try 147 { 148 //读到xml字符串流的结尾 149 while (reader.Read()) 150 { 151 if (reader.NodeType == XmlNodeType.Element) 152 { 153 //只解析当前天气信息,forcast预报信息不解析,直接放弃 154 if (reader.Name.Equals("current")) 155 { 156 double ImperialTemp; 157 //读取温度,华氏温度 158 reader.MoveToAttribute("temperature"); 159 double.TryParse(reader.Value, out ImperialTemp); 160 //转化为摄氏温度 161 int MetricTemp = (int)(5.0 / 9.0 * (ImperialTemp - 32.0)); 162 163 //天气信息 164 reader.MoveToAttribute("skytext"); 165 string weathercondition = reader.Value; 166 167 //天气图片编号 168 reader.MoveToAttribute("skycode"); 169 string IconUrl = weatherQueryIcon + reader.Value + ".png"; 170 171 myWeatherInfo.Temp = MetricTemp.ToString(); 172 myWeatherInfo.Condition = weathercondition; 173 myWeatherInfo.IconUri = IconUrl; 174 175 return true; 176 } 177 } 178 } 179 } 180 catch (Exception err) 181 { 182 log.Error("获取MSN天气失败", err); 183 } 184 } 185 return false; 186 } 187 }