http://demo.blueyian.top/mara...
完整的代碼包請上gayhub取用。以爲有用的能夠給個star :)
地址:https://github.com/KongYian/m...php
咱們的目標是http://www.runchina.org.cn/po... 所以先來分析一下此網站是如何實現成績查詢。
多嘗試輸入幾回本身的查詢信息,打開F12觀察NetWork和Application裏面的數據,咱們能夠簡單的判斷出查詢的大體流程以下圖:
在反覆試驗的過程和檢查中,咱們會發現這個網站木有什麼CRSF等保護,除了一個+-*/的驗證碼,其餘就是一個赤裸裸的接口了。html
在實際作的過程當中,我將第一步和第二步放在一塊兒做爲了一個接口(命名爲-- 接口1)。獲取驗證碼圖片和PHPSESSIONID,代碼以下:
其中關鍵操做在代碼註釋中--前端
<?php $verify_code_url = "http://www.runchina.org.cn/template/default/public/js/securimage/securimage_show.php"; $query_url = "http://www.runchina.org.cn/portal.php?mod=score&ac=personal"; $cookie_file = "../tmp.cookie"; showAuthcode($verify_code_url,$cookie_file); $handle = fopen($cookie_file,'r'); $line= ''; while (!feof($handle)) { $line .= fgets($handle); } preg_match("/PHPSESSID(?<right>.*)/",$line,$sessionArr); fclose($handle); $session = trimall($sessionArr['right'],' '); $sessionString = "PHPSESSID=".$session.';'; $res = curlLogin($query_url,$cookie_file,$sessionString); preg_match_all('/Set-Cookie:(.*);/iU',$res,$out); $tmp = implode(';',$out[1]); $cookieString = $sessionString.$tmp; //此變量圍第二次請求使用的cookie值 echo json_encode(['data'=>$cookieString]); exit; function trimall($str)//刪除空格 { $oldchar=array(" "," ","\t","\n","\r"); $newchar=array("","","","",""); return str_replace($oldchar,$newchar,$str); } function showAuthcode( $authcode_url,$cookieFile) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $authcode_url); curl_setopt($curl, CURLOPT_COOKIEJAR, $cookieFile); //將獲取的cookie以文件的形式保存 curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36'); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $img = curl_exec($curl); curl_close($curl); $fp = fopen("../image/verifyCode.jpg","w"); //獲取驗證碼的圖片 fwrite($fp,$img); fclose($fp); } function curlLogin($url,$cookiefile,$session) { $headers = [ "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding:gzip, deflate", "Accept-Language:zh-CN,zh;q=0.9", "Connection:keep-alive", "Cookie:".$session, "Host:www.runchina.org.cn", "Upgrade-Insecure-Requests:1", "User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36", ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_ACCEPT_ENCODING, "gzip, deflate, sdch"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile); //用請求驗證碼接口獲取的cookie做爲本次請求的set-cookie 獲取新的cookie文件,可是這裏咱們沒有以文件形式存儲而是直接輸出,這樣避免了屢次文件IO的消耗。 curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_HEADER, true); $contents = curl_exec($ch); curl_close($ch); return $contents; }
咱們從接口一獲取到了要用的cookieString和驗證碼的圖片,下面就來模擬表單提交了,模擬提交的代碼以下:vue
$query_url = "http://www.runchina.org.cn/portal.php?mod=score&ac=personal"; $idnum = $_POST['idnum']; $name = $_POST['name']; $code = $_POST['code']; $cookie = $_POST['cookie']; $params = [ 'idnum'=>$idnum, 'name'=>$name, 'captcha_code'=>$code ]; $https = query($query_url,$params,$cookie); function query($query_url,$params,$cookie){ $headers = [ "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding:gzip, deflate", "Accept-Language:zh-CN,zh;q=0.9", "Connection:keep-alive", "Cookie:".$cookie, "Host:www.runchina.org.cn", "Upgrade-Insecure-Requests:1", "User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36", ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $query_url); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $resp = curl_exec($ch); curl_close($ch); return $resp; } function trimall($str)//刪除空格 { $oldchar=array(" "," ","\t","\n","\r"); $newchar=array("","","","",""); return str_replace($oldchar,$newchar,$str); }
變量$https
即是咱們請求的結果了,若是正確的話是一個結果頁面,若是沒有數據或者出錯的話則沒有數據了。
拿到頁面以後,咱們就能夠來操做dom了,這裏我用的是‘simple_html_dom’,具體如何食用能夠google一下。如下是我操做的具體代碼:git
require_once 'simple_html_dom.php'; $htmlDom = str_get_html($https); $out = []; foreach($htmlDom->find('.myScore tbody tr') as $kk => $e) { if($kk != 0){ foreach ($e->children as $k => $child) { switch ($k){ case 0: $out[$kk]['date'] = $child->plaintext ;break; case 1: $out[$kk]['name'] = trimall($child->plaintext) ;break; case 2: $out[$kk]['type'] = trimall($child->plaintext) ;break; case 3: $out[$kk]['raceNetTime'] = $child->plaintext ; if(strpos($out[$kk]['raceNetTime'],'PB') !== false){ $out[$kk]['pbColor'] = 'pink'; }else{ $out[$kk]['pbColor'] = ''; } break; case 4:$out[$kk]['raceTrueTime'] = $child->plaintext ;break; // case 5: $out[$kk]['raceDetailTime'] = trimall($child->innertext) ;break; } } } } //釋放資源對象,會很佔用內存 $htmlDom->clear(); unset($htmlDom);
最後咱們獲得的數據結構以下:github
前端的話,用的很亂,vue,jq,layer,妹子UI都用了,正真的demo...
放一些JS代碼吧:web
<script> var vm = new Vue({ el:'#app', data:{ name:localStorage.getItem('name')=='undefined'?'':localStorage.getItem('name'), idnum:localStorage.getItem('idnum')=='undefined'?'':localStorage.getItem('idnum'), code:'', showSearch : 1, result:'', imageSrc : 'image/verifyCode.jpg', isPBColor :'pink' }, beforeCreate:function(){ cookie = init(); }, filters:{ }, methods:{ query:function () { if(!(this.name && this.idnum && this.code && cookie)){ layer.msg('每一項都要填寫:)'); return false; } var load = layer.load(); $.ajax({ url:'action/search.php', data:{ name:this.name, idnum:this.idnum, code:this.code, cookie:cookie, }, dataType:'json', type:'post', success:function (response) { if(response.status == 1){ vm.result = response.data; vm.showSearch = 0; localStorage.setItem('name',vm.name); localStorage.setItem('idnum',vm.idnum); }else{ layer.msg('未查詢到成績,再試試吧QAQ'); vm.reload(); return false; } }, error:function () { layer.msg('服務器開小差啦,稍後再試'); }, complete:function () { layer.close(load) } }) }, reload:function () { window.location.reload(); } } }) function init() { var cookieString; $.ajax({ url:'action/init.php', dataType:'json', type:'post', async:false, success:function (response) { cookieString = response.data }, error:function () { } }) return cookieString; } </script>