一.需求

最近,刚好项目中有天气预报查询功能的需求,要求录入城市名称,获取该城市今日天气信息及相关气象生活辅助信息等。

例如:查询北京市天气

结果为:

今日北京天气:15℃~5℃ 阵雨转阴,北风3-4级,天气冷,建议着棉服、羽绒服、皮夹克加羊毛衫等冬季服装。年老体弱者宜着厚棉衣、冬大衣 或厚羽绒服。 洗车指数:不宜。紫外线指数:最弱。晨练指数:较不宜.舒适指数:较舒适。

还好,国家气象局提供相关接口,再此表示感谢,虽然个人觉得该api设计思路有待提高,但是相比于其他部委【如交通部】来说,气象局这个冷衙门有开源、开放的心态,相比而言,相当了不起。期待后期能在接口规范、可提供查询城市数量等方面继续提高。

二.接口说明

据我所知,气象局提供三个天气查询接口,如下:

1、实时天气接口

地址:http://www.weather.com.cn/data/ sk/【城市代码】.html

例如:查询北京实时天气

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

结果:

{"weatherinfo":{"city":"北京","cityid":"101010100","temp":"13","WD":"南风","WS":"2","SD":"59%","WSE":"2","time":"10:30","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB"}}

2、今日天气接口

地址:http://www.weather.com.cn/data/cityinfo/【城市代码】.html

例如:查询北京今日天气

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

结果:

{"weatherinfo":{"city":"北京","cityid":"101010100","temp1":"15","temp2":"5℃","weather":"阵雨转阴","img1":"d3.gif","img2":"n2.gif","ptime":"08:00"}}

3、今日及未来天气接口【内容最详细】

地址:http://m.weather.com.cn/data/【城市代码】.html

例如:查询北京今日及未来天气

http://m.weather.com.cn/data/101010100.html

结果:

