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 相关文章推荐
NT IIS下用ODBC连接数据库
Oct 09 PHP
PHP array_push 数组函数
Dec 26 PHP
PHP中几个常用的魔术常量
Feb 23 PHP
关于php程序报date()警告的处理(date_default_timezone_set)
Oct 22 PHP
php inc文件使用的风险和注意事项
Nov 12 PHP
Laravel 5框架学习之子视图和表单复用
Apr 09 PHP
CI映射(加载)数据到view层的方法
Mar 28 PHP
PHP实现路由映射到指定控制器
Aug 13 PHP
php mongodb操作类 带几个简单的例子
Aug 25 PHP
php抛出异常与捕捉特定类型的异常详解
Oct 26 PHP
php变量与数组相互转换的方法(extract与compact)
Dec 02 PHP
php传值和传引用的区别点总结
Nov 19 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入门速成教程
2007/03/19 PHP
php下获取客户端ip地址的函数
2010/03/15 PHP
Yii2使用小技巧之通过 Composer 添加 FontAwesome 字体资源
2014/06/22 PHP
PHP中include/require/include_once/require_once使用心得
2016/08/28 PHP
laravel 去掉index.php伪静态的操作方法
2019/10/12 PHP
JavaScript 高效运行代码分析
2010/03/18 Javascript
JQuery获取浏览器窗口内容部分高度的代码
2012/02/24 Javascript
javascript 基础篇2 数据类型,语句,函数
2012/03/14 Javascript
nodeType属性返回被选节点的节点类型介绍
2013/11/22 Javascript
require.js+vue开发微信上传图片组件
2016/10/27 Javascript
javascript判断firebug是否开启的方法
2016/11/23 Javascript
Vue 过渡(动画)transition组件案例详解
2017/01/22 Javascript
详解ES6之用let声明变量以及let loop机制
2017/07/15 Javascript
react-router v4如何使用history控制路由跳转详解
2018/01/09 Javascript
Bootstrap实现的表格合并单元格示例
2018/02/06 Javascript
Vue 中使用vue2-highcharts实现曲线数据展示的方法
2018/03/05 Javascript
详解Ubuntu安装angular-cli遇到的坑
2018/09/08 Javascript
vue服务端渲染页面缓存和组件缓存的实例详解
2018/09/18 Javascript
如何用Node写页面爬虫的工具集
2018/10/26 Javascript
浅谈JS中this在各个场景下的指向
2019/08/14 Javascript
JavaScript实现电灯开关小案例
2020/03/30 Javascript
python多线程socket编程之多客户端接入
2017/09/12 Python
快速解决pandas.read_csv()乱码的问题
2018/06/15 Python
Python网页正文转换语音文件的操作方法
2018/12/09 Python
Python-numpy实现灰度图像的分块和合并方式
2020/01/09 Python
Python多线程Threading、子线程与守护线程实例详解
2020/03/24 Python
在 Windows 下搭建高效的 django 开发环境的详细教程
2020/07/27 Python
关于python中remove的一些坑小结
2021/01/04 Python
伦敦著名的运动鞋综合商店:Footpatrol
2019/03/25 全球购物
法学毕业生自我鉴定
2013/11/08 职场文书
前台文员岗位职责
2013/12/28 职场文书
副处级干部考察材料
2014/05/17 职场文书
协商一致解除劳动合同协议书
2014/09/14 职场文书
社区党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
参观邀请函范文
2015/02/02 职场文书
2015个人年度工作总结范文
2015/05/28 职场文书