首先简单的说下表单的原理:当我们输入学号、密码、验证码,点击提交时会产生一个post请求,服务器在接收到post请求时会检查提交上来的学号、密码、验证码是否正确,正确则登陆成功。
在之前看到很多文章说模拟登陆正方时可以不输入验证码,博主亲自试了一下,无奈博主大学的正方系统更新的快,这一漏洞已经被填补了。所以只能老老实实的输验证码了…
接下来步入正题:
第一步,抓包
打开谷歌浏览器访问学校教务处网址,按F12选择network,之后在正方里填上你的学号,密码,验证码,登录,看看这期间提交的数据。
我们要用到的数据只有default2.aspx和xs_main.aspx?xh=”你的学号”这两个,其余的都是修饰用的css文件。点开default2.aspx可以看到你提交的表单数据。
其中__VIEWSTATE是asp.net服务器的状态信息,需要抓取出来。
另外default2.aspx这个页面采用了302跳转,即登录成功后会跳转到xs_main.aspx?xh=”你的学号”这个网址,这一点可能是大多数人模拟登录失败的原因。
第二步,构造登录页面
三项信息必填,学号、密码、验证码。先说说验证码怎么保存到本地。
验证码是由一个叫checkcode.aspx的网页生成的,要保存可以用fwrite
来实现。有同鞋可能会说,直接用<img src=""
填上刚才的网址不行么?理论上可以,只要你能保存下这张图片所对应的cookie,这个cookie决定了你是否能够进行后续数据抓取。
具体代码如下:
首先要新建一个cookie文件夹,并且把session打开(可以解决高并发访问时登陆失败的问题)。
1 |
|
验证码保存:
1 |
|
之后构造input
表单,设置好name
第三步,后端模拟登录页面
1 |
|
如果你之前代码都正确的话,可以看到如下熟悉的界面:
出来这个界面就说明你已经成功了一半。接下来我们去抓取考试成绩的数据。
第四步,后端成绩查询
博主正方更新后成绩查询是酱婶儿的(是不是暴露了什么T_T):
老办法,抓包。
选好学年、学期,点学期成绩之前,打开开发者工具–network
成绩查询的url组成是http://教务处地址/xscjcx.aspx?xh=学号&xm=姓名&gnmkdm=XXX
gnmkdm是个固定值,干什么用博主也不知道。不过查询的时候可以不带这个参数,直接http://教务处地址/xscjcx.aspx?xh=学号&xm=姓名 就可以
那么问题来了,姓名从哪来?还记得刚才登录成功那个界面么,我们可以用正则表达式提取姓名。
1 | preg_match_all('/<span id="xhxm">([^<>]+)/', $con, $xm); //正则出的数据存到$xm数组中 |
之后查看post数据,这次多了好多。注意:再次抓取VIEWSTATE字段。
要正则的页面:http://教务处地址/xscjcx.aspx?xh=学号&xm=姓名 (点了成绩查询后的页面)
正则表达式:
1 | $url2="http://210.44.176.46/xscjcx.aspx?xh=".$_SESSION['xh']."&xm=".$xm[1][0]; |
Post数据:
1 | $post=array( |
模拟登录:
1 | $content=login_post($url2,$cookie,http_build_query($post)); |
一切正常的话就会看到下面的界面:
如果想去掉多余的字段,可以用正则表达式:
1 | preg_match_all('/<td>([^<>]+)/', $content, $cj); |
就是这样简单,快去试试吧!