php实现模拟登陆方正教务系统抓取课表


Posted in PHP onMay 19, 2015

课程格子和超级课程表这两个应用,想必大学生都很熟悉,使用自己的学号和教务系统的密码,就可以将自己的课表导入,随时随地都可以在手机上查看。

其实稍微了解一点php的话,我们也可以做一个类似这样的web 应用。

1,解决掉验证码

其实这是正方的一个小bug,当我们进入登陆界面时,浏览器会去请求服务器,服务器会生成一个验证码图片。如果我们不去请求这个图片,那么正方后台也不会生成相应的        验证码,于是这样我们就有了可乘之机,让我高兴会儿~这时,我们在不填写验证码的情况下,可以很流畅的进入。大家可以在自己的电脑上禁止访问验证码的地址,然后试试这        是不是真的~当然,这只对正方有效。

2,php 的curl 模拟登陆

接下来就是相关代码了,相信很多人和我一样,只喜欢看例子,对于长篇大论的讲解,转头就走……不过这个习惯还是不好……废话不多说!

//模拟登陆
  function curl_request($url,$post='',$cookie='', $returnCookie=0){
      $curl = curl_init();
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
      curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
      curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
      curl_setopt($curl, CURLOPT_REFERER, "这里一定要换成教务系统登陆的url"); //填写教务系统url
      if($post) {
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
      }
      if($cookie) {
        curl_setopt($curl, CURLOPT_COOKIE, $cookie);
      }
      curl_setopt($curl, CURLOPT_HEADER, $returnCookie);
      curl_setopt($curl, CURLOPT_TIMEOUT, 20);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
      $data = curl_exec($curl);
      if (curl_errno($curl)) {
        return curl_error($curl);
      }
      curl_close($curl);
      if($returnCookie){
        list($header, $body) = explode("\r\n\r\n", $data, 2);
        preg_match_all("/Set\-Cookie:([^;]*);/", $header, $matches);
        $info['cookie'] = substr($matches[1][0], 1);
        $info['content'] = $body;
        return $info;
      }else{
        return $data;
      }
  }

3,教务系统登陆页面的隐藏字段

举个栗子

<input type="hidden" name="__VIEWSTATE" value="dDwyODE2NTM0OTg7Oz61eIbnKVojBioGYtg2vsy2SklwiA==">

这些东西在登陆的时候也是需要带上的,顺便贴出函数,顺便暴漏了博主的学校……皇家种地大学(主要是正则表达式的运用)

//登陆页面的隐藏字段

function getView(){
  $url = 'http://jw.hzau.edu.cn/default2.aspx';
  $result = curl_request($url);
  $pattern = '/<input type="hidden" name="__VIEWSTATE" value="(.*?)" \/>/is';
  preg_match_all($pattern, $result, $matches);
  $res[0] = $matches[1][0];
     
  return $res[0] ;
}
//返回教室查询页面的隐藏值
private function getViewJs($cookie,$xh){
$url = "http://jw.hzau.edu.cn/xxjsjy.aspx?xh={$xh}";
$result = curl_request($url,'',$cookie);
$pattern = '/<input type="hidden" name="__VIEWSTATE" value="(.*?)" \/>/is';
preg_match_all($pattern, $result, $matches);
$res[0] = $matches[1][0];
return $res[0] ;
}

4,cookie 的获取

function login($xh,$pwd){
    $url = 'http://jw.hzau.edu.cn/default2.aspx';
    $post['__VIEWSTATE'] = $this->getView();
    $post['txtUserName'] = $xh; //填写学号
    $post['TextBox2'] = $pwd; //填写密码
    $post['txtSecretCode'] = '';
    $post['lbLanguage'] = '';
    $post['hidPdrs'] = '';
    $post['hidsc'] = '';
    $post['RadioButtonList1'] = iconv('utf-8', 'gb2312', '学生');
    $post['Button1'] = iconv('utf-8', 'gb2312', '登录');
    $result = curl_request($url,$post,'', 1);
    return $result['cookie'];
  }

5,让我们来试试查课表的功能,格式有点乱额,大家凑合着看,我把课表转成了一个二维关联数组