{"weatherinfo":{"city":"北京","city_en":"beijing","date_y":"2013年10月22日","date":"","week":"星期二","fchh":"08","cityid":"101010100","temp1":"15℃~5℃","temp2":"15℃~4℃………【省略】"index_tr":"适宜","index_co":"较舒适","st1":"11","st2":"1","st3":"13","st4":"5","st5":"14","st6":"4","index_cl":"较不宜","index_ls":"不太适宜","index_ag":"不易发"}}

字段说明:我刚好是调用这个接口,所以下面通过对应的实体及属性来说明上述返回结果中各字段的含义

/// <summary>
/// 天气查询结果信息实体
/// </summary>
public class WeatherinfoModel
{
/// <summary>
/// 城市名称
/// </summary>
public String city{get;set;} /// <summary>
/// 城市英文名称==拼音
/// </summary>
public String city_en{get;set;} /// <summary>
/// 今日时间【年-月-日】
/// </summary>
public String date_y{get;set;} /// <summary>
/// 为空,无用
/// </summary>
public String date{get;set;} /// <summary>
/// 星期几
/// </summary>
public String week{get;set;} /// <summary>
/// 系统更新时间
/// </summary>
public String fchh{get;set;} /// <summary>
/// 城市代码
/// </summary>
public String cityid{get;set;} /// <summary>
/// 今天及之后五天的摄氏温度
/// </summary>
public String temp1{get;set;}
public String temp2{get;set;}
public String temp3{get;set;}
public String temp4{get;set;}
public String temp5{get;set;}
public String temp6{get;set;} /// <summary>
/// 今天及之后五天的华氏温度
/// </summary>
public String tempF1{get;set;}
public String tempF2{get;set;}
public String tempF3{get;set;}
public String tempF4{get;set;}
public String tempF5{get;set;}
public String tempF6{get;set;} /// <summary>
/// 今天及之后五天的天气描述
/// </summary>
public String weather1{get;set;}
public String weather2{get;set;}
public String weather3{get;set;}
public String weather4{get;set;}
public String weather5{get;set;}
public String weather6{get;set;} /// <summary>
/// 天气描述图片序号
/// </summary>
public String img1{get;set;}
public String img2{get;set;}
public String img3{get;set;}
public String img4{get;set;}
public String img5{get;set;}
public String img6{get;set;}
public String img7{get;set;}
public String img8{get;set;}
public String img9{get;set;}
public String img10{get;set;}
public String img11{get;set;}
public String img12{get;set;}
public String img_single{get;set;} /// <summary>
/// 图片名称
/// </summary>
public String img_title1{get;set;}
public String img_title2{get;set;}
public String img_title3{get;set;}
public String img_title4{get;set;}
public String img_title5{get;set;}
public String img_title6{get;set;}
public String img_title7{get;set;}
public String img_title8{get;set;}
public String img_title9{get;set;}
public String img_title10{get;set;}
public String img_title11{get;set;}
public String img_title12{get;set;}
public String img_title_single{get;set;} /// <summary>
/// 今天及之后五天的风速描述
/// </summary>
public String wind1{get;set;}
public String wind2{get;set;}
public String wind3{get;set;}
public String wind4{get;set;}
public String wind5{get;set;}
public String wind6{get;set;} /// <summary>
/// 风速级别描述
/// </summary>
public String fx1{get;set;}
public String fx2{get;set;}
public String fl1{get;set;}
public String fl2{get;set;}
public String fl3{get;set;}
public String fl5{get;set;}
public String fl6{get;set;} /// <summary>
/// 今天穿衣指数
/// </summary>
public String index{get;set;}
public String index_d{get;set;} /// <summary>
/// 48小时穿衣指数
/// </summary>
public String index48{get;set;}
public String index48_d{get;set;} /// <summary>
/// 紫外线及48小时紫外线
/// </summary>
public String index_uv{get;set;}
public String index48_uv{get;set;} /// <summary>
/// 洗车
/// </summary>
public String index_xc{get;set;} /// <summary>
/// 旅游
/// </summary>
public String index_tr{get;set;} /// <summary>
/// 舒适指数
/// </summary>
public String index_co{get;set;} /// <summary>
/// ??
/// </summary>
public String st1{get;set;}
public String st2{get;set;}
public String st3{get;set;}
public String st4{get;set;}
public String st5{get;set;}
public String st6{get;set;} /// <summary>
/// 晨练
/// </summary>
public String index_cl{get;set;} /// <summary>
/// 晾晒
/// </summary>
public String index_ls{ get; set; } /// <summary>
/// 过敏
/// </summary>
public String index_ag{get;set;}
}

总结:从上面三个接口来看,调用的关键是获取【城市代码】,所以气象局又提供了三个查询城市代码接口。个人有个疑问?为何气象局不提供一个或三个xml文档或json文本?比现在省市县逐级拼接获取方便很多,或许已经有,只是我不知道,求补充啊!

4、省份或直辖市代码接口

地址:http://www.weather.com.cn/data/citydata/china.html

结果:

{"10101":"北京","10102":"上海","10103":"天津","10104":"重庆","10105":"黑龙江","10106":"吉林","10107":"辽宁","10108":"内蒙古","10109":"河北","10110":"山西","10111":"陕西","10112":"山东","10113":"新疆","10114":"西藏","10115":"青海","10116":"甘肃","10117":"宁夏","10118":"河南","10119":"江苏","10120":"湖北","10121":"浙江","10122":"安徽","10123":"福建","10124":"江西","10125":"湖南","10126":"贵州","10127":"四川","10128":"广东","10129":"云南","10130":"广西","10131":"海南","10132":"香港","10133":"澳门","10134":"台湾"}

5、省会或地区市代码接口

地址:http://www.weather.com.cn/data/citydata/district/【省份或直辖市代码】.html

例如:查询福建省包含的城市

http://www.weather.com.cn/data/citydata/district/10123.html

结果:

{"01":"福州","02":"厦门","03":"宁德","04":"莆田","05":"泉州","06":"漳州","07":"龙岩","08":"三明","09":"南平"}

6、区或县代码

地址:http://www.weather.com.cn/data/citydata/city/【省份或直辖市代码】+【省会或地区市代码】.html

例如:查询福建省南平市包含的区县

http://www.weather.com.cn/data/citydata/city/1012309.html

结果:

{"01":"南平","02":"顺昌","03":"光泽","04":"邵武","05":"武夷山","06":"浦城","07":"建阳","08":"松溪","09":"政和","10":"建瓯"}

说明:

注意该结果不仅包含区县,还包含上级的地级市或省会城市,所以我们只要获取这一级别的结果,再拼接就可以获取省会城市、地级市及区县的城市代码!

三. 城市代码拼接

通过上述三个接口,我们可以通过拼接省市县级别城市代码,来获取南平市或政和县的城市代码。

例如:南平市代码为:101230901【10123是福建省的省级代码+09南平市的市级代码+01南平市的区县级代码】,同理,政和县代码为:101230909。

知道城市代码后,要获取政和县的今日天气,调用下面的url就可以了:

http://www.weather.com.cn/data/sk/101230909.html

注意:并不是所有的城市代码都是通过省市县来拼接,存在下面两个问题。个人建议各城市的代码完全可以==该城市的邮编,因为各省市县的邮编都是不可能重复的,but.....

问题一:海南下属市及湖北荆州的沙市中区县代码包含省级代码和市级代码,如:

http://www.weather.com.cn/data/citydata/city/1013101.html

http://www.weather.com.cn/data/citydata/city/1012008.html

问题二:四个直辖市的城市代码不是由省+市+县代码拼接,而是用省+县+市代码拼接方式。

所以,城市代码的拼接方法如下:

//pID:省或直辖市代码
//cID:省会或地区市代码
//dID:区或县代码
int code=0;//城市代码
//name:区县名称
//如果是海南省或湖北荆州沙市【感谢luoliurong反馈,否则未对沙市特别处理,无法查询】,则直接获取
if (pID == 10131||name == "沙市")
{
code = int.Parse(dID);
}
//如果是直辖市
else if (pID < 10105)
{
int.TryParse(string.Format("{0}{1}{2}", pID, dID, cID), out code);
}
else
{
int.TryParse(string.Format("{0}{1}{2}", pID, cID, dID), out code);
}

通过上述说明,表明我们需要建一个项目循环请求并获取各级城市的城市代码,可以将城市代码保存在数据库中,也可以保存在xml文件中。我做法是保存在数据库中,同时生成xml文件,一周更新xml文件一次,并将该xml通过文件依赖缓存到内存中,使用该缓存的xml作为城市代码查询的数据源。

四. 省市县代码表表结构

表名:Weather_Province【省代码表实体】

表名:Weather_City【省会或地级市代码表实体】

表名:Weather_District【区或县代码表实体】

可被直接调用代码,即该区县的代码

源码包中的DBScript.sql为上述数据脚本

五. 获取省级代码数据

Http请求方法:

/// <summary>
/// Get方式获取url地址输出内容
/// </summary>
/// <param name="url">url</param>
/// <param name="encoding">返回内容编码方式,例如:Encoding.UTF8</param>
/// <returns></returns>
public static String SendRequestByGetMethod(String url,Encoding encoding)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "GET";
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
StreamReader sr = new StreamReader(webResponse.GetResponseStream(), encoding);
return sr.ReadToEnd();
}

/// <summary> 
/// 生成天气查询省代码表
/// </summary>
private void CreateProvinceCode()
{
m_ProvinceBLL.TruncateProvince();
var responseText = HttpRequestOpt.SendRequestByGetMethod("http://www.weather.com.cn/data/citydata/china.html",System.Text.Encoding.UTF8);
if (!String.IsNullOrEmpty(responseText))
{
m_ProvinceBLL.SaveProvinceCode(responseText);
}
}
/// <summary>
/// 添加天气查询省代码表
/// </summary>
/// <param name="responseText">查询结果文本</param>
public void SaveProvinceCode(String responseText)
{
responseText = responseText.TrimStart('{').TrimEnd('}');
List<Weather_ProvinceModel> list = new List<Weather_ProvinceModel>();
responseText.Split(',').ToList().ForEach(item =>
{
Weather_ProvinceModel provinceModel = new Weather_ProvinceModel();
if (!String.IsNullOrEmpty(item) && item.Split(':').Count() == 2 && !String.IsNullOrEmpty(item.Split(':')[0]) && !String.IsNullOrEmpty(item.Split(':')[1]))
{
int pID = 0;
int.TryParse(item.Split(':')[0].Trim('"'), out pID);
provinceModel.PID = pID;
provinceModel.Name = item.Split(':')[1].Trim('"');
list.Add(provinceModel);
}
});
if (list.Count > 0)
{
m_ProvinceDAL.SaveProvinceCode(list);
}
}
/// <summary>
/// 批量添加天气查询省代码表
/// </summary>
/// <param name="list">省代码表实体集</param>
public void SaveProvinceCode(List<Weather_ProvinceModel> list)
{
SqlBulkCopy sqlBc = null;
DataTable dt = new DataTable();
try
{
sqlBc = new SqlBulkCopy(Common.WebConfig.WeatherDBConnString, SqlBulkCopyOptions.UseInternalTransaction);
sqlBc.DestinationTableName = "Weather_Province";
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(String));
dt.Columns.Add("PID", typeof(int));
if (dt.Rows.Count > 0)
{
sqlBc.WriteToServer(dt);
dt.Clear();
}
list.ForEach(entity =>
{
DataRow dr = dt.NewRow();
dr["Name"] = entity.Name;
dr["PID"] = entity.PID;
dt.Rows.Add(dr);
});
if (dt.Rows.Count > 0)
{
sqlBc.WriteToServer(dt);
dt.Clear();
}
}
catch (Exception ex)
{
string mayLoseData = Common.JsonHelp.SerializeJson(dt);
Common.Log4NetHelp.LoseDataLog("ProvinceDAL", "SaveProvinceCode", string.Format("批量添加天气查询省代码表异常,异常信息:{0}", ex.Message), mayLoseData);
}
finally
{
if (sqlBc != null)
{
sqlBc.Close();
}
}
}

