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