愉悦的绅士 【开发记录】如何在B/S项目中使用中国天气的实时天气功能
好久没有更新我的博客了,正好手头有一个比较合适的项目经验可以分享出来,就是这个如何使用中国天气的天气预报功能,也正好做个项目经验记录。
功能需求
这个功能需求比较简单,就是想在网页端显示实时天气数据。
解决方案:
第一种:使用百度地图的api来做,以定位为例,可以很方便的查找到用的的所在地,进而进行天气查询(或者一步到位,直接能获取到用户所在地的天气信息);然而使用百度地图的api需要去申请一个key才能使用,比较的麻烦,于是就放弃了,有兴趣的园友可以自己去尝试一下;
第二种:既然方便的方式用不了,那么只能自己去寻找另一种的解决方案了;获取实时天气的步骤我给分了两步,第一步先获取用户的所在地,第二步根据所在地获取实时天气数据。
跨域的问题:
先在这里把跨域的问题提一下吧,js的ajax功能为了安全性考虑,只允许ajax访问相同域名下的接口,其他网站是不允许访问的;虽说ajax有jsonp的跨域请求,但是也得要求被访问的接口支持jsonp的数据格式返回(jsonp也是有一定的数据解析格式的),然而本文提到的接口基本上都是返回html或者字符串,是不符合jsonp数据解析的,因此这里需要后台来进行代理请求(就是js访问自己的后台,然后后台进行一次web请求而已)。
代码实现
获取城市
第一种:
http://2018.ip138.com/ic.asp(父网址http://www.ip138.com/),浏览器能直接打开,可以通过F12查看网页的代理请求,发现返回的是html页,不方便确定城市信息字符串的位置,并且使用上述代码返回数据,汉字一直是乱码,所以这个网址接口被pass掉了;
第二种:
我也是参考根据IP查询所在城市接口(查询用户所在城市)这个博客来做的,使用的其中的:搜狐IP地址查询接口(可设置编码):http://pv.sohu.com/cityjson?ie=utf-8,这里最好设置编码(ie=utf-8),否则汉字也有可能会乱码,这里返回的结果是
var returnCitySN = {"cip": "", "cid": "370100", "cname": "山东省济南市"};
调用方式是在html页里面引用就好,也不必再考虑跨域的问题,而且在js里面也可以直接使用returnCitySN 这个对象(object)。
获取到用户所在的城市就可以进行下一步操作了...
获取实时天气
使用的是后台来进行代理请求
获取用户的所在地之后,就能获取实时天气了,这里也是参考园友的博客天气预报接口api(中国天气网)来做的,主要用了里面的城市与其对应的代码,我也给封装了下(原谅我没给换行XD):
城市对应代码
这样就能根据上面获取对应的城市代码了,以济南(101120101)为例
1、首先我们先登录到中国天气网,找到济南的天气,点开查看详情,会跳转到详情界面http://www.weather.com.cn/weather1d/101120101.shtml
2、在详情界面F12能看到这个界面的网络请求,我们会发现有有一个特殊的请求,这里返回了我们需要的数据,也可以看到请求的地址是http://d1.weather.com.cn/sk_2d/101120101.html?_=1544606328541,但是直接打开这个网址或者直接使用后台去请求是不允许的,原因是在请求头少了一个referer的属性,加上就好了
后台代码如下:
复制代码
public class WeatherCache
{
public string Weather { get; set; }
public DateTime DateTime { get; set; }
}
//-------------------------------------华丽分割线-----------------------------------------
public static Dictionary WeatherCaches = new Dictionary();
public string GetWeatherByCityCode(string code)
{
string str = string.Empty;
if (WeatherCaches.ContainsKey(code))
{
if ((DateTime.Now - WeatherCaches[code].DateTime).Minutes > 15)
{
str = await GetWeather(code);
WeatherCaches[code].Weather = str;
WeatherCaches[code].DateTime = DateTime.Now;
}
else
str = WeatherCaches[code].Weather;
}
else
{
str = GetWeather(code);
WeatherCaches.Add(code, new WeatherCache { Weather = str, DateTime = DateTime.Now });
}
return str;
}
private string GetWeather(string code)
{
Encoding encoding = Encoding.UTF8;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://d1.weather.com.cn/sk_2d/" + code + ".html");
request.Method = "GET";
request.Headers.Add("Referer", "http://www.weather.com.cn/weather1d/" + code + ".shtml");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string str = string.Empty;
using (Stream s = response.GetResponseStream())
{
StreamReader reader = new StreamReader(s, encoding);
str = reader.ReadToEnd();
}
return str;
}
复制代码
到此为止我们终于获取到了用户所在地的实时天气数据了,返回前台js(同样使用 eval(result)函数处理下返回的字符串就可以了)后怎么展示就不是本章的重点了,可以随便前端折腾。
总结
总的来说就是适用后台来进行代理请求
http://pv.sohu.com/cityjson?ie=utf-8 获取城市信息
http://d1.weather.com.cn/sk_2d/101120101.html 获取城市的实时天气数据
特别注意,上述接口可能会过期失效,到时留言,我若看到会进行更新https://www.cnblogs.com/nbclw/p/10109683.html