六. 获取省会或地级市代码表数据

///<summary>/// 获取天气查询省代码表所有数据
///</summary>///<returns></returns>public DataSet GetAllProvince()
{
String strSql ="select * from Weather_Province order by PID asc";
return DbHelperSQL.Query(strSql);
}
/// <summary>
/// 生成天气查询市代码表
/// </summary>
private void CreateCityCode()
{
m_CityBLL.TruncateCity();
DataSet ds = m_ProvinceBLL.GetAllProvince();
if (ds != null && ds.Tables.Count > 0 & ds.Tables[0].Rows.Count > 0)
{
ds.Tables[0].Rows.Cast<DataRow>().ToList().ForEach(dr =>
{
int pID = 0;
int.TryParse(dr["PID"].ToString(), out pID);
if (pID > 0)
{
string url = string.Format("http://www.weather.com.cn/data/citydata/district/{0}.html", pID);
var responseText = HttpRequestOpt.SendRequestByGetMethod(url,System.Text.Encoding.UTF8);
if (!String.IsNullOrEmpty(responseText))
{
m_CityBLL.SaveCityCode(pID, responseText);
}
}
else
{
Log4NetHelp.ErrorLog("GetCode", "CreateCityCode",string.Format("存在PID<=0的数据"));
}
});
}
}
/// <summary>
/// 添加天气查询省会或地级市代码
/// </summary>
/// <param name="pID">省ID</param>
/// <param name="responseText">查询结果文本</param>
public void SaveCityCode(int pID, String responseText)
{
responseText = responseText.TrimStart('{').TrimEnd('}');
List<Weather_CityModel> list = new List<Weather_CityModel>();
responseText.Split(',').ToList().ForEach(item =>
{
Weather_CityModel cityModel = new Weather_CityModel();
if (!String.IsNullOrEmpty(item) && item.Split(':').Count() == 2 && !String.IsNullOrEmpty(item.Split(':')[0]) && !String.IsNullOrEmpty(item.Split(':')[1]))
{
cityModel.Name = item.Split(':')[1].Trim('"');
cityModel.PID = pID;
string cID = item.Split(':')[0].Trim('"');
cityModel.CID = cID;
list.Add(cityModel);
}
});
if (list.Count > 0)
{
m_CityDAL.SaveCityCode(list);
}
}
/// <summary>
/// 批量添加天气查询省会或地级市代码表
/// </summary>
/// <param name="list">省会或地级市代码表实体集</param>
public void SaveCityCode(List<Weather_CityModel> list)
{
SqlBulkCopy sqlBc = null;
DataTable dt = new DataTable();
try
{
sqlBc = new SqlBulkCopy(Common.WebConfig.WeatherDBConnString, SqlBulkCopyOptions.UseInternalTransaction);
sqlBc.DestinationTableName = "Weather_City";
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(String));
dt.Columns.Add("PID", typeof(int));
dt.Columns.Add("CID", typeof(String));
if (dt.Rows.Count > 0)
{
sqlBc.WriteToServer(dt);
dt.Clear();
}
list.ForEach(entity =>
{
DataRow dr = dt.NewRow();
dr["Name"] = entity.Name;
dr["PID"] = entity.PID;
dr["CID"] = entity.CID;
dt.Rows.Add(dr);
});
if (dt.Rows.Count > 0)
{
sqlBc.WriteToServer(dt);
dt.Clear();
}
}
catch (Exception ex)
{
string mayLoseData = Common.JsonHelp.SerializeJson(dt);
Common.Log4NetHelp.LoseDataLog("CityDAL", "SaveCityCode", string.Format("批量添加天气查询省会或地级市代码表异常,异常信息:{0}",ex.Message),mayLoseData);
}
finally
{
if (sqlBc != null)
{
sqlBc.Close();
}
}
}

