上一篇提到CURL。咱们这一篇来玩玩它。
CURL 是什么呢?
CURL有什么用?
咱们今天通过CURL模拟登陆教务系统查成绩来学习一下这个函数。
今天要实现的功能是:通过微信查成绩。
原理:
怎么实现的呢?
就是模拟登陆。什么是模拟登陆?通俗一点的说法就是,模拟咱们的浏览器去登陆咱们的教务系统。怎么实现登陆的呢。这就得用到CURL类的函数了。下面我们来看看原理图。
![这里写图片描述](https://img-blog.csdn.net/20150801154152948)
现在我们模拟登陆教务系统,把成绩抓过来再返回给我们的手机。
![原理](https://img-blog.csdn.net/20150801154340651)
正常情况下我们查成绩是登陆教务系统网站,输入学号和密码,登陆成功,然后点击查看成绩。今天我们要实现的就是模拟浏览器发送账号密码并取回成绩。大家知道,浏览器有两种传值方法GET和POST。(有的说有3种,有一种不常用)GET方法就是通过URL传值,一般我们是可以在地址栏看得到的。就是这种形式http://www.baidu.com?word=“xxxx”。POST传值一般我们是看不到的,但是我们可以通过抓包看得到。做模拟登录最重要的就是保存cookie。cookie是一种会话技术,http连接是一种无状态的连接,网站不知道是谁发送的请求,需要一种标识来记录用户身份。Cookie是由教务系统服务器端生成,发送给浏览器,浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求教务系统网站时就发送该Cookie给服务器。Cookie名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等,服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。所以咱们发送完数据的时候记得保存cookie。到时候咱们再请求页面的时候直接发送cookie就可以了。
下面我以中南民族教务系统演示一下抓包。
打开中南民族大学教务系统首页,输入学号和密码。
在点击登陆之前按下F12,我们通过谷歌浏览器自带的这个抓包就可以了。当然你也可以用你习惯的抓包工具。F12,在上面一栏点击NetWork。![这里写图片描述](https://img-blog.csdn.net/20150801160718361)
点击登陆,然后注意看看下面控制台的变化。
咱们一点击登陆,浏览器就发了这么多请求,到底哪个是咱们想要的呢请求呢?找到第一条POST请求。右键,我们看看浏览器发了什么给教务系统系统服务器。
看图中的1和2是我的账号密码,浏览器就是把DATA下面的数据通过POST形式发送给教务系统服务器的。下面我们通过代码来模拟浏览器的行为。
右键第一条POST请求,选择Copy as CURL。
把复制出来的东西粘贴到编辑器里,待会会用到。
curl开头的这一行是我们请求的地址。
-H开头的都是请求头。
-data开头的是我们要模拟发送的数据。
这里我们只需要留:curl和-data开头的就行了。
curl:
http://ids.scuec.edu.cn/amserver/UI/Login
–data :”IDToken0=&IDToken1=我的账号&IDToken2=我的密码&IDButton=Submit&goto=aHR0cDovL215LnNjdWVjLmVkdS5jbi9pbmRleC5wb3J0YWw”%”3D&encoded=true&gx_charset=UTF-8”
这时可以清空控制台下面的请求了。待会继续看成绩的页面也抓包,主要是为了获取成绩页面的URL地址。这里说明一下:我这里不是直接进的教务系统,而是进的信息门户,信息门户集成了中门民族大学的大部分系统。中南民族大学教务系统有验证码,模拟登录起来比较麻烦,所以我就绕道而行,如果以后把自动识别验证码做出来的话,可以直接从这里模拟登录。不过有学校的教务系统有漏洞,不用验证码也可成功登录。带验证码登录的我也做过,就是靠人工识别,自己写程序识别识别率不是很高,经常导致模拟登录失败。废话不多说了。咱们把请求成绩的URL地址找出来。你根据你自己的情况来。我这里是先跳转到中南民族大学教务系统,跳转的时候需要再保存一次cookie。然后再点击请求成绩页面。
这两个URL地址在地址栏就可以复制出来。
新建一个test.php文件,咱们用CURL来模拟浏览器登录教务系统:记得保存cookie。
来说一下这个CURL类。
CURL基本的使用方法:
1.初始化,创建一个新cURL资源
2.设置URL和相应的选项
3.抓取URL并把它传递给浏览
4.关闭cURL资源,并且释放系统资源
直接上代码,代码里有注释。
<?php
/*
* 查成绩功能
*
*/
$username="你的账户";
$password="你的密码";
$cookie_file = tempnam('./temp','cookie');
// $cookie_file = tempnam(SAE_TMP_PATH, 'cookie');//在SAE下用这个
$login_url ='http://ids.scuec.edu.cn/amserver/UI/Login';//信息门户登陆地址
$post_fields ="encoded=true&goto=aHR0cDovL215LnNjdWVjLmVkdS5jbi9pbmRleC5wb3J0YWw=&gx_charset=UTF-8&IDButton=Submit&IDToken0=&IDToken1=".$username."&IDToken2=".$password;//这是post的数据
$ch = curl_init($login_url);//初始化
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//这儿参数1,不输出,后面如果有输出函数也能输出页面
curl_setopt($ch, CURLOPT_POST, 1);//使用的是post方法,参数为1
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);//需要post的数据
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);//这句的作用就是保存cookie
$content=curl_exec($ch);
curl_close($ch);
//模拟登陆教务系统
$url='http://ssfw.scuec.edu.cn/ssfw/j_spring_ids_security_check';//这是转到教务系统页面
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);//这里会用到前面保存的cookie
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
$contents = curl_exec($ch); //执行,得到是字符串,赋值给contents,$contents变量的类型是string
// print_r($contents);
//die;
//成绩查询页面
$url='http://ssfw.scuec.edu.cn/ssfw/zhcx/cjxx.do';//这次请求的就是成绩页面
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);//这里会用到前面保存的cookie
$contents = curl_exec($ch);
curl_close($ch);
print_r($contents);
运行一下这个文件,看看,已经可以抓到成绩的页面了,咱们再成正则表达式把我们需要的内容提取出来。咱们只需要这个学期的成绩。好,继续加代码。
<?php
/*
* 查成绩功能
*
*/
//header('Content-Type: text/html; charset=UTF-8');
function chengji($username,$password){
//$cookie_file = tempnam('./temp','cookie');
$cookie_file = tempnam(SAE_TMP_PATH, 'cookie');//在SAE下用这个
$login_url ='http://ids.scuec.edu.cn/amserver/UI/Login';//信息门户登陆地址
$post_fields ="encoded=true&goto=aHR0cDovL215LnNjdWVjLmVkdS5jbi9pbmRleC5wb3J0YWw=&gx_charset=UTF-8&IDButton=Submit&IDToken0=&IDToken1=".$username."&IDToken2=".$password;//这是post的数据
$ch = curl_init($login_url);//初始化
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//这儿参数1,不输出,后面如果有输出函数也能输出页面
curl_setopt($ch, CURLOPT_POST, 1);//使用的是post方法,参数为1
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);//需要post的数据
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);//这句的作用就是保存cookie
$content=curl_exec($ch);
curl_close($ch);
//模拟登陆教务系统
$url='http://ssfw.scuec.edu.cn/ssfw/j_spring_ids_security_check';//这是转到教务系统页面
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);//这里会用到前面保存的cookie
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
$contents = curl_exec($ch); //执行,得到是字符串,赋值给contents,$contents变量的类型是string
curl_close($ch);
//成绩查询页面
$url='http://ssfw.scuec.edu.cn/ssfw/zhcx/cjxx.do';//这次请求的就是成绩页面
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);//这里会用到前面保存的cookie
$contents = curl_exec($ch);
if(!empty($contents))
{
$match="|(<=<td>).*(?=</td>)|";
preg_match_all( '/<table class="table_con" base="color3" width="100%" border="0" align="center" cellpadding="0" cellspacing="0">[^>]*>([\s\S]*?)<\/table>/', $contents, $mycontents);//正则匹配成绩那一表格
$arr = get_td_array($mycontents[0][0]);
array_shift($arr);
array_pop($arr);
$result="-------------我的成绩---------------\n";
if(count($arr)>0){
for($i=0;$i<count($arr);$i++){
$result .=trim($arr[$i][3]);
$result .= trim($arr[$i][7])."\n";
}
}else{
$result= "您的考试成绩还没出来哦O(∩_∩)O~";
}
}else{
$result= "登陆教务系统失败!!!";
}
return $result;
}
function get_td_array($table) {
$table = preg_replace("'<table[^>]*?>'si","",$table);
$table = preg_replace("'<tr[^>]*?>'si","",$table);
$table = preg_replace("'<td[^>]*?>'si","",$table);
$table = str_replace("</tr>","{tr}",$table);
$table = str_replace("</td>","{td}",$table);
//去掉 HTML 标记
$table = preg_replace("'<[/!]*?[^<>]*?>'si","",$table);
//去掉空白字符
$table = preg_replace("'([rn])[s]+'","",$table);
$table = preg_replace('/ /',"",$table);
$table = str_replace(" ","",$table);
$table = str_replace(" ","",$table);
$table = explode('{tr}', $table);
//array_pop($table);
foreach ($table as $key=>$tr) {
$td = explode('{td}', $tr);
//array_pop($td);
$td_array[] = $td;
}
return $td_array;
}
到这里咱们的成绩处理就处理完了。根据你的情况处理成绩。
现在我们把他接入微信。
新建一个index.php文件
把上面的成绩页面引进来。
$keywords = explode("+",$keyword);
$username=$keywords[1];
$password= $keywords[2];
$contentStr=chengji($username,$password);
“`
58行的这断是把微信发过来的消息拆分,我们约定查询的格式为:成绩+学号+密码。当然你也可以存到数据库里,查询的时候先要求绑定学号,然后再从数据库里面查询。这里我们就直接拆分为三个字段了。
好,把代码打包上传到SAE。咱们来测试一把。
成功了。完整代码包下载:点击下载
查询课表,查询考试安排的原理也是一样的。有什么问题联系我,QQ648988391。QQ交流群:429207338