zoukankan      html  css  js  c++  java
  • 使用php的curl爬去青果教务系统 课表

    1. 分析

    首先我们要了解 Http Cookie 的作用(可参考HTTP cookies 详解),简单来说就是维持一个会话,这样我们就能在登陆一个网页后,就能进入这个网页需要登陆的界面。

    现在我们需要模拟登陆青果教务系统,就也需要先获取服务器给我们的cookie,然后用这个cookie值去获取验证码登陆,获取我们想要的内容。要注意的是有的网站对表头信息也是有验证的,我们需要在请求中添加表头信息。

    总结起来就三部,首先获取登录界面的验证码并存储Cookie,然后通过cookie来模拟登陆,最后进入教务系统取想要的东西。

    现在我们需要去留意的内容,各个请求的连接、header、和发送的数据

    2. 查看请求

    首先我们查看首页,我们发现登录并不在首页上,需要点击用户登录后才算进入了登录界面。 
    这里写图片描述

    这里写图片描述

    然后我们查看登录界面的请求。我们就是需要图中的Cookie 来登录, 
    这里写图片描述

    在看验证码的请求,发现其中你的Cookie是一样的,所以,我们直接获取验证码的Cookie保存就行,不管登界面。 
    这里写图片描述

    我们在看登录的请求,请求类型为POST,还是原来的cookie,但是我们发现传送的数据竟然那么多,其实,比多请求几次就会发现,其实有几个的值是永远不会变的,我们下面接着分析。 
    这里写图片描述
    这里写图片描述

    查看表单登录结构,发现刚才的提交数据都是隐藏的标签,并且都是大部分都是固定值,只有两个是我在输入密码或验证码时会一直变动,其实这两个就是密码和验证码,只是进行了特殊处理,这个网页引入了一个 md5.js 文件(上面第二张图中可以看到),加密就是通过这个文件进行的。 
    这里写图片描述

    我们寻找加密部分的代码,在页面的某一部分,我们发现了加密的代码,我们在模拟登陆时就可以使用这部分处理了。 
    这里写图片描述

    当我们登陆成功后我们课表的请求。OK,我们的心思收集工作完成了。下面开始编码吧。 
    这里写图片描述

    3. 获取验证码和Cookie

    首先我们需要一个界面来模拟登陆,我写了一个简单的html form登录,需要注意的是咋提交账号密码时要对信息使用 md5.js 加密。

     1 /**
     2   *test.html文件
     3   */
     4 <!doctype html>
     5 <html lang="en">
     6 <head>
     7     <meta charset="UTF-8">
     8     <meta name="viewport"
     9           content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    10     <meta http-equiv="X-UA-Compatible" content="ie=edge">
    11     <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    12     <title>课表登录</title>
    13 </head>
    14 <body>
    15 <form action="./php/login.php" method="post">
    16     <div class="form-group">
    17         <input type="hidden" name="password" value="" id="password">
    18         <input type="hidden" name="validate" value="" id="validate">
    19     </div>
    20     <div class="form-group">
    21         <label for="id">学号:</label>
    22         <input type="number" class="form-control" id="id" name="txt_asmcdefsddsd" placeholder="" onblur="chkpwd()" onkeyup="chkpwd()">
    23     </div>
    24     <div class="form-group">
    25         <label for="exampleInputPassword1">密码:</label>
    26         <input type="password" class="form-control" id="exampleInputPassword1"  name="txt_pewerwedsdfsdff" placeholder="Password" onblur="chkpwd()" onkeyup="chkpwd()">
    27     </div>
    28     <div class="form-group">
    29         <label for="exampleInputValidate">验证码:</label>
    30         <input type="text" class="form-control" id="exampleInputValidate" name="validatessss" placeholder="" onblur="chkyzm()" onkeyup="chkyzm()">
    31         <img src="./php/getValidate.php" onclick="changeValidateCode()" alt="" id="validateImg">
    32     </div>
    33 
    34     <button type="submit" class="btn btn-default">登录</button>
    35 </form>
    36 <script  src="./js/jquery-3.2.1.min.js"></script>
    37 <script  src="./js/md5.js"></script>
    38 <script>
    39 
    40     function changeValidateCode(){
    41         var Obj = $('#validateImg');
    42         var dt = new Date();
    43         var src = "./php/getValidate.php?t="+dt.getMilliseconds();
    44         Obj.attr('src', src);
    45     }
    46 
    47     function chkpwd() {
    48         var obj = $('#exampleInputPassword1');
    49         if(obj.val()!='')  {
    50             var s = md5($('#id').val()+md5(obj.val()).substring(0,30).toUpperCase()+'10467').substring(0,30).toUpperCase();
    51             $('#password').attr("value",s);
    52         } else {
    53             $('#password').attr("value",'');
    54         }
    55     }
    56     function chkyzm() {
    57         var obj = $('#exampleInputValidate');
    58         if(obj.val()!='') {
    59             var s=md5(md5(obj.val().toUpperCase()).substring(0,30).toUpperCase()+'10467').substring(0,30).toUpperCase();
    60             $('#validate').attr("value",s);
    61         } else {
    62             $('#validate').attr("value",'');
    63         }
    64     }
    65 </script>
    66 </body>
    67 </html>

    我们来获取验证码 ,注意的是我是吧Cookie存储到了本地

     1 /**
     2   */php/getValidate.php文件
     3   */
     4 <?php
     5 //Cookie存储文件
     6 $cookie_file = dirname(__FILE__)."/../cookie/tmp.cookie";
     7 if(!file_exists($cookie_file)) {
     8     $myfile = fopen($cookie_file, "w");
     9     fclose($myfile);
    10 }
    11 $t = isset($_GET['t'])?$_GET['t']:0;
    12 $verify_code_url = "http://jwgl.xxxxxx.edu.cn/jwweb/sys/ValidateCode.aspx?t=".$t;
    13 
    14 //不用纠结那条需要不需要,直接header都写上是不会错的
    15 $header = [
    16     'Accept:image/webp,image/apng,image/*,*/*;q=0.8',
    17     'Accept-Encoding:gzip, deflate',
    18     'Accept-Language:zh-CN,zh;q=0.8',
    19     'Cache-Control:no-cache',
    20     'Connection:keep-alive',
    21     'Host:jwgl.xxxx.edu.cn',  //修改名称
    22     'Pragma:no-cache',
    23     'Referer:http://jwgl.xxxxx.edu.cn/jwweb/_data/login.aspx',//修改名称
    24     'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36',
    25 ];
    26 
    27 $curl = curl_init();
    28 curl_setopt($curl,CURLOPT_HTTPHEADER,$header);  //设置表头
    29 curl_setopt($curl, CURLOPT_URL, $verify_code_url); // 设置请求地址
    30 curl_setopt($curl,CURLOPT_COOKIEJAR,$cookie_file); //获取COOKIE并存储
    31 
    32 $img = curl_exec($curl);
    33 curl_close($curl);
    34 
    35 //输出图片到html
    36 echo $img;

    当进入test.html 时,cookie文件夹下就有存储的Cookie了 

    这里写图片描述

    4. 模拟登陆

    然后我们模拟登录,主要的地方是要用之前存储的Cookie和用Post请求

     1 //Cookie路径
     2 $cookie_file = dirname(__FILE__)."/../cookie/tmp.cookie";
     3 $url = 'http://jwgl.xxxx.edu.cn/jwweb/_data/index_LOGIN.aspx';
     4 $post = [
     5     '__VIEWSTATE' => 'dDw4ODEwMTkyNTY7Oz6uXw9RQf0bw8SrGIjZutgOtpxLCw==',
     6     '__VIEWSTATEGENERATOR' =>'4B596BA9',
     7     'pcInfo' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36undefined5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36 SN:NULL',
     8     'typeName' => '(unable to decode value)',
     9     'dsdsdsdsdxcxdfgfg' => $_POST['password'],
    10     'fgfggfdgtyuuyyuuckjg' => $_POST['validate'],
    11     'Sel_Type' => 'STU',
    12     'txt_asmcdefsddsd' => $_POST['txt_asmcdefsddsd'],
    13     'txt_pewerwedsdfsdff'=> '',
    14     'txt_sdertfgsadscxcadsads' => '',
    15     'sbtState' => '',
    16 ];
    17 $post = http_build_query($post);
    18 $headers = array(
    19     "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
    20     "Accept-Encoding:gzip, deflate",
    21     "Accept-Language:zh-CN,zh;q=0.8",
    22     "Cache-Control:max-age=0",
    23     "Content-Length:603",
    24     "Content-Type:application/x-www-form-urlencoded",
    25     "Host:jwgl.xxxx.edu.cn",
    26     "Origin:http://jwgl.xxxx.edu.cn",
    27     "Proxy-Connection:keep-alive",
    28     "Referer:http://jwgl.xxxx.edu.cn/jwweb/_data/index_LOGIN.aspx",
    29     "Upgrade-Insecure-Requests:1",
    30     "User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36",
    31 );
    32 $curl = curl_init();
    33 curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);//设置header
    34 curl_setopt($curl, CURLOPT_URL, $url);  //设置url
    35 curl_setopt($curl, CURLOPT_POST, true); // 设置为POST请求
    36 curl_setopt($curl, CURLOPT_RETURNTRANSFER,1); // 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
    37 curl_setopt($curl, CURLOPT_POSTFIELDS, $post); //传送的数据
    38 curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);  //设置cookie
    39 
    40 $result=curl_exec($curl);
    41 
    42 //可以输出当前信息看看是否登录成功
    43 //$file = dirname(__FILE__)."/../html/test.html";
    44 //$fp = fopen($file,"w");
    45 //fwrite($fp,$result);
    46 //fwrite($fp, '结束');
    47 //fclose($fp);

    5. 获取数据

    到此,我们已经登录成功了,然后我们就可以进入系统提取数据了,比如提取课表信息。 
    这里写图片描述

     1 $curl = curl_init();
     2 $url = 'http://jwgl.xxx.edu.cn/jwweb/wsxk/stu_zxjg_rpt.aspx';
     3 curl_setopt($curl, CURLOPT_URL, $url);
     4 curl_setopt($curl, CURLOPT_HEADER, false);
     5 curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
     6 curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
     7 $result=curl_exec($curl);
     8 
     9 $file = dirname(__FILE__)."/../html/test.html";
    10 
    11 $fp = fopen($file,"w");
    12 fwrite($fp,$result);
    13 fclose($fp);

    对于上面的 curl函数 也可以使用封装好的库Guzzle 替换来发送请求

    6. 提取数据

    当我们得到网页文本时,并不是我们的最终目的,我们要的是其中除了html标签之外的数据。关于提取数据,我推荐大家使用symfony/dom-crawler,再配合他的symfony/css-selector来将html文本转换成结点,通过CSS选择器方式定位结点获取相应的数据。

    注:本文转自:http://blog.csdn.net/mrwangweijin/article/details/77194994,如需转载请注明出处:https://www.cnblogs.com/zhuchenglin/p/7732352.html

  • 相关阅读:
    git的使用
    对大学学习的一些看法
    远程连接mysql失败情况总结
    缓存穿透、缓存击穿、缓存雪崩
    Hello Redis
    Celery的简单使用
    git操作
    码云、github同时配置ssh key,解决冲突问题
    阿里云短信验证码服务
    Vue中img标签的src属性绑定的坑
  • 原文地址:https://www.cnblogs.com/zhuchenglin/p/7732352.html
Copyright © 2011-2022 走看看