七. 获取区或县代码数据

/// <summary>
/// 获取省会或地级市代码表所有数据
/// </summary>
/// <returns></returns>
public DataSet GetAllCity()
{
String strSql = "select * from Weather_City order by PID asc,CID asc";
return DbHelperSQL.Query(strSql);
}
/// <summary>
/// 生成天气查询区县代码表
/// </summary>
private void CreateDistrictCode()
{
m_DistrictBLL.TruncateDistrict();
DataSet ds = m_CityBLL.GetAllCity();
if (ds != null && ds.Tables.Count > 0 & ds.Tables[0].Rows.Count > 0)
{
ds.Tables[0].Rows.Cast<DataRow>().ToList().ForEach(dr =>
{
int pID = 0;
int.TryParse(dr["PID"].ToString(), out pID);
String cID = dr["CID"].ToString();
if (pID > 0&&!string.IsNullOrEmpty(cID))
{
string url = string.Format("http://www.weather.com.cn/data/citydata/city/{0}{1}.html", pID, cID);
var responseText = HttpRequestOpt.SendRequestByGetMethod(url,System.Text.Encoding.UTF8);
if (!String.IsNullOrEmpty(responseText))
{
m_DistrictBLL.SaveDistrictCode(pID,cID,responseText);
}
}
else
{
Log4NetHelp.ErrorLog("GetCode", "CreateDistrictCode", string.Format("Weather_City表存在非法数据ID={0} PID={0} CID={1}", dr["ID"].ToString(), pID.ToString(),cID));
}
});
}
}
/// <summary>
/// 添加天气查询区县代码表
/// </summary>
/// <param name="pID">省ID</param>
/// <param name="cID">省会或地区市ID</param>
/// <param name="responseText">查询结果文本</param>
public void SaveDistrictCode(int pID, String cID, String responseText)
{
responseText = responseText.TrimStart('{').TrimEnd('}');
List<Weather_DistrictModel> list = new List<Weather_DistrictModel>();
responseText.Split(',').ToList().ForEach(item =>
{
Weather_DistrictModel districtModel = new Weather_DistrictModel();
if (!String.IsNullOrEmpty(item) && item.Split(':').Count() == 2 && !String.IsNullOrEmpty(item.Split(':')[0]) && !String.IsNullOrEmpty(item.Split(':')[1]))
{
string name = item.Split(':')[1].Trim('"');
districtModel.Name = name;
districtModel.PID = pID;
districtModel.CID = cID;
var dID=item.Split(':')[0].Trim('"');
districtModel.DID = dID;
int code = 0;
//海南的DID=Code,无语啊,对比地址:
//http://www.weather.com.cn/data/citydata/city/1013101.html
//http://www.weather.com.cn/data/citydata/city/1011101.html
// 湖北荆州的沙市DID=Code
//http://www.weather.com.cn/data/citydata/city/1012008.html
if (pID == 10131 || name == "沙市")
{
code = int.Parse(dID);
}
else if (pID < 10105)
{
//注意:直辖市所属的区县市代码拼接方式与非直辖市不通
int.TryParse(String.Format("{0}{1}{2}", pID.ToString(), dID, cID), out code);
}
else
{
int.TryParse(String.Format("{0}{1}{2}", pID.ToString(), cID, dID), out code);
}
districtModel.Code = code;
list.Add(districtModel);
}
});
if (list.Count > 0)
{
m_DistrictDAL.SaveDistrictCode(list);
}
}
/// <summary>
/// 批量添加天气查询区县代码表
/// </summary>
/// <param name="list">区县码表实体集</param>
public void SaveDistrictCode(List<Weather_DistrictModel> list)
{
SqlBulkCopy sqlBc = null;
DataTable dt = new DataTable();
try
{
sqlBc = new SqlBulkCopy(Common.WebConfig.WeatherDBConnString, SqlBulkCopyOptions.UseInternalTransaction);
sqlBc.DestinationTableName = "Weather_District";
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(String));
dt.Columns.Add("PID", typeof(int));
dt.Columns.Add("CID", typeof(String));
dt.Columns.Add("DID", typeof(String));
dt.Columns.Add("Code", typeof(int));
if (dt.Rows.Count > 0)
{
sqlBc.WriteToServer(dt);
dt.Clear();
}
list.ForEach(entity =>
{
DataRow dr = dt.NewRow();
dr["Name"] = entity.Name;
dr["PID"] = entity.PID;
dr["CID"] = entity.CID;
dr["DID"] = entity.DID;
dr["Code"] = entity.Code;
dt.Rows.Add(dr);
});
if (dt.Rows.Count > 0)
{
sqlBc.WriteToServer(dt);
dt.Clear();
}
}
catch (Exception ex)
{
string mayLoseData = Common.JsonHelp.SerializeJson(dt);
Common.Log4NetHelp.LoseDataLog("DistrictDAL", "SaveDistrictCode", string.Format("批量添加天气查询区县代码表异常,异常信息:{0}", ex.Message), mayLoseData);
}
finally
{
if (sqlBc != null)
{
sqlBc.Close();
}
}
}

