最近遇到一个需求,需要做一个网页实现停电查询的功能。
我建站使用的是快站,但是请求数据的来源来自于国家电网。快站(https://www.kuaizhan.com/)使用的协议是使用 ssl 加密的 https 国家电网(http://www.95598.cn/)使用的是http 二者协议不同没有办法通信,使用 ajax 时会报错。
于是我改为自己写一个网站,然后网站采用http协议。在使用国家电网查询信息的时候,打开控制台,分析报文,发现95598(电网)使用json来传输数据,这为我的需求解决提供了可能性,我也可以使用ajax发送get/post请求报文来获取json数据。
在网页中使用$.ajax 获取数据代码如下
$.ajax({
type:"get",
url:"http://www.95598.cn/95598/outageNotice/queryOutageNoticeList?orgNo=51412&outageStartTime=2017-08-16&outageEndTime=2017-08-23&scope=&provinceNo=51101&typeCode=&lineName=&anHui=02",
async:true,
success:function(data){
if(data.query.results) {
//$("#outage").text(JSON.stringify(data.query.results));
var J_data = JSON.parse(JSON.stringify(data.query.results));
//alert(J_data.json.today);
messageStr(J_data.json);
} else {
$("#content").text('no such code: ' + code);
}
}
});
然后报错,错误如下
错误的意思是不可以请求非同源的数据,除非请求源的头部添加了,Access-Control-Allow-Origin:* 这样其他对象可以来请求数据。
后台不在我这里,我没有办法在网站中添加 Access-Control-Allow-Origin,所以这时候要采用其他办法
$(document).ready(function(){
var url='http://localhost:8080/WorkGroupManagment/open/getGroupById"
+"?id=1&callback=?';
$.ajax({
url:url,
dataType:'jsonp',
processData: false,
type:'get',
success:function(data){
alert(data.name);
},
error:function(XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus);
}});
});
1.在请求中要 dataType:'json' ==> dataType:'jsonp'
2.在返回的数据方面 json :
{
"message":"获取成功",
"state":"1",
"result":{"name":"工作组1","id":1,"description":"11"}
}
callback({
"message":"获取成功",
"state":"1",
"result":{"name":"工作组1","id":1,"description":"11"}
})
jsonp比json多了一个回调函数的函数名,因为二者工作方式不同,AJAX其实是XMLHttpRequest 请求来实现异步加载数据,而jsonp原理相当于加载一段js代码在获取数据的同时返回了js对象,这样就可以直接使用callback。但是这样方式并不适合我使用,所以继续去找下一种解决办法
HTML5中提供的XMLHTTPREQUEST Level2(及XHR2)已经实现了跨域访问。但ie10以下不支持
只需要在服务端填上响应头:
header("Access-Control-Allow-Origin:*");
/*星号表示所有的域都可以接受,*/
header("Access-Control-Allow-Methods:GET,POST");
这种我没有试过,因为我并没有服务端。而且这种方案也不能帮助我解决需求
雅虎的Yahoo Query Language (YQL)通过它可以把 Web 上的各种数据服务作为数据库表来查询,并获得结果。
通过yql服务, 可以把https://openapi.baidu.com/api的内容再次封装, 还可以把接口返回的内容, 再次使用sql语句查询, 然后再通过yql服务返回最终结果
例
$.getJSON("http://query.yahooapis.com/v1/public/yql?q=select * from json where url=\"http://www.95598.cn/95598/outageNotice/queryOutageNoticeList?orgNo=51412&outageStartTime=2017-08-16&outageEndTime=2017-08-23&scope=&provinceNo=51101&typeCode=&lineName=&anHui=02\"", function (data) {
console.log(data);
});
到这就结束了, 已经能在控制台输出结果了
这个解决方案不好的一点就是又通过了一次yql, 等于是yql先拿到结果, 然后又到浏览器, 中转了一次, 好的一点是不用自己再去动服务器代码
虽然用这个方法,我获取到了停电信息,但是部门等信息我却没办法获得,因为这种办法只适合把参数写在url中get请求,对于post请求无能为力。
var ajax = require('./public/javascripts/express_demo');
app.use('/95598',ajax);
当浏览器有95598的请求就会转发给express_demo.js
// 一级单位获取POST 请求
router.post('/region/findOrgList', function (req, res) {
console.log("post for org list");
//不能正确解析json 格式的post参数
var body = '',jsonStr;
req1 = http.request(options, (res1) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res1.headers)}`);
res1.setEncoding('utf8');
res1.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
body += `${chunk}`; //读取参数流转化为字符串
console.log('\n\n\n body------------'+body);
}).on('end', () => {
console.log('No more data in response.');
console.log(res1.headers);
console.log('body');
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(body);
}).on('error', (e) => {
console.error(`problem with request: ${e.message}`);
})
});
// write data to request body
req1.write(postData);
req1.end();
//console.log('\n\n\n before send body------------'+body);
})
我这里做的有点复杂,在获取请求的同时向95598发送了同样的请求,用代理会简便很多,但是这样其实也有好处,可以定制不同的请求头,也可以处理数据,实际上也只起到了一个代理的作用。
[{"value":"北京市电力公司","code":"11102","codeType":"02","pcode":null},{"value":"国网天津市电力公司","code":"12101","codeType":"02","pcode":null},{"value":"河北省电力公司","code":"13102","codeType":"02","pcode":null},{"value":"山西省电力公司","code":"14101","codeType":"02","pcode":null},{"value":"内蒙古东部电力有限公司","code":"15101","codeType":"02","pcode":null},{"value":"辽宁省电力有限公司","code":"21102","codeType":"02","pcode":null},{"value":"吉林省电力有限公司","code":"22101","codeType":"02","pcode":null},{"value":"黑龙江省电力有限公司","code":"23101","codeType":"02","pcode":null},{"value":"上海市电力公司","code":"31102","codeType":"02","pcode":null},{"value":"江苏省电力公司","code":"32101","codeType":"02","pcode":null},{"value":"浙江省电力公司","code":"33101","codeType":"02","pcode":null},{"value":"安徽省电力公司","code":"34101","codeType":"02","pcode":null},{"value":"福建省电力有限公司","code":"35101","codeType":"02","pcode":null},{"value":"江西省电力公司","code":"36101","codeType":"02","pcode":null},{"value":"山东省电力公司","code":"37101","codeType":"02","pcode":null},{"value":"河南省电力公司","code":"41101","codeType":"02","pcode":null},{"value":"湖北省电力公司","code":"42102","codeType":"02","pcode":null},{"value":"湖南省电力公司","code":"43101","codeType":"02","pcode":null},{"value":"重庆市电力公司","code":"50101","codeType":"02","pcode":null},{"value":"四川省电力公司","code":"51101","codeType":"02","pcode":null},{"value":"西藏自治区电力有限公司","code":"54101","codeType":"02","pcode":null},{"value":"陕西省电力公司","code":"61102","codeType":"02","pcode":null},{"value":"甘肃省电力公司","code":"62101","codeType":"02","pcode":null},{"value":"青海省电力公司","code":"63101","codeType":"02","pcode":null},{"value":"宁夏区电力公司","code":"64101","codeType":"02","pcode":null},{"value":"新疆区电力公司","code":"65101","codeType":"02","pcode":null},{"value":"冀北电力公司","code":"66103","codeType":"02","pcode":null}]