一、案例
本次要做的案例的是使用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实战--天气预报
原文地址:https://www.cnblogs.com/ldq678/p/9748904.html