八. 生成天气查询城市代码XML

/// <summary>
/// 获取直辖市、省会、地级市及区县的天气查询代码及市名称+区县名称的全称
/// </summary>
/// <returns></returns>
public DataSet GetNameCodeInfo()
{
string strSql = @"select d.Name as Name,p.Name+d.Name as FullName,d.Code as Code from Weather_District d
left join Weather_Province p on d.PID=p.PID";
return DBUtility.DbHelperSQL.Query(strSql);
}

说明:为何要全称FullName,因为存在两个城市同名的情况,例如:北京有朝阳,辽宁也有朝阳,所以通过全称来提示用户录入更准确的城市信息,如下:

private static String savePath = string.Format("{0}config/weatherConfig.xml", AppDomain.CurrentDomain.BaseDirectory);
/// <summary>
/// 生成xml文档
/// </summary>
public void CreateWeatherXML()
{
var ds = GetNameCodeInfo();
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
XElement root = new XElement("Weather");
ds.Tables[0].Rows.Cast<DataRow>().ToList().ForEach(dr =>
{
root.Add(new XElement("City",
new XAttribute("Name", dr["Name"].ToString()),
new XAttribute("FullName", dr["FullName"].ToString()),
new XAttribute("Code", dr["Code"].ToString())
));
});
root.Save(savePath);
}
}

