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编程最快明白》第二讲 数字、浮点、布尔型、字符串和数组
Nov 01 PHP
8个出色的WordPress SEO插件收集
Feb 26 PHP
Warning: session_destroy() : Trying to destroy uninitialized sessionq错误
Jun 16 PHP
PHP写的获取各搜索蜘蛛爬行记录代码
Aug 21 PHP
php上传apk后自动提取apk包信息的使用(示例下载)
Apr 26 PHP
PHP实现生成唯一编号(36进制的不重复编号)
Jul 01 PHP
PHP中使用strpos函数实现屏蔽敏感关键字功能
Aug 21 PHP
php实现网站文件批量压缩下载功能
Oct 28 PHP
PHP二维数组去重算法
Dec 17 PHP
thinkPHP中钩子的使用方法实例分析
Nov 16 PHP
详解PHP的抽象类和抽象方法以及接口总结
Mar 15 PHP
laravel框架中视图的基本使用方法分析
Nov 23 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制作图型计数器的例子
2006/10/09 PHP
php中get_meta_tags()、CURL与user-agent用法分析
2014/12/16 PHP
thinkPHP框架实现图像裁剪、缩放、加水印的方法
2017/03/14 PHP
phpstudy2018升级MySQL5.5为5.7教程(图文)
2018/10/24 PHP
关于PHP中interface的用处详解
2020/07/26 PHP
jQuery之网页换肤实现代码
2011/04/30 Javascript
javascript中关于&amp;&amp; 和 || 表达式的小技巧分享
2015/04/10 Javascript
Bootstrap每天必学之栅格系统(布局)
2015/11/25 Javascript
jquery.cookie实现的客户端购物车操作实例
2015/12/24 Javascript
jquery二级目录选中当前页的css样式
2016/12/08 Javascript
详解js中Number()、parseInt()和parseFloat()的区别
2016/12/20 Javascript
Js利用prototype自定义数组方法示例
2017/10/20 Javascript
vue组件横向树实现代码
2018/08/02 Javascript
使用Node.js实现一个多人游戏服务器引擎
2019/03/13 Javascript
JSON 入门教程基础篇 json入门学习笔记
2020/09/22 Javascript
Python3基础之条件与循环控制实例解析
2014/08/13 Python
Python 基础之字符串string详解及实例
2017/04/01 Python
新手如何快速入门Python(菜鸟必看篇)
2017/06/10 Python
opencv python统计及绘制直方图的方法
2019/01/21 Python
解决pyinstaller打包发布后的exe文件打开控制台闪退的问题
2019/06/21 Python
Django获取该数据的上一条和下一条方法
2019/08/12 Python
Django更新models数据库结构步骤
2020/04/01 Python
浅析PyCharm 的初始设置(知道)
2020/10/12 Python
详解H5 活动页之移动端 REM 布局适配方法
2017/12/07 HTML / CSS
匈牙利最大的健身制造商和销售商:inSPORTline
2018/10/30 全球购物
GAZMAN官网:澳大利亚领先的男装品牌
2019/12/19 全球购物
英国书籍、CD、DVD和游戏的第一道德零售商:Awesome Books
2020/02/22 全球购物
给幼儿园老师的表扬信
2014/01/19 职场文书
吸烟检讨书2000字
2014/02/13 职场文书
实践单位评语
2014/04/26 职场文书
奥巴马连任演讲稿
2014/05/15 职场文书
地方白酒代理协议书
2014/10/25 职场文书
亲属关系公证书样本
2015/01/23 职场文书
2015年污水处理厂工作总结
2015/05/26 职场文书
体育教师研修感悟
2015/11/18 职场文书
MongoDB支持的数据类型
2022/04/11 MongoDB