1、線上demo
http://demo.blueyian.top/mara...
完整的程式碼包請上gayhub取用。覺得有用的可以給個star :)
地址:https://github.com/KongYian/m...
2、截圖
2.1、首頁
2.2、查詢結果
3、實現
3.1、分析目標網站
我們的目標是http://www.runchina.org.cn/po... 因此先來分析一下此網站是如何實現成績查詢。
多嘗試輸入幾次自己的查詢資訊,開啟F12觀察NetWork和Application裡面的資料,我們可以簡單的判斷出查詢的大致流程如下圖:
在反覆試驗的過程和檢查中,我們會發現這個網站木有什麼CRSF等保護,除了一個+-*/的驗證碼,其他就是一個赤裸裸的介面了。
3.2、流程
在實際做的過程中,我將第一步和第二步放在一起作為了一個介面(命名為-- 介面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和驗證碼的圖片,下面就來模擬表單提交了,模擬提交的程式碼如下:
$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一下。以下是我操作的具體程式碼:
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);
最後我們得到的資料結構如下:
前端的話,用的很亂,vue,jq,layer,妹子UI都用了,正真的demo...
放一些JS程式碼吧:
<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>