生成天气查询城市代码的xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<Weather>
<City Name="北京" FullName="北京北京" Code="101010100" />
<City Name="海淀" FullName="北京海淀" Code="101010200" />
<City Name="朝阳" FullName="北京朝阳" Code="101010300" />
<City Name="顺义" FullName="北京顺义" Code="101010400" />
<City Name="怀柔" FullName="北京怀柔" Code="101010500" />
<City Name="通州" FullName="北京通州" Code="101010600" />
<City Name="昌平" FullName="北京昌平" Code="101010700" />
<City Name="延庆" FullName="北京延庆" Code="101010800" />
<City Name="丰台" FullName="北京丰台" Code="101010900" />
<City Name="石景山" FullName="北京石景山" Code="101011000" />
<City Name="大兴" FullName="北京大兴" Code="101011100" />
<City Name="房山" FullName="北京房山" Code="101011200" />
<City Name="密云" FullName="北京密云" Code="101011300" />
<City Name="门头沟" FullName="北京门头沟" Code="101011400" />

未完,更多数据

九. 天气查询

/// <summary>
/// weatherConfig.xml文档
/// </summary>
private static XElement docRoot
{
get
{
try
{
string key = "WeatherBLL_docRoot";
var cache = WebCache.GetCache(key);
if (cache != null)
{
return (XElement)cache;
}
else
{
AsynReCreateCodeAndXml();
var result = XElement.Load(savePath);
WebCache.SetCache(key, result, DateTime.Now.AddDays(7));
return result;
}
}
catch
{
return XElement.Load(savePath);
}
}
}
/// <summary>
/// 天气查询
/// </summary>
/// <param name="keyWord">关键字</param>
/// <returns></returns>
public string QueryFutureWeather(String keyWord)
{
keyWord = HandleKeyWord(keyWord);
if (keyWord.Length < 2)
{
return string.Empty;
}
else
{
var queryResult = from d in docRoot.Elements("City")
where (d.Attribute("Name").Value == keyWord || d.Attribute("FullName").Value == keyWord)
select d;
if (queryResult.Count() > 1)
{
List<String> fullNames=new List<string>();
foreach(var q in queryResult)
{
fullNames.Add(q.Attribute("FullName").Value);
}
return String.Format("您要查询的是:{0},请输入上述全称之一!", string.Join("、", fullNames.ToArray()));
}
else if (queryResult.Count() == 1)
{
String code = queryResult.First().Attribute("Code").Value;
try
{
var weatherResult = RequestWeatherResult(code);
return string.Format("今日{0}天气:{1} {2},{3},{4} 洗车指数:{5}。紫外线指数:{6}。晨练指数:{7}.舒适指数:{8}。",
weatherResult.city, weatherResult.temp1, weatherResult.weather1,
weatherResult.wind1, weatherResult.index_d, weatherResult.index_xc,
weatherResult.index_uv, weatherResult.index_cl, weatherResult.index_co);
}
catch (System.Net.WebException ex)
{
Log4NetHelp.ErrorLog("WeatherBLL", "QueryFutureWeather", string.Format("查询天气异常,调用代码为为:{0}", code), ex);
return string.Format("网速繁忙,请您再次查询!");
} }
else
{
return String.Format("抱歉!暂无{0}天气信息", keyWord);
}
}
}
/// <summary>
/// 请求天气查询结果
/// </summary>
/// <param name="cityCode">城市代码</param>
/// <returns></returns>
private WeatherinfoModel RequestWeatherResult(String cityCode)
{
String key = string.Format("WeatherBLL_RequestWeatherResult_{0}", cityCode);
var cache= WebCache.GetCache(key);
if (cache != null)
{
return (WeatherinfoModel)cache;
}
else
{
String url = String.Format("http://m.weather.com.cn/data/{0}.html", cityCode);
String result = HttpRequestOpt.SendRequestByGetMethod(url,System.Text.Encoding.UTF8);
result = GetJsonContent(result);
WeatherinfoModel info = (WeatherinfoModel)JsonHelp.DeserializeJson<WeatherinfoModel>(result);
if (info != null)
{
//相同地址查询结果缓存一小时
WebCache.SetCache(key, info, 60);
}
return info;
}
}
/// <summary>
/// 获取天气查询结果里面的JSON内容
/// </summary>
/// <param name="weatherQueryResult">天气查询结果</param>
/// <returns></returns>
private String GetJsonContent(String weatherQueryResult)
{
string pattern = "{\"weatherinfo\":(.*)}";
var result = Regex.Match(weatherQueryResult,pattern,RegexOptions.IgnoreCase).Groups;
if (result.Count > 1)
{
return result[1].Value;
}
return string.Empty;
}
/// <summary>
/// 获取包含省市区县关键字的城市
/// </summary>
/// <returns></returns>
private List<String> GetExpectWords()
{
string key = "WeatherBLL_GetExpectWords";
var cache = WebCache.GetCache(key);
if (cache != null)
{
return (List<String>)cache;
}
else
{
List<String> expectionWords = new List<String>();
var ds = m_WeatherDAL.GetExpectWords();
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
ds.Tables[0].Rows.Cast<DataRow>().ToList().ForEach(dr =>
{
expectionWords.Add(dr["Name"].ToString());
});
}
WebCache.SetCache(key,expectionWords,savePath);
return expectionWords;
}
}
/// <summary>
/// 关键字处理,忽略省市区县的关键字,如:北京市>北京
/// </summary>
/// <param name="keyWord">用户录入关键字</param>
/// <returns></returns>
private String HandleKeyWord(String keyWord)
{
List<String> expectWords = GetExpectWords();
if (expectWords.Count > 0)
{
foreach (String s in expectWords)
{
if (keyWord == s)
{
return keyWord;
}
}
}
List<String> delWords = new List<String>() { "省","市","区","县"};
delWords.ForEach(delWord =>
{
keyWord=keyWord.Replace(delWord, "");
});
return keyWord;
}
/// <summary>
/// 获取区县代码表中包含省市区县关键字的城市
/// </summary>
/// <returns></returns>
public DataSet GetExpectWords()
{
string strSql = @"select Name from Weather_District
where (Name like '%省%' or Name like '%市%' or Name like '%区%' or Name like '县')";
return DBUtility.DbHelperSQL.Query(strSql);
}