//返回课表字符串
private function classresult($xh,$pwd){
    date_default_timezone_set("PRC"); //时区设置
    $classList = "";//声明课表变量
 
    $cookie = $this->login($xh,$pwd);
    $view = $this->getViewJs($cookie,$xh);//验证密码是否正确
 
    //如果密码正确
    if (!empty($view)) {
      $url = "http://jw.hzau.edu.cn/xskbcx.aspx?xh={$xh}";
      $result = curl_request($url,'',$cookie); //保存的cookies
      preg_match_all('/<table id="Table1"[\w\W]*?>([\w\W]*?)<\/table>/',$result,$out);
      $table = $out[0][0]; //获取整个课表
 
      preg_match_all('/<td [\w\W]*?>([\w\W]*?)<\/td>/',$table,$out);
      $td = $out[1];
      $length = count($td);
 
      //获得课程列表
      for ($i=0; $i < $length; $i++) {
        $td[$i] = str_replace("<br>", "", $td[$i]);
 
        $reg = "/{(.*)}/";
       
        if (!preg_match_all($reg, $td[$i], $matches)) {
          unset($td[$i]);
        }
      }
 
      $td = array_values($td); //将课程列表数组重新索引
      $tdLength = count($td);
      for ($i=0; $i < $tdLength; $i++) {
        $td[$i] = iconv('GB2312','UTF-8',$td[$i]);
      }
 
      //将课表转换成数组形式
      function converttoTable($table){
        $list = array(
          'sun' => array(
            '1,2' => '',
            '3,4' => '',
            '5,6' => '',
            '7,8' => '',
            '9,10' => ''
          ),
          'mon' => array(
            '1,2' => '',
            '3,4' => '',
            '5,6' => '',
            '7,8' => '',
            '9,10' => ''
          ),
          'tues' => array(
            '1,2' => '',
            '3,4' => '',
            '5,6' => '',
            '7,8' => '',
            '9,10' => ''
          ),
          'wed' => array(
            '1,2' => '',
            '3,4' => '',
            '5,6' => '',
            '7,8' => '',
            '9,10' => ''
          ),
          'thur' => array(
            '1,2' => '',
            '3,4' => '',
            '5,6' => '',
            '7,8' => '',
            '9,10' => ''
          ),
          'fri' => array(
            '1,2' => '',
            '3,4' => '',
            '5,6' => '',
            '7,8' => '',
            '9,10' => ''
          ),
          'sat' => array(
            '1,2' => '',
            '3,4' => '',
            '5,6' => '',
            '7,8' => '',
            '9,10' => ''
          )
        );
        $week = array("sun"=>"周日","mon"=>"周一","tues"=>"周二","wed"=>"周三","thur"=>"周四","fri"=>"周五","sat"=>"周六");
        $order = array('1,2','3,4','5,6','7,8','9,10');
        foreach ($table as $key => $value) {
          $class = $value;
          foreach ($week as $key => $weekDay) {
            $pos = strpos($class,$weekDay);
            // echo $pos;
            if ($pos) {
              $weekArrayDay = $key; //获取list数组中的第一维key
              foreach ($order as $key => $orderClass) {
                $pos = strpos($class,$orderClass);
                if ($pos) {
                  $weekArrayOrder = $orderClass; //获取该课程是第几节
                  break;
                }
              }
              break;
            }
          }
          $list[$weekArrayDay][$weekArrayOrder] = $class;
        }
        return $list;
      }
           
      //调用函数
      return converttoTable($td);
    }else{
      return 0;
    }
  }

6,再试试查询空教室的功能

//空教室查询结果
  public function roomresult(){
    $xh = ""; //设置学号
    $pwd = ""; //学号对应的密码
 
    $cookie = $this->login($xh,$pwd);
    $url = "http://jw.hzau.edu.cn/xs_main.aspx?xh={$xh}";
    $result = curl_request($url,'',$cookie); //保存的cookies
 
    $url="http://jw.hzau.edu.cn/xxjsjy.aspx?xh={$xh}";
    $post['Button2'] = iconv('utf-8', 'gb2312', '空教室查询');
    $post['__EVENTARGUMENT']='';
    $post['__EVENTTARGET']='';
    $post['__VIEWSTATE'] = $this->getViewJs($cookie,$xh);
    $post['ddlDsz'] = iconv('utf-8', 'gb2312', '单');
    $post['ddlSyXn'] = '2014-2015'; //学年
    $post['ddlSyxq'] = '1';
    $post['jslb'] = '';
    $post['xiaoq'] = '';
 
    $post['kssj']=$_GET['start']; //提交的开始查询时间 
    $post['sjd']=$_GET['class'];//提交的课程节次
 
    $post['xn']='2014-2015';//所在学年
    $post['xq']='2';//所在学期
    $post['xqj']='6';//当天星期几
    $post['dpDataGrid1:txtPageSize']=90;//每页显示条数
 
    $result = curl_request($url,$post,$cookie,0);
     
    preg_match_all('/<span[^>]+>[^>]+span>/',$result,$out);
    $tip = iconv('gb2312', 'utf-8', $out[0][3]);//获取页面前部的提示内容
    preg_match_all('/<table[\w\W]*?>([\w\W]*?)<\/table>/',$result,$out);
    $table = iconv('gb2312', 'utf-8', $out[0][0]); //获取查询列表
     
    $this->load->view("classroom",array('tip'=>$tip,'table'=>$table));
  }

