1. 程式人生 > >AJAX(七)jsonp實戰--天氣預報

AJAX(七)jsonp實戰--天氣預報

每天 app callback 數據服務 sele 網絡 請求 sel url

  一、案例

  本次要做的案例的是使用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         ["\u6cb3\u5357", "18"],
 7         ["\u5b89\u9633", "1802"],
 8         ["\u5b89\u9633", "101180201"]
 9     ],
10     "weather": [{
11         "date": "2018-06-25",
12         "info": {
13             "dawn": ["2", "\u9634", "24", "\u5357\u98ce", "\u5fae\u98ce", "19:44"],
14             "day": ["8", "\u4e2d\u96e8", "27", "\u5317\u98ce", "\u5fae\u98ce", "05:07"],
15             "night": ["8", "\u4e2d\u96e8", "22", "\u897f\u98ce", "\u5fae\u98ce", "19:44"]
16         }
17     }, {
18         "date": "2018-06-26",
19         "info": {
20             "dawn": ["8", "\u4e2d\u96e8", "22", "\u897f\u98ce", "\u5fae\u98ce", "19:44"],
21             "day": ["7", "\u5c0f\u96e8", "28", "\u5357\u98ce", "\u5fae\u98ce", "05:07"],
22             "night": ["1", "\u591a\u4e91", "22", "\u5357\u98ce", "\u5fae\u98ce", "19:44"]
23         }
24     }, {
25         "date": "2018-06-27",
26         "info": {
27             "dawn": ["1", "\u591a\u4e91", "22", "\u5357\u98ce", "\u5fae\u98ce", "19:44"],
28             "day": ["0", "\u6674", "37", "\u5357\u98ce", "\u5fae\u98ce", "05:08"],
29             "night": ["0", "\u6674", "24", "\u5317\u98ce", "3-5\u7ea7", "19:44"]
30         }
31     }, {
32         "date": "2018-06-28",
33         "info": {
34             "dawn": ["0", "\u6674", "24", "\u5317\u98ce", "3-5\u7ea7", "19:44"],
35             "day": ["0", "\u6674", "36", "\u4e1c\u5317\u98ce", "\u5fae\u98ce", "05:08"],
36             "night": ["1", "\u591a\u4e91", "21", "\u897f\u98ce", "\u5fae\u98ce", "19:45"]
37         }
38     }, {
39         "date": "2018-06-29",
40         "info": {
41             "dawn": ["1", "\u591a\u4e91", "21", "\u897f\u98ce", "\u5fae\u98ce", "19:45"],
42             "day": ["1", "\u591a\u4e91", "35", "\u4e1c\u5357\u98ce", "\u5fae\u98ce", "05:08"],
43             "night": ["1", "\u591a\u4e91", "22", "\u5357\u98ce", "\u5fae\u98ce", "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次夠玩了。

AJAX(七)jsonp實戰--天氣預報