Angular+Node+Python快速建站
Augular+Node+Python搭建网站的历程
AJ+NJ搭建一个小网站的例子数不胜数,我也不费力去说。这篇文章假设大家已经对以上提到的语言有一定基础。我把自己再搭建过程中的想法、遇到的一些问题以及部分问题的解决的方法记录下来,希望对大家有帮助。
想法:最近写了一个小小的用来查询自己学校选修课成绩的Python脚本(具体可以见上一篇博客),有人说很实用,但是会觉得用程序查询过于麻烦,不够直观。希望能改善成一个网页,供大家使用。于是乎,正逢软件工程大作业,我决定将大家的想法实(随)现(便)一(玩)下(玩)。我本来希望能够使用node来搭建起全部的后端。但是由于自己不愿意多花精力重写一遍和之前Python脚本同样功能的代码,于是我选择在node中调用Python脚本。(想了解node-python的也可以继续看一下)。前端页面使用了Bootstrap+AngularJS来实现,为的是可响应的布局。
流程:首先呢看过上一篇博客的话知道,教务网会有一个验证码,那么我们需要将这个验证码显示到自己的网页中。有人会说,那不是很简单?一个![](bkjw/captchaImage)
不就可以完成了。但事实并不是如此,我们不仅要获得验证码图片,还要携带一个用于登陆的cookie。那么这样的想法仅仅靠src这个属性就不能够做到了。而且觉得如果使用AngularJS的$http进行请求的话涉及到跨域,并且我不能够去修改教务网站,一定会失败。最后我决定在后端使用暴露一个接口 /getimage,用来返回图片并记录相应cookie。于是呢我在node中添加了一个路由。
if (path == '/getimage'){
request('http://jwc.xxx.edu.cn/bkjw',function(err,res1,body){
header = res1.headers;
console.log(header['set-cookie'].toString());
var mycookie = header['set-cookie'].toString().split(";")[0];
console.log(mycookie);
u_m[arg_uuid] = mycookie;
console.log(u_m);
var options = {
url : 'http://jwc.xxx.edu.cn/bkjw/captchaImage',
method : 'GET',
headers : {'Cookie':mycookie}
};
request(options).pipe(res);
});
}
上述代码完成的工作就是获取cookie并根据相应cookie去请求验证码图片。而对应的cookie保存在了数组中。那么此步骤完成之后,我们在网页中就可以通过指定 <img src = '/getimage'>
来获得验证码图片了。但是接下来我们以后的操作要用到请求图片时所得到cookie,而我们上一步仅仅是将起保存在了u_m这个数组中。所以我们仍需定制一个路由用来返回cookie。
if (path == '/getcookie'){
res.end(u_m[arg_uuid]);
}
这个就很好理解了,返回数组中对应uuid的那一项。(每个用户在刚刚打开网页的时候都会获得一个uuid,uuid是唯一标识,以这个uuid代替你,那么以后查找属于你的cookie的时候,直接查找对应的uuid就可以了,嗯相当于一个临时身份证)。那么现在呢,我们在AngularJS上就可以通过$http的get请求来获取cookie了,但是现在呢出现了一个问题。
如果我们用来请求数据的后端程序和用来浏览的前端web项目都运行在同一个端口的话(或者说,express.static开启的静态服务器,与其他比如/getimage等这些路由都监听在8080端口的话)互相访问是没有问题的。但有的人会选择在一个端口开启静态服务器(用于web项目的访问),而在另外一个端口开启后端服务。一旦这样的话,前端页面AngularJS的请求就会因为跨域访问而失效,下面一个简单的办法解决掉这个问题
res.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8088")
那么只需要在服务器的响应流中添加一个响应头属性Access-Control-Allow-Origin,就搞定了,是不是很简单地就解决了跨域访问的限制了!
接下来我们聊一聊如何将node与python连接起来呢。网上也有很多方案,这里我们就说最简单的,通过系统的输入输出流来进行调用
import sys
studentId = sys.argv[1]
password = sys.argv[2]
x = sys.argv[3]
img_cookie = sys.argv[4]
我们在python中引入sys模块,通过sys.argv的方式获得传入参数。其中为什么第一个参数的下标从1开始呢?我们现来看看一看在node中如何调用python并传入参数。
exec('python htt.py '+stdid+' '+stdpwd+' '+yzm+' '+cookie,function(err,stdout,stderr){
if(err)
{
res.end('出错啦,请重新尝试');
console.log('stderr',err);
}else if(stdout)
{
console.log('py Result:-----------------------');
console.log(stdout);
res.end(stdout);
}
});
我们在node中通过exec('python 脚本名.py 参数1 参数2 参数3...',FUN()),所以说我们获取参数的argv数组第0个是脚本名字,而参数1从角标1开始。
我们在掌握以上的要点之后就可以对上一篇博客中的python脚本进行改造,原本我们需要联网获得的验证码图片,cookie,以及输入全部替换成参数的形式,最终提交到教务网服务器,并返回结果。
在我们完成以上步骤之后,我们就可以在AngularJS中通过/getcookie路由成功获得cookie之后,将表单信息整理成学号、密码、输入验证码,cookie,并提交到路由,后端路由将参数解析,并请求教务网返回结果。返回的结果在包装成html格式,返回给AngularJS,AngularJS获得输入流之后,最终渲染页面,更新绑定值,显示结果。
最后一步呢,我们不管是请求成功还是不成功,都得重新刷新验证码,以便与用户继续查询。同时人性化设计,如果用户看不清验证码那么要有更换图片的功能。于是我们将获取验证码的代码提取成一个模块changePic()
changePic = function(){
a = new Date().getTime();
document.getElementById("yzmimg").src = "http://127.0.0.1:8080/getimage?uuid=" + a;
}
搞定之后我们的功能就大致实现了。增加一些错误的捕捉,检查。最后我将这个小网站挂在了阿里云上,测试效果不错。这里就不贴网址了,小小菜鸟,怕大佬来攻击我 /笑哭!