总结起来就是这些了,每个学校的教务系统都不尽相同,这时我们可以借助火狐浏览器的 firebug 抓包,看看到底提交了哪些东西。

以上所述就是本文的全部内容了,希望大家能够喜欢。

PHP 相关文章推荐
如何对PHP程序中的常见漏洞进行攻击(下)
Oct 09 PHP
php gd2 上传图片/文字水印/图片水印/等比例缩略图/实现代码
May 15 PHP
php checkbox 取值详细说明
Aug 19 PHP
php入门学习知识点三 PHP上传
Jul 14 PHP
PHP仿博客园 个人博客(2) 数据库增添改删
Jul 05 PHP
php判断页面是否是微信打开的示例(微信打开网页)
Apr 25 PHP
php快递单号查询接口使用示例
May 05 PHP
php 购物车完整实现代码
Jun 05 PHP
PHP图片处理之使用imagecopy函数添加图片水印实例
Nov 19 PHP
老生常谈PHP 文件写入和读取(必看篇)
May 22 PHP
php实现简单的权限管理的示例代码
Aug 25 PHP
PHP命名空间与自动加载机制的基础介绍
Aug 25 PHP
PHP IDE phpstorm 常用快捷键
May 18 #PHP
PHP网络操作函数汇总
May 18 #PHP
PHP面向对象之后期静态绑定功能介绍
May 18 #PHP
php中关于socket的系列函数总结
May 18 #PHP
php简单socket服务器客户端代码实例
May 18 #PHP
php实现粘贴截图并完成上传功能
May 17 #PHP
php获取json数据所有的节点路径
May 17 #PHP
You might like
PHP+AJAX实现无刷新注册(带用户名实时检测)
2006/12/02 PHP
php 注册时输入信息验证器的实现详解
2013/07/05 PHP
理清PHP在Linxu下执行时的文件权限方法
2017/06/07 PHP
PHP去除空数组且数组键名重置的讲解
2019/02/28 PHP
Javascript调试工具(下载)
2007/01/09 Javascript
脚本之家贴图转换+转贴工具用到的js代码超级推荐
2007/04/05 Javascript
弹出广告特效(一个IP只弹出一次)的代码
2007/07/27 Javascript
dwr spring的集成实现代码
2009/03/22 Javascript
网站导致浏览器崩溃的原因总结(多款浏览器) 推荐
2010/04/15 Javascript
JQuery Tips相关(1)----关于$.Ready()
2014/08/14 Javascript
JS判断字符串字节数并截取长度的方法
2016/03/05 Javascript
JavaScript String 对象常用方法总结
2016/04/28 Javascript
jQuery中DOM节点删除之empty与remove
2017/01/20 Javascript
详解angularjs结合pagination插件实现分页功能
2017/02/10 Javascript
JS实现带导航城市列表以及输入搜索功能
2018/01/04 Javascript
js脚本中执行java后台代码方法解析
2019/10/11 Javascript
JavaScript日期库date-fn.js使用方法解析
2020/09/09 Javascript
Vue 实现拨打电话操作
2020/11/16 Javascript
JavaScript实现筛选数组
2021/03/02 Javascript
Python正则表达式实现截取成对括号的方法
2017/01/06 Python
对Python 文件夹遍历和文件查找的实例讲解
2018/04/26 Python
django 删除数据库表后重新同步的方法
2018/05/27 Python
使用Python计算玩彩票赢钱概率
2019/06/26 Python
python ubplot使用方法解析
2020/01/10 Python
详解Scrapy Redis入门实战
2020/11/18 Python
pycharm 使用tab跳出正在编辑的括号(){}{}等问题
2021/02/26 Python
Mybag美国/加拿大:英国奢华包包和名牌手袋网站
2020/02/16 全球购物
宏碁西班牙官网:Acer西班牙
2021/01/08 全球购物
涉外经济法专业毕业生推荐信
2013/11/24 职场文书
大学生求职自荐信
2013/12/12 职场文书
对孩子的寄语
2014/04/09 职场文书
财务会计求职信范文
2015/03/20 职场文书
python 实现德洛内三角剖分的操作
2021/04/22 Python
Python入门学习之类的相关知识总结
2021/05/25 Python
Redis实战高并发之扣减库存项目
2022/04/14 Redis
Docker与K8s关系介绍不会Docker也可以使用K8s
2022/06/25 Servers