十、异步生成城市代码XML

private delegate void ReCreateCodeAndXml();

/// <summary>
/// 异步重新生成城市代码和XML信息
/// </summary>
private static void AsynReCreateCodeAndXml()
{
ReCreateCodeAndXml re = new ReCreateCodeAndXml(ReCreateCodeAndXmlInfo);
IAsyncResult asyn = re.BeginInvoke(new AsyncCallback(CompletedCal), null);
}
/// <summary>
/// 重新生成城市代码和XML信息
/// </summary>
private static void ReCreateCodeAndXmlInfo()
{
string url = string.Format("{0}CreateCodeAndXml.ashx", WebConfig.Domain);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.Timeout = 120000;//两分钟
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream(),Encoding.UTF8);
var result = sr.ReadToEnd();
if (result != "success")
{
Log4NetHelp.ErrorLog("WeatherBLL", "ReCreateCodeAndXmlInfo", string.Format("重新获取省市县代码表及重新生天气xml异常,异常信息:{0}",result));
}
}
private static void CompletedCal(IAsyncResult isa)
{ }

用途:异步更新XML,第一次生成XML的时候使用同步操作,之后更新该XML使用异步,这样可减少http请求时间。

十一、示例代码

代码结构图

生成各级代码表及创建xml

天气查询

