• AJAX(七)jsonp实战--天气预报


      一、案例

      本次要做的案例的是使用jsonp制作一个查询天气情况的网页,我会从如何抓取数据接口,到一步一步完成这个案例来详细讲解。

      这个页面样式非常简单,截图如下。用户需要先选择一个城市,然后点击查看天气,那么最近5天的天气数据,就会展示到下面。

       

      二、数据从何而来

      当然我们不可能自己建气象站,我们只有通过互联网拿到别人“分享”给我们的数据接口,然后通过这个数据接口获取全国的气象数据。这样我们就必须使用jsonp了,因为提供气象数据服务的api,其所在的域名肯定跟我们自己的应用程序不是一个域名。

      那么问题来了,我们如何知道哪里有api提供气象数据服务的?这个就要多观察多积累了。比如现在很多人的电脑上都会安装360,一般360杀毒在安装时候会篡改你的浏览器主页为“hao360”这个网站,那么你打开网页,每次都会看到这样的画面。

                      

      这个网站在非常显眼的地方提供了一个查看天气的模块。难道360还开着气象站?如果不是,那我们只要看看它是如何搞到数据的,我们就能如法炮制了。

      一般你可以这样做:

      1.在气象模块上点鼠标右键->审查元素。去看看他的结构

      2.打开开发者选项工具窗口,点击Network(网络)选项卡,然后去查看请求报文,这样就能找到气象数据从哪儿来了。

      不过,如果你没有经验,你会被请求报文列表中的数据给吓住,因为实在是太多了,至少不下300条请求项。那我们怎么去找真正需要的那个请求呢?

      试想,这个hao360也不可能自己弄个气象站,所以它必然也是抓取的第三方api,所以也必然是通过jsonp的形式来实现的。那么我们只需要在所有的请求报文中按type这一列排下序,然后就只管看请求类型是script的那些项。这样一下就把范围缩小了很多很多。

      最后我们找到,这里的请求url是:https://cdn.weather.hao.360.cn/sed_api_weather_info.php?code=101180201&app=hao360&_jsonp=__jsonp3__

      简单说明下这个url的参数

      1.code:要查询的城市编码,这个可以百度

      2._jsonp:你自己定义的回调函数的名字。

      3.其他的参数都无关紧要,至少对本案例来说是这样。

      在浏览器里打开这个链接,你看到的结果是这样的:

      当然,我只截取了一小部分。不过已经可以看出了,这是一个典型的jsonp跨域访问。

      然后,我把数据copy出来,贴到sublime中,格式化之后,数据是这个样子的。

     1 {
     2     "pubdate": "2018-06-25",
     3     "pubtime": "16:44:10",
     4     "time": 1529916250,
     5     "area": [
     6         ["u6cb3u5357", "18"],
     7         ["u5b89u9633", "1802"],
     8         ["u5b89u9633", "101180201"]
     9     ],
    10     "weather": [{
    11         "date": "2018-06-25",
    12         "info": {
    13             "dawn": ["2", "u9634", "24", "u5357u98ce", "u5faeu98ce", "19:44"],
    14             "day": ["8", "u4e2du96e8", "27", "u5317u98ce", "u5faeu98ce", "05:07"],
    15             "night": ["8", "u4e2du96e8", "22", "u897fu98ce", "u5faeu98ce", "19:44"]
    16         }
    17     }, {
    18         "date": "2018-06-26",
    19         "info": {
    20             "dawn": ["8", "u4e2du96e8", "22", "u897fu98ce", "u5faeu98ce", "19:44"],
    21             "day": ["7", "u5c0fu96e8", "28", "u5357u98ce", "u5faeu98ce", "05:07"],
    22             "night": ["1", "u591au4e91", "22", "u5357u98ce", "u5faeu98ce", "19:44"]
    23         }
    24     }, {
    25         "date": "2018-06-27",
    26         "info": {
    27             "dawn": ["1", "u591au4e91", "22", "u5357u98ce", "u5faeu98ce", "19:44"],
    28             "day": ["0", "u6674", "37", "u5357u98ce", "u5faeu98ce", "05:08"],
    29             "night": ["0", "u6674", "24", "u5317u98ce", "3-5u7ea7", "19:44"]
    30         }
    31     }, {
    32         "date": "2018-06-28",
    33         "info": {
    34             "dawn": ["0", "u6674", "24", "u5317u98ce", "3-5u7ea7", "19:44"],
    35             "day": ["0", "u6674", "36", "u4e1cu5317u98ce", "u5faeu98ce", "05:08"],
    36             "night": ["1", "u591au4e91", "21", "u897fu98ce", "u5faeu98ce", "19:45"]
    37         }
    38     }, {
    39         "date": "2018-06-29",
    40         "info": {
    41             "dawn": ["1", "u591au4e91", "21", "u897fu98ce", "u5faeu98ce", "19:45"],
    42             "day": ["1", "u591au4e91", "35", "u4e1cu5357u98ce", "u5faeu98ce", "05:08"],
    43             "night": ["1", "u591au4e91", "22", "u5357u98ce", "u5faeu98ce", "19:45"]
    44         }
    45     }],
    46     。。。。。。
    47 }

      简单解释下数据:

      1.这里只截取了数据的一部分,只保留了我们案例中需要用到的那一小部分,感兴趣的自己去研究吧。

      2.显然,这个数据是js中的,json格式数据。

      3.本案例中用到的气象数据,是在这个json对象的“weather”属性中。这个属性的值是一个js数组,数组一共有5个元素,每个元素又是一个json对象,每个json对象都代表了一天的天气情况。

      三、案例的HTML结构

      先看下页面的HTML结构  

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>天气预报-hao360接口</title>
        <link rel="stylesheet" href="css/weather.css">
    </head>
    <body>
        <div class="wt_container">
            <div class="city">
                <select id="selCity">
                    <option value="101180201">大安阳</option>
                    <option value="101010100">北京</option>
                    <option value="101180101">郑州</option>
                    <option value="101250101">长沙</option>
                    <option value="101050101">哈尔滨</option>
                    <option value="101130101">乌鲁木齐</option>
                    <option value="101280101">广州</option>
                </select>
                <button id="btn">查看天气</button>
            </div>
            <div class="weather">
                <ul id="wtInfo">
                    <!-- <li>
                        <h2>25日</h2>
                        <div class="day">
                            <h3>白天天气</h3>
                            <p>天气:</p>
                            <p>温度</p>
                            <p>风向</p>
                            <p>风速</p>
                        </div>
                        <div class="night">
                            <h3>夜间天气</h3>
                            <p>天气:</p>
                            <p>温度</p>
                            <p>风向</p>
                            <p>风速</p>
                        </div>
                    </li>                 -->
                </ul>
            </div>
        </div>
    </body>
    </html>

      大家都看得懂,简单说明下:

      1.select标签中的每个选项都有一个value值,这个值对应的城市编码,这个编码是国家标准编码,不是自己随便乱写的,我是从百度出来然后写死到页面上的。当然,网上也有关于提供省市编码查询的api,你完全可以根据本案例所讲的方法,结合之前AJAX中讲的省市联动的案例,把这里城市的选择做成活的。我这里为了简单起见,随便从网上扒了几个城市,把城市的code拷贝了一下就写死到HTML了。目的只是为了让例子别太复杂。

      2.由于我们拿到的数据是5天的数据,所以我们用一个<ul id = "wtInof">标签来展示所有的查询到的5天的天气,每天的天气用一个li包住。HTML中注释掉的部分就是模拟数据。

      我们在js部分,只需要通过jsonp请求道数据,然后按照模拟数据的格式,填充到ul里就行了。

      四、案例的js部分

      直接看代码

     1 <script src="js/jquery-3.3.1.js"></script>
     2 <script>
     3     function callback(data){
     4         //1.清空ul#wtInfo
     5         $("#wtInfo").html("");
     6         //2.呈现数据
     7         var wt = data.weather;
     8         $.each(wt, function(index, ele){
     9             var date = ele.date;
    10             var day = ele.info.day;
    11             var night = ele.info.night;
    12             var tag = "<li>";
    13             tag += "<h2>" + date + "</h2>";
    14             tag += "<div class='day'>";
    15             tag += "<h3>白天天气</h3>";
    16             tag += "<p>天气:" + day[1] + "</p>";
    17             tag += "<p>温度:" + day[2] + "</p>";
    18             tag += "<p>风向:" + day[3] + "</p>";
    19             tag += "<p>风速:" + day[4] + "</p>";
    20             tag += "</div>";
    21             tag += "<div class='night'>";
    22             tag += "<h3>夜间天气</h3>";
    23             tag += "<p>天气:" + night[1] + "</p>";
    24             tag += "<p>温度:" + night[2] + "</p>";
    25             tag += "<p>风向:" + night[3] + "</p>";
    26             tag += "<p>风速:" + night[4] + "</p>";
    27             tag += "</div>";
    28             tag += "</li>";
    29             $("#wtInfo").append(tag);
    30         });
    31     }
    32     $(function () {
    33         $("#btn").on("click", function () {
    34             var cityCode = $("#selCity option:selected").val();
    35             var url =
    36                 'https://cdn.weather.hao.360.cn/sed_api_weather_info.php?app=hao360&_jsonp=callback&code=' +
    37                 cityCode;
    38             $("body").append($("<script src='" + url + "'><script>"));
    39         })
    40     })
    41 </script>

      代码解释:

      1.这用到了jQuery,所以第1行代码先引入了jQuery包

      2.jsonp的原理是通过<script>标签发出请求,而本例中不希望一打开网页就显示某一个城市的天气数据,而是要先选择一个,然后点击查询按钮,才发出请求,得到气象数据, 展示数据。

      3.所以我们的思路是:肯定不能在页面上写死那个做jsonp请求的<script src = "......">标签。我们的做法是,当点击按钮时,我们动态的获取到所选select标签中城市的code,然后拼写出待请求的url,最后在文档(document)的body标签底部,动态添加这个做jsonp请求的<script src = "......">标签。

      4.代码中定义的function callback(data)函数,就是用来做回调函数的,在这个回调函数中,主要功能就是解析json数据,然后填充到ul中。本身代码逻辑不复杂,就是拼写每个li,以及li里边的各项元素有点费事而已。

      五、后记

      这个案例,到这里就结束了。我再补充2点:

      1.这个案例中需要大量拼写HTML标签代码,这么做是相当费时费力的,而且容易出错;一旦开发一个复杂点的页面,这么做是非常痛苦的。如何改进?我们可以使用模板技术。前端模板插件很多,最流行的前端模板就是art-template.js,大家可以从网上下载。我在这里给出使用该模板改造本例后的js代码,具体这个art-template怎么用,大家看看他官服的demo就一目了然,非常简单。  

    <script src="js/template.js"></script>
    <script id="weatherTemp" type="text/html">
        <li>
            <h2><%= date %></h2>
            <div class="day">
                <h3>白天天气</h3>
                <% for(var i=1; i < info.day.length; i++){%>
                    <p><%= info.day[i]%></p>
                <% }%>
            </div>
            <div class="night">
                <h3>夜间天气</h3>
                <% for(var i=1; i < info.night.length; i++){%>
                    <p><%= info.night[i]%></p>
                <% }%>
            </div>
        </li>
    </script>
    <script>
        function callback(data) {
            //1.清空ul#wtInfo
            $("#wtInfo").html("");
            //2.呈现数据
            var wt = data.weather;
            $.each(wt, function (index, ele) {
                var html = template("weatherTemp", ele)
                $("#wtInfo").append(html);
            });
        }
        $(function () {
            $("#btn").on("click", function () {
                var cityCode = $("#selCity option:selected").val();
                var url =
                    'https://cdn.weather.hao.360.cn/sed_api_weather_info.php?app=hao360&_jsonp=callback&code=' +
                    cityCode;
                $("body").append($("<script src='" + url + "'><script>"));
            })
        })
    </script>

       2.如果我们每次都去分析别人的报文,那将是一个非常痛苦的过程。好在现在有专业的,专门提供数据服务的web api提供商,比如“聚合数据”,百度api商店等等,还有很多,大家可以去网上搜索下。其中有免费的,有付费的。比如聚合数据,申请账号是免费的,提供的服务有的免费,有的付费,不过即使是付费的,也可以免费使用1000次,对于我们学习来说1000次够玩了。

  • 相关阅读:
    作业信息获取
    SQL Server数据库性能监控计数器
    c# 索引器學習
    C# DataGridView 小技巧
    C# DataTable 小技巧
    c# 小技巧
    C# new,Virtual,abstract,sealed,Override的簡單理解
    C# 位操作符
    C# 類型小技巧
    C# partial 局部类型
  • 原文地址:https://www.cnblogs.com/ldq678/p/9748904.html
Copyright © 2020-2023  润新知