示例源码下载:【点击此处下载】

说明:调试时,接口http://m.weather.com.cn/data/101010100.html已不可用

【转自】http://www.cnblogs.com/lonelyxmas/p/5667230.html

【转载】C#调用国家气象局天气预报接口的更多相关文章

  1. C#调用国家气象局天气预报接口

    原文:C#调用国家气象局天气预报接口 一.需求 最近,刚好项目中有天气预报查询功能的需求,要求录入城市名称,获取该城市今日天气信息及相关气象生活辅助信息等. 例如:查询北京市天气 结果为: 今日北京天 ...

  2. webservice通信调用天气预报接口实例

    转载:http://www.cnblogs.com/warrior4236/p/5668449.html 一:环境搭建 1:新建一个java project工程weatherInf 2:引入相应的ja ...

  3. 开源免费天气预报接口API以及全国所有地区代码!!(国家气象局提供) 【转】

    国家气象局提供的天气预报接口 接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data ...

  4. 开源免费的天气预报接口API以及全国所有地区代码(国家气象局提供)

    天气预报一直是各大网站的一个基本功能,最近小编也想在网站上弄一个,得瑟一下,在网络搜索了很久,终于找到了开源免费的天气预报接口API以及全国所有地区代码(国家气象局提供),具体如下: 国家气象局提供的 ...

  5. 基于JAVA的全国天气预报接口调用示例

    step1:选择本文所示例的接口"全国天气预报接口" url:https://www.juhe.cn/docs/api/id/39/aid/87step2:每个接口都需要传入一个参 ...

  6. 开源免费天气预报接口API以及全国全部地区代码!!(国家气象局提供)

    国家气象局提供的天气预报接口 接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data ...

  7. 国家气象局提供的天气预报接口(完整Json接口)

    国家气象局提供的天气预报接口主要有三个,分别是:http://www.weather.com.cn/data/sk/101010100.htmlhttp://www.weather.com.cn/da ...

  8. 5. webservice通信调用天气预报接口实例

    转自:https://blog.csdn.net/xiejuan6105/article/details/78452605 一:环境搭建 1:新建一个java project工程weatherInf ...

  9. [Android] 免费天气预报接口

    [Android] 免费天气预报接口 这是 国家气象局提供的天气预报接口 [免费] 当然,网上有很多的收费API或者每天定次数的接口 使用 国家气象局 的步骤如下: 1.首先获取城市ID号 北京:10 ...

随机推荐

  1. PAT Basic 1019

    1019 数字黑洞 给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有“数字 ...

  2. 使用Lucene的java api 写入和读取索引库

    import org.apache.commons.io.FileUtils;import org.apache.lucene.analysis.standard.StandardAnalyzer;i ...

  3. HTML5教程之本地存储SessionStorage

    SessionStorage: 将数据保存在session对象中,所谓session是指用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间会话,也就是用户浏览这个网站所花费的时间就是sess ...

  4. 大数据学习——kafka+storm+hdfs整合

    1 需求 kafka,storm,hdfs整合是流式数据常用的一套框架组合,现在 根据需求使用代码实现该需求 需求:应用所学技术实现,kafka接收随机句子,对接到storm中:使用storm集群统计 ...

  5. 2017 ACM/ICPC Asia Regional Qingdao Online

    Apple Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submi ...

  6. SQL注入与xss

    1. 什么是SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.通过递交参数构造巧妙的SQL语句,从而成功获取 ...

  7. hdu 1848 sg——dfs&&打表双实现

    Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  8. 【容器人必看】你一定要来 ECUG Con 2018 的三个理由!

    引领国内云领域风向的高端峰会 ECUG Con 2018,即将在 12 月 22-23 日 深圳南山 全新启程!如果你的工作和容器内容相关联,如果你的兴趣和容器技术有交集,如果你是「容器人」,那么这就 ...

  9. 刷题总结——bzoj1725(状压dp)

    题目: 题目描述 Farmer John 新买了一块长方形的牧场,这块牧场被划分成 N 行 M 列(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地. FJ  ...

  10. 解决 sqlalchemy 报错:(1193, "Unknown system variable 'tx_isolation'")

    1出现此报错的原因是使用的mysql8.0 以前用的是:tx_isolation 现在用是: transaction_isolation a.通过升级 sqlalchemy 的方法可以解决此问题, p ...