2016-07-20 09:29:42 +08:00
|
|
|
<?php
|
|
|
|
|
set_time_limit(0);
|
|
|
|
|
header('Content-type:text/html;charset=utf-8');
|
|
|
|
|
|
2016-08-09 13:32:51 +08:00
|
|
|
$date = U::getValue($_GET,'date','2016-09-06'); // 购票日期
|
|
|
|
|
$from = U::getValue($_GET,'form','襄阳'); // 起点
|
|
|
|
|
$to = U::getValue($_GET,'to','北京'); // 终点
|
2016-07-20 09:29:42 +08:00
|
|
|
$min = 1; // 最小余票量。如:余票量大于 1 就提醒我,否者忽略
|
|
|
|
|
|
|
|
|
|
$url = C::getListsUrl($date, Z::getName($from), Z::getName($to));
|
|
|
|
|
$result = U::curlRequest($url); // 获取列车表
|
|
|
|
|
|
2016-08-09 13:32:51 +08:00
|
|
|
|
2016-07-20 09:29:42 +08:00
|
|
|
if( ($data = U::getDataByJson($result)) === false ){
|
|
|
|
|
U::end('获取列车失败');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存需要操作的列车
|
|
|
|
|
M::saveAs($data);
|
|
|
|
|
|
|
|
|
|
// 立即检测车次
|
|
|
|
|
M::checkIsBuy($data);
|
|
|
|
|
|
|
|
|
|
// 计算备选车次
|
|
|
|
|
M::computeAlternateTrain($data); // 计算备选车次
|
|
|
|
|
|
|
|
|
|
// 检查可用车次信息
|
|
|
|
|
M::checkingLieche();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 业务处理功能类
|
|
|
|
|
class M{
|
|
|
|
|
|
|
|
|
|
// 预定义可购买列车
|
|
|
|
|
public static $buyArr = array();
|
|
|
|
|
// 需要遍历的车次的信息
|
|
|
|
|
public static $trainArr = array();
|
|
|
|
|
// 需要遍历的站点
|
|
|
|
|
public static $stationArr = array();
|
|
|
|
|
// 需要遍历的站点
|
|
|
|
|
public static $stationNewArr = array();
|
|
|
|
|
// 需要遍历的车次
|
|
|
|
|
public static $As = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 判断返回的余票量是否有效
|
|
|
|
|
*
|
|
|
|
|
* @param $val
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public static function rNumber($val){
|
|
|
|
|
|
|
|
|
|
if($val == '有'){
|
|
|
|
|
return true;
|
|
|
|
|
}elseif( intval($val) >= $GLOBALS['min'] ){
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 计算备选车次
|
|
|
|
|
*/
|
|
|
|
|
public static function computeAlternateTrain($data){
|
|
|
|
|
self::foreachTrain($data); // 获取所有列车信息
|
|
|
|
|
self::foreachStation(); // 遍历站点
|
|
|
|
|
self::dealWithDika(); // 处理笛卡尔积结果
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查可用车次
|
|
|
|
|
*/
|
|
|
|
|
public static function checkingLieche(){
|
|
|
|
|
foreach(self::$stationNewArr as $v){
|
|
|
|
|
$url = C::getListsUrl($GLOBALS['date'], Z::getName($v['start']), Z::getName($v['end']));
|
2016-08-09 13:32:51 +08:00
|
|
|
|
2016-07-20 09:29:42 +08:00
|
|
|
$result = U::curlRequest($url); // 获取列车表
|
|
|
|
|
if( ($data = U::getDataByJson($result)) ){
|
|
|
|
|
self::checkIsBuyByThis($data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理笛卡尔积结果
|
|
|
|
|
*/
|
|
|
|
|
public static function dealWithDika(){
|
|
|
|
|
foreach(self::$stationArr as $item){
|
|
|
|
|
foreach($item as $v){
|
|
|
|
|
$tArr1 = explode('|',$v[0]);
|
|
|
|
|
$tArr2 = explode('|',$v[1]);
|
|
|
|
|
|
|
|
|
|
$arr = array();
|
|
|
|
|
$arr['start'] = $tArr1[0];
|
|
|
|
|
$arr['end'] = $tArr2[0];
|
|
|
|
|
$arr['order'] = $tArr1[1] + $tArr2[1];
|
|
|
|
|
if($arr['order'] > 0){ // 当前站点就不再重复查询了
|
|
|
|
|
self::$stationNewArr[$arr['start'].'-'.$arr['end']] = $arr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-09 13:32:51 +08:00
|
|
|
|
2016-07-20 09:29:42 +08:00
|
|
|
// 按照跨站的距离排序
|
|
|
|
|
self::$stationNewArr = U::array_sort(self::$stationNewArr,'order','asc');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 遍历站点
|
|
|
|
|
*/
|
|
|
|
|
public static function foreachStation(){
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 第一次遍历:
|
|
|
|
|
* 1. 给每个站点加上序号。(index)
|
|
|
|
|
* 2. 找到当次查询的列车行程起点的序号与站名,并标记到列车起点信息中
|
|
|
|
|
* 3. 找到当次查询的列车行程终点的序号与站名,并标记到列车起点信息中
|
|
|
|
|
*/
|
|
|
|
|
foreach(M::$trainArr as $key => $item){
|
|
|
|
|
|
|
|
|
|
$_sBol = false; // 预定义状态游标
|
|
|
|
|
$from_station_name = '';
|
|
|
|
|
$from_station_index = 1;
|
|
|
|
|
$to_station_name = '';
|
|
|
|
|
$to_station_index = 1;
|
|
|
|
|
foreach($item as $k => $v){
|
|
|
|
|
// 给站点加上序号
|
|
|
|
|
M::$trainArr[$key][$k]->index = intval(U::getValue($v,'station_no'));
|
|
|
|
|
|
|
|
|
|
if( $_sBol === true && U::getValue($v,'isEnabled') === true ){
|
|
|
|
|
// 默认找到行程起点后,任何一个有效站点当做行程终点站
|
|
|
|
|
$to_station_name = U::getValue($v,'station_name');
|
|
|
|
|
$to_station_index = intval(U::getValue($v,'station_no'));
|
|
|
|
|
}elseif( $_sBol === false && U::getValue($v,'isEnabled') === true){ // 找到起点站
|
|
|
|
|
$from_station_name = U::getValue($v,'station_name');
|
|
|
|
|
$from_station_index = intval(U::getValue($v,'station_no'));
|
|
|
|
|
$_sBol = true; // 修改游标状态
|
|
|
|
|
}
|
|
|
|
|
elseif( $_sBol === true && U::getValue($v,'isEnabled') === false ){ // 找到行程终点
|
|
|
|
|
$_sBol = false; // 还原游标状态
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将行程起点,序号记录到首行信息
|
|
|
|
|
M::$trainArr[$key][0]->from_station_name = $from_station_name;
|
|
|
|
|
M::$trainArr[$key][0]->from_station_index = $from_station_index;
|
|
|
|
|
M::$trainArr[$key][0]->to_station_name = $to_station_name;
|
|
|
|
|
M::$trainArr[$key][0]->to_station_index = $to_station_index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 第二次遍历:
|
|
|
|
|
* 1. 取出行程起点站的序号
|
|
|
|
|
* 2. 取出行程终点站的序号
|
|
|
|
|
* 3. 取出 列车起点站 - 行程起点站 的集合站点
|
|
|
|
|
* 4. 取出 行程终点站 - 列车终点站 的集合站点
|
|
|
|
|
* 5. 传入 笛卡尔算法 计算出新的查询站点
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
foreach(M::$trainArr as $key => $item) {
|
|
|
|
|
|
|
|
|
|
// 取出行程信息及起点序号
|
|
|
|
|
$from_station_name = U::getValue($item[0],'from_station_name');
|
|
|
|
|
$from_station_index = U::getValue($item[0],'from_station_index');
|
|
|
|
|
$to_station_name = U::getValue($item[0],'to_station_name');
|
|
|
|
|
$to_station_index = U::getValue($item[0],'to_station_index');
|
|
|
|
|
|
|
|
|
|
// 取出列车编号
|
|
|
|
|
$station_train_code = U::getValue($item[0],'station_train_code');
|
|
|
|
|
|
|
|
|
|
// 预定义超前站点集
|
|
|
|
|
$beforeSizesArr = array();
|
|
|
|
|
$backSizesArr = array();
|
|
|
|
|
|
|
|
|
|
// 取两端极至站点
|
|
|
|
|
foreach ($item as $k => $v) {
|
|
|
|
|
$index = intval(U::getValue($v,'index',0));
|
|
|
|
|
if($index <= $from_station_index){
|
|
|
|
|
$beforeSizesArr[] = U::getValue($v,'station_name','').'|'.abs($from_station_index - $index);
|
|
|
|
|
}elseif($index >= $to_station_index){
|
|
|
|
|
$backSizesArr[] = U::getValue($v,'station_name','').'|'.abs($index - $to_station_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 送入笛卡尔算法
|
|
|
|
|
self::$stationArr[] = U::combineDika($beforeSizesArr,$backSizesArr); # 计算笛卡尔积
|
|
|
|
|
}
|
2016-08-09 13:32:51 +08:00
|
|
|
|
2016-07-20 09:29:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 提取需要遍历的车次所有站点
|
|
|
|
|
public static function foreachTrain($data){
|
|
|
|
|
// 遍历当前行程的车次
|
|
|
|
|
foreach ($data as $val) {
|
2016-08-09 13:32:51 +08:00
|
|
|
//$row = U::getValue($val,'queryLeftNewDTO');
|
|
|
|
|
$row = $val;
|
2016-07-20 09:29:42 +08:00
|
|
|
|
2016-08-09 13:32:51 +08:00
|
|
|
$train_no = U::getValue($val,'train_no',0); // 列车编号
|
2016-07-20 09:29:42 +08:00
|
|
|
|
|
|
|
|
$start_station_telecode = U::getValue($row,'start_station_telecode'); // 列车起点站代号
|
|
|
|
|
$start_station_name = U::getValue($row,'start_station_name'); // 列车起点站名称
|
|
|
|
|
$end_station_telecode = U::getValue($row,'end_station_telecode'); // 列车终点站代号
|
|
|
|
|
$end_station_name = U::getValue($row,'end_station_name'); // 列车终点站名称
|
|
|
|
|
|
|
|
|
|
$from_station_telecode = U::getValue($row,'from_station_telecode'); // 行程起点代号
|
|
|
|
|
$from_station_name = U::getValue($row,'from_station_name'); // 行程起点名称
|
2016-08-09 13:32:51 +08:00
|
|
|
|
2016-07-20 09:29:42 +08:00
|
|
|
$to_station_telecode = U::getValue($row,'to_station_telecode'); // 行程终点代号
|
|
|
|
|
$to_station_name = U::getValue($row,'to_station_name'); // 行程终点名称
|
2016-08-09 13:32:51 +08:00
|
|
|
|
|
|
|
|
$seat_types = U::getValue($row,'seat_types'); //
|
|
|
|
|
|
|
|
|
|
$url = C::getStationUrl($train_no,$GLOBALS['date'],$from_station_telecode,$to_station_telecode,$seat_types);
|
2016-07-20 09:29:42 +08:00
|
|
|
|
2016-08-09 13:32:51 +08:00
|
|
|
$result = U::curlRequest($url);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( $data = U::getDataByJson2($result)){
|
2016-07-20 09:29:42 +08:00
|
|
|
$tmpArr = U::getValue($data,'data',array());
|
|
|
|
|
if(!empty($tmpArr)){
|
|
|
|
|
M::$trainArr[] = $tmpArr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 保存需要操作的车次
|
|
|
|
|
*/
|
|
|
|
|
public static function saveAs($data = array()){
|
|
|
|
|
foreach ($data as $val) {
|
2016-08-09 13:32:51 +08:00
|
|
|
//$row = U::getValue($val,'queryLeftNewDTO');
|
|
|
|
|
$row = $val;
|
2016-07-20 09:29:42 +08:00
|
|
|
self::$As[U::getValue($row,'station_train_code')] = array(
|
|
|
|
|
'station_train_code' => U::getValue($row,'station_train_code'),
|
|
|
|
|
'train_no' => U::getValue($row,'train_no'),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检测车次列表是否有可购买的车次
|
|
|
|
|
*/
|
|
|
|
|
public static function checkIsBuy($data = array()){
|
|
|
|
|
foreach ($data as $val) {
|
2016-08-09 13:32:51 +08:00
|
|
|
//$row = U::getValue($val,'queryLeftNewDTO');
|
|
|
|
|
$row = $val;
|
2016-07-20 09:29:42 +08:00
|
|
|
|
|
|
|
|
$yz_num = M::rNumber(U::getValue($row,'yz_num',0)); // 硬座
|
|
|
|
|
$yw_num = M::rNumber(U::getValue($row,'yw_num',0)); // 硬卧
|
|
|
|
|
$ze_num = M::rNumber(U::getValue($row,'ze_num',0)); // 二等座
|
|
|
|
|
$zy_num = M::rNumber(U::getValue($row,'zy_num',0)); // 一等座
|
|
|
|
|
|
|
|
|
|
if( $yz_num || $yw_num || $ze_num || $zy_num ){ // 只要有一个座位等次符合余量就加入待选队列
|
|
|
|
|
self::$buyArr[] = $row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检测车次列表是否有可购买的车次,只选择目标行程中出现的车次
|
|
|
|
|
*/
|
|
|
|
|
public static function checkIsBuyByThis($data = array()){
|
|
|
|
|
foreach ($data as $val) {
|
2016-08-09 13:32:51 +08:00
|
|
|
//$row = U::getValue($val,'queryLeftNewDTO');
|
|
|
|
|
$row = $val;
|
|
|
|
|
|
2016-07-20 09:29:42 +08:00
|
|
|
$station_train_code = U::getValue($row,'station_train_code','');
|
|
|
|
|
if(isset(self::$As[$station_train_code])){
|
|
|
|
|
$yz_num = M::rNumber(U::getValue($row,'yz_num',0)); // 硬座
|
|
|
|
|
$yw_num = M::rNumber(U::getValue($row,'yw_num',0)); // 硬卧
|
|
|
|
|
$ze_num = M::rNumber(U::getValue($row,'ze_num',0)); // 二等座
|
|
|
|
|
$zy_num = M::rNumber(U::getValue($row,'zy_num',0)); // 一等座
|
|
|
|
|
|
|
|
|
|
if( $yz_num || $yw_num || $ze_num || $zy_num ){ // 只要有一个座位等次符合余量就加入待选队列
|
|
|
|
|
self::$buyArr[] = $row;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// 业务处理功能类
|
|
|
|
|
|
|
|
|
|
// 配置类
|
|
|
|
|
class C{
|
|
|
|
|
/**
|
|
|
|
|
* 获取列车列表URL
|
|
|
|
|
*/
|
|
|
|
|
public static function getListsUrl($date = '',$from = '',$to = ''){
|
2016-08-09 13:32:51 +08:00
|
|
|
return "https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate={$date}&from_station={$from}&to_station={$to}";
|
|
|
|
|
//return "https://kyfw.12306.cn/otn/leftTicket/queryT?leftTicketDTO.train_date={$date}&leftTicketDTO.from_station={$from}&leftTicketDTO.to_station={$to}&purpose_codes=ADULT";
|
2016-07-20 09:29:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取列车站点URL
|
|
|
|
|
*/
|
2016-08-09 13:32:51 +08:00
|
|
|
public static function getStationUrl($train_no = '',$date = '',$from = '',$to = '', $seat_types = ''){
|
2016-07-20 09:29:42 +08:00
|
|
|
return "https://kyfw.12306.cn/otn/czxx/queryByTrainNo?train_no={$train_no}&from_station_telecode={$from}&to_station_telecode={$to}&depart_date={$date}";
|
2016-08-09 13:32:51 +08:00
|
|
|
//return "https://kyfw.12306.cn/otn/czxx/queryByTrainNo?train_no={$train_no}&from_station_telecode={$from}&to_station_telecode={$to}&depart_date={$date}";
|
2016-07-20 09:29:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// 配置类 End
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 功能类
|
|
|
|
|
class U{
|
|
|
|
|
|
|
|
|
|
// 检查
|
|
|
|
|
public static function getDataByJson($result){
|
2016-08-09 13:32:51 +08:00
|
|
|
if(self::isJson($result)){
|
|
|
|
|
$json = json_decode($result);
|
|
|
|
|
if( (self::getValue($json,'status') === true) && (self::getValue($json,'httpstatus') === 200) ){
|
|
|
|
|
$data = self::getValue($json,'data',array());
|
|
|
|
|
return self::getValue($data,'datas',array());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function getDataByJson2($result){
|
2016-07-20 09:29:42 +08:00
|
|
|
if(self::isJson($result)){
|
|
|
|
|
$json = json_decode($result);
|
|
|
|
|
if( (self::getValue($json,'status') === true) && (self::getValue($json,'httpstatus') === 200) ){
|
|
|
|
|
return self::getValue($json,'data',array());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 二维数组按指定列排序
|
|
|
|
|
*
|
|
|
|
|
* @param $arr
|
|
|
|
|
* @param $keys
|
|
|
|
|
* @param string $type
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function array_sort($arr, $keys, $type = 'desc') {
|
|
|
|
|
$keysvalue = $new_array = array();
|
|
|
|
|
foreach ($arr as $k => $v) {
|
|
|
|
|
$keysvalue[$k] = U::getValue($v,$keys);
|
|
|
|
|
}
|
|
|
|
|
if ($type == 'asc') {
|
|
|
|
|
asort($keysvalue);
|
|
|
|
|
} else {
|
|
|
|
|
arsort($keysvalue);
|
|
|
|
|
}
|
|
|
|
|
reset($keysvalue);
|
|
|
|
|
foreach ($keysvalue as $k => $v) {
|
|
|
|
|
$new_array[$k] = $arr[$k];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $new_array;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查字符串是否一个合法的json
|
|
|
|
|
*
|
|
|
|
|
* @param $string
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public static function isJson($string) {
|
|
|
|
|
json_decode($string);
|
|
|
|
|
return (json_last_error() == JSON_ERROR_NONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Isset 封装
|
|
|
|
|
* @param array|object $arr_or_obj
|
|
|
|
|
* @param $key_or_prop
|
|
|
|
|
* @param string $else
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public static function getValue($arr_or_obj, $key_or_prop, $else = ''){
|
|
|
|
|
$result = $else;
|
|
|
|
|
if(isset($arr_or_obj)){
|
|
|
|
|
if(is_array($arr_or_obj)){
|
|
|
|
|
if(isset($arr_or_obj[$key_or_prop])) {
|
|
|
|
|
$result = $arr_or_obj[$key_or_prop];
|
|
|
|
|
}
|
|
|
|
|
}else if(is_object($arr_or_obj)){
|
|
|
|
|
if (isset($arr_or_obj->$key_or_prop)) {
|
|
|
|
|
$result = $arr_or_obj->$key_or_prop;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 模拟 Post/Get 请求
|
|
|
|
|
* @param String $url 请求URl
|
|
|
|
|
* @param Array $info 携带数据
|
|
|
|
|
* @param int $timeout 超时时间
|
|
|
|
|
* @return mixed
|
|
|
|
|
*/
|
|
|
|
|
public static function curlRequest($url = '', $info = array(), $timeout = 30) { // 模拟提交数据函数
|
|
|
|
|
$curl = curl_init(); // 启动一个CURL会话
|
|
|
|
|
curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
|
|
|
|
|
curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
|
|
|
|
|
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); // 设置超时限制防止死循环
|
|
|
|
|
if (stripos ( $url, "https://" ) !== FALSE) {
|
|
|
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
|
|
|
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
|
|
|
|
|
}
|
|
|
|
|
curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
|
|
|
|
|
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
|
|
|
|
|
curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
|
|
|
|
|
if(!empty($info)) {
|
|
|
|
|
curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
|
|
|
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $info); // Post提交的数据包
|
|
|
|
|
}
|
|
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
|
|
|
|
|
$tmpInfo = curl_exec($curl); // 执行操作
|
|
|
|
|
if (curl_errno($curl)) {
|
|
|
|
|
error_log('Errno:' . curl_error($curl)); //捕抓异常
|
|
|
|
|
}
|
|
|
|
|
curl_close($curl); // 关闭CURL会话
|
|
|
|
|
return $tmpInfo; // 返回数据
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 所有数组的笛卡尔积
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function combineDika() {
|
|
|
|
|
$data = func_get_args();
|
|
|
|
|
$cnt = count($data);
|
|
|
|
|
$result = array();
|
|
|
|
|
foreach($data[0] as $item) {
|
|
|
|
|
$result[] = array($item);
|
|
|
|
|
}
|
|
|
|
|
for($i = 1; $i < $cnt; $i++) {
|
|
|
|
|
$result = self::combineArray($result,$data[$i]);
|
|
|
|
|
}
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 两个数组的笛卡尔积
|
|
|
|
|
*
|
|
|
|
|
* @param $arr1
|
|
|
|
|
* @param $arr2
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function combineArray($arr1,$arr2) {
|
|
|
|
|
$result = array();
|
|
|
|
|
foreach ($arr1 as $item1) {
|
|
|
|
|
foreach ($arr2 as $item2) {
|
|
|
|
|
$temp = $item1;
|
|
|
|
|
$temp[] = $item2;
|
|
|
|
|
$result[] = $temp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 终止运行
|
|
|
|
|
public static function end($str = ''){
|
|
|
|
|
echo $str;
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 功能类 End
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 地名处理类
|
|
|
|
|
*/
|
|
|
|
|
class Z{
|
|
|
|
|
const STATICON_NAMES = '@bjb|北京北|VAP|beijingbei|bjb|0@bjd|北京东|BOP|beijingdong|bjd|1@bji|北京|BJP|beijing|bj|2@bjn|北京南|VNP|beijingnan|bjn|3@bjx|北京西|BXP|beijingxi|bjx|4@gzn|广州南|IZQ|guangzhounan|gzn|5@cqb|重庆北|CUW|chongqingbei|cqb|6@cqi|重庆|CQW|chongqing|cq|7@cqn|重庆南|CRW|chongqingnan|cqn|8@gzd|广州东|GGQ|guangzhoudong|gzd|9@sha|上海|SHH|shanghai|sh|10@shn|上海南|SNH|shanghainan|shn|11@shq|上海虹桥|AOH|shanghaihongqiao|shhq|12@shx|上海西|SXH|shanghaixi|shx|13@tjb|天津北|TBP|tianjinbei|tjb|14@tji|天津|TJP|tianjin|tj|15@tjn|天津南|TIP|tianjinnan|tjn|16@tjx|天津西|TXP|tianjinxi|tjx|17@cch|长春|CCT|changchun|cc|18@ccn|长春南|CET|changchunnan|ccn|19@ccx|长春西|CRT|changchunxi|ccx|20@cdd|成都东|ICW|chengdudong|cdd|21@cdn|成都南|CNW|chengdunan|cdn|22@cdu|成都|CDW|chengdu|cd|23@csh|长沙|CSQ|changsha|cs|24@csn|长沙南|CWQ|changshanan|csn|25@fzh|福州|FZS|fuzhou|fz|26@fzn|福州南|FYS|fuzhounan|fzn|27@gya|贵阳|GIW|guiyang|gy|28@gzh|广州|GZQ|guangzhou|gz|29@gzx|广州西|GXQ|guangzhouxi|gzx|30@heb|哈尔滨|HBB|haerbin|heb|31@hed|哈尔滨东|VBB|haerbindong|hebd|32@hex|哈尔滨西|VAB|haerbinxi|hebx|33@hfe|合肥|HFH|hefei|hf|34@hfx|合肥西|HTH|hefeixi|hfx|35@hhd|呼和浩特东|NDC|huhehaotedong|hhhtd|36@hht|呼和浩特|HHC|huhehaote|hhht|37@hkd|海口东|HMQ|haikoudong|hkd|38@hko|海口|VUQ|haikou|hk|39@hzd|杭州东|HGH|hangzhoudong|hzd|40@hzh|杭州|HZH|hangzhou|hz|41@hzn|杭州南|XHH|hangzhounan|hzn|42@jna|济南|JNK|jinan|jn|43@jnd|济南东|JAK|jinandong|jnd|44@jnx|济南西|JGK|jinanxi|jnx|45@kmi|昆明|KMM|kunming|km|46@kmx|昆明西|KXM|kunmingxi|kmx|47@lsa|拉萨|LSO|lasa|ls|48@lzd|兰州东|LVJ|lanzhoudong|lzd|49@lzh|兰州|LZJ|lanzhou|lz|50@lzx|兰州西|LAJ|lanzhouxi|lzx|51@nch|南昌|NCG|nanchang|nc|52@nji|南京|NJH|nanjing|nj|53@njn|南京南|NKH|nanjingnan|njn|54@nni|南宁|NNZ|nanning|nn|55@sjb|石家庄北|VVP|shijiazhuangbei|sjzb|56@sjz|石家庄|SJP|shijiazhuang|sjz|57@sya|沈阳|SYT|shenyang|sy|58@syb|沈阳北|SBT|shenyangbei|syb|59@syd|沈阳东|SDT|shenyangdong|syd|60@tyb|太原北|TBV|taiyuanbei|tyb|61@tyd|太原东|TDV|taiyuandong|tyd|62@tyu|太原|TYV|taiyuan|ty|63@wha|武汉|WHN|wuhan|wh|64@wjx|王家营西|KNM|wangjiayingxi|wjyx|65@wln|乌鲁木齐南|WMR|wulumuqinan|wlmqn|66@xab|西安北|EAY|xianbei|xab|67@xan|西安|XAY|xian|xa|68@xan|西安南|CAY|xiannan|xan|69@xni|西宁|XNO|xining|xn|70@ych|银川|YIJ|yinchuan|yc|71@zzh|郑州|ZZF|zhengzhou|zz|72@aes|阿尔山|ART|aershan|aes|73@aka|安康|AKY|ankang|ak|74@aks|阿克苏|ASR|akesu|aks|75@alh|阿里河|AHX|alihe|alh|76@alk|阿拉山口|AKR|alashankou|alsk|77@api|安平|APT|anping|ap|78@aqi|安庆|AQH|anqing|aq|79@ash|安顺|ASW|anshun|as|80@ash|鞍山|AST|anshan|as|81@aya|安阳|AYF|anyang|ay|82@ban|北安|BAB|beian|ba|83@bbu|蚌埠|BBH|bengbu|bb|84@bch|白城|BCT|baicheng|bc|85@bha|北海|BHZ|beihai|bh|86@bhe|白河|BEL|baihe|bh|87@bji|白涧|BAP|baijian|bj|88@bji|宝鸡|BJY|baoji|bj|89@bji|滨江|BJB|binjiang|bj|90@bkt|博克图|BKX|boketu|bkt|91@bse|百色|BIZ|baise|bs|92@bss|白山市|HJL|baishanshi|bss|93@bta|北台|BTT|beitai|bt|94@btd|包头东|BDC|baotoudong|btd|95@bto|包头|BTC|baotou|bt|96@bts|北屯市|BXR|beitunshi|bts|97@bxi|本溪|BXT|benxi|bx|98@byb|白云鄂博|BEC|baiyunebo|byeb|99@byx|白银西|BXJ|baiyinxi|byx|100@bzh|亳州|BZH|bozhou|bz|101@cbi|赤壁|CBN|chibi|cb|102@cde|常德|VGQ|changde|cd|103@cde|承德|CDP|chengde|cd|104@cdi|长甸|CDT|changdian|cd|105@cfe|赤峰|CFD|chifeng|cf|106@cli|茶陵|CDG|chaling|cl|107@cna|苍南|CEH|cangnan|cn|108@cpi|昌平|CPP|changping|cp|109@cre|崇仁|CRG|chongren|cr|110@ctu|昌图|CTT|changtu|ct|111@ctz|长汀镇|CDB|changtingzhen|ctz|112@cxi|曹县|CXK|caoxian|cx|113@cxi|楚雄|COM|chuxiong|cx|114@cxt|陈相屯|CXT|chenxiangtun|cxt|115@czb|长治北|CBF|changzhibei|czb|116@czh|长征|CZJ|changzheng|cz|117@czh|池州|IYH|chizhou|cz|118@czh|常州|CZH|changzhou|cz|119@czh|郴州|CZQ|chenzhou|cz|120@czh|长治|CZF|changzhi|cz|121@czh|沧州|COP|cangzhou|cz|122@czu|崇左|CZZ|chongzuo|cz|1
|
|
|
|
|
|
|
|
|
|
public static function getName($val = ''){
|
|
|
|
|
if(empty($val)){ return false; }
|
|
|
|
|
$pattern = '/'.$val.'\|([A-Z]+)\|/';
|
|
|
|
|
preg_match($pattern, self::STATICON_NAMES, $matches);
|
|
|
|
|
return isset($matches[1]) ? $matches[1] : false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 地名处理类 End
|
|
|
|
|
?>
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<title>火车票检漏脚本 - By v1.0</title>
|
|
|
|
|
<meta charset="UTF-8" />
|
|
|
|
|
<style type="text/css">
|
|
|
|
|
*{margin:0;padding:0;}
|
|
|
|
|
body{font-size:12px; font-family: "Helvetica Neue", "Hiragino Sans GB", "Segoe UI", "Microsoft Yahei", "微软雅黑", Tahoma, Arial, STHeiti, sans-serif; }
|
|
|
|
|
a{text-decoration:none; color:#459ae9; margin:0 5px;}
|
|
|
|
|
.hidden{display:none;}
|
|
|
|
|
.wrap{width:980px; height:auto; margin:0 auto;}
|
|
|
|
|
|
|
|
|
|
div.title{height:100px; line-height:100px; text-align:center; margin-top:20px;}
|
|
|
|
|
div.title h1{font-size:24px;}
|
|
|
|
|
|
|
|
|
|
div.block{width:100%; margin-top:20px;}
|
|
|
|
|
div.block h2{font-size:14px; line-height:32px; padding-left:10px;}
|
|
|
|
|
div.block h2 p{float:right; padding-right:10px;}
|
|
|
|
|
div.block h2 p span{font-weight:200;padding-left:5px;}
|
|
|
|
|
div.block table{width:100%;border-collapse:collapse;border-spacing:0;}
|
|
|
|
|
div.block table tr td,div.block table tr th{border:1px solid #ddd; padding:8px 10px;background-color:#eee;}
|
|
|
|
|
.input-txt{width:100%; height:22px; line-height:22px;}
|
|
|
|
|
|
|
|
|
|
div.config_block table thead th:nth-of-type(1){width:150px; text-align:center;}
|
|
|
|
|
div.config_block table thead th:nth-of-type(3){width:145px; text-align:center;}
|
|
|
|
|
div.config_block table tbody tr td:nth-of-type(1){text-align:right;}
|
|
|
|
|
|
|
|
|
|
div.api_block table thead th:nth-of-type(1){width:20px; text-align:center;}
|
|
|
|
|
div.api_block table tbody tr td:nth-of-type(1){text-align:center;}
|
|
|
|
|
|
|
|
|
|
div.api_block table thead th:nth-of-type(2){width:30px; text-align:center;}
|
|
|
|
|
div.api_block table tbody tr td:nth-of-type(2){text-align:center;}
|
|
|
|
|
|
|
|
|
|
div.api_block table thead th:nth-of-type(3){ text-align:center;}
|
|
|
|
|
div.api_block table tbody tr td:nth-of-type(3){text-align:left;}
|
|
|
|
|
|
|
|
|
|
div.api_block table thead th:nth-of-type(5),div.api_block table thead th:nth-of-type(6){text-align:center;}
|
|
|
|
|
div.api_block table tbody tr td:nth-of-type(5){text-align:center;}
|
|
|
|
|
div.api_block table tbody tr td:nth-of-type(6){text-align:center;}
|
|
|
|
|
|
|
|
|
|
div.api_block table tbody tr td:nth-of-type(5) > strong{font-weight:400; font-size:16px;}
|
|
|
|
|
|
|
|
|
|
div.api_block table thead th:nth-of-type(7){ text-align:center;}
|
|
|
|
|
div.api_block table tbody tr td:nth-of-type(7){text-align:center;}
|
|
|
|
|
|
|
|
|
|
footer{width:100%; height:100px; line-height:100px; text-align:center;}
|
|
|
|
|
.dosubmit{background-color:#ffb000; padding:6px 20px; text-shadow:1px 1px 0 #cf7000; border:solid 1px #e77c00; font-family: "Microsoft YaHei", SimSun, Tahoma, Verdana, Arial, sans-serif; font-size:16px; color:#FFF; cursor:pointer;font-weight:bold;letter-spacing:0.4em;text-indent:0.4em;box-shadow: 0 1px 0 rgba(95,50,0,0.7);border-radius:3px;}
|
|
|
|
|
|
|
|
|
|
/* ======================================= */
|
|
|
|
|
.box{width:52%; height:55%; position:fixed; left:50%; top:50%; border:5px solid #ccc; background-color:#FFF; margin-top:-16%; margin-left:-26%;overflow:hidden; display:none;}
|
|
|
|
|
.box-title{width:100%; height:30px; line-height: 30px;background-color:#3385ff;}
|
|
|
|
|
.box-title span{foont-size:14px; font-weight:bold; color:#FFF; padding-left:10px; float:left;}
|
|
|
|
|
.box-title strong{foont-size:14px; font-weight:bold; color:#FFF; padding-right:5px; float:right;}
|
|
|
|
|
.box-title strong a{color:#FFF;}
|
|
|
|
|
.box-content{width:100%; height:100%;}
|
|
|
|
|
.box-textarea{width:100%; height:100%; font-size:12px; line-height:16px;}
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
|
|
|
|
|
<div class="wrap">
|
|
|
|
|
<header>
|
2016-08-09 13:32:51 +08:00
|
|
|
<div class="title"><h1>火车票检漏脚本 - By v1.1</h1></div>
|
2016-07-20 09:29:42 +08:00
|
|
|
</header>
|
|
|
|
|
<content>
|
|
|
|
|
|
|
|
|
|
<div class="block api_block">
|
|
|
|
|
<h2>查询信息<br />
|
|
|
|
|
出行时间:<?php echo $date; ?><br />
|
|
|
|
|
出发地:<?php echo $from; ?><br />
|
|
|
|
|
目的地:<?php echo $to; ?><br />
|
|
|
|
|
</h2>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- API 区域 -->
|
|
|
|
|
<div class="block api_block">
|
|
|
|
|
<h2>可购买车次列表 <p></h2>
|
|
|
|
|
<table>
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>序</th>
|
|
|
|
|
<th>车次</th>
|
|
|
|
|
<th>行程</th>
|
|
|
|
|
<th>发车时间</th>
|
|
|
|
|
<th>硬卧</th>
|
|
|
|
|
<th>硬座</th>
|
|
|
|
|
<th>二等座</th>
|
|
|
|
|
<th>一等座</th>
|
|
|
|
|
<th>操作</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<?php if(M::$buyArr): foreach(M::$buyArr as $item): ?>
|
|
|
|
|
<tr>
|
|
|
|
|
<td></td>
|
|
|
|
|
<td><?php echo U::getValue($item,'station_train_code');?></td>
|
|
|
|
|
<td><?php echo U::getValue($item,'from_station_name'),' == ',U::getValue($item,'to_station_name'); ?></td>
|
|
|
|
|
<td><?php echo U::getValue($item,'start_time');?></td>
|
|
|
|
|
<td><?php echo U::getValue($item,'yw_num');?></td>
|
|
|
|
|
<td><?php echo U::getValue($item,'yz_num');?></td>
|
|
|
|
|
<td><?php echo U::getValue($item,'ze_num');?></td>
|
|
|
|
|
<td><?php echo U::getValue($item,'zy_num');?></td>
|
|
|
|
|
<td><a href="javascript:;" onclick="mySubmitForm('<?php echo U::getValue($item,'from_station_name');?>','<?php echo U::getValue($item,'to_station_name');?>','<?php echo U::getValue($item,'from_station_telecode');?>','<?php echo U::getValue($item,'to_station_telecode');?>','<?php echo $date;?>');">立即购买</a></td>
|
|
|
|
|
</tr>
|
|
|
|
|
<?php endforeach; endif; ?>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- API 区块 End -->
|
|
|
|
|
</content>
|
|
|
|
|
|
|
|
|
|
<footer>
|
2016-08-09 13:32:51 +08:00
|
|
|
<p><strong>©</strong><a href="https://www.56br.com/" target="_blank">Wanglele</a><span>版权所有</span></p>
|
2016-07-20 09:29:42 +08:00
|
|
|
</footer>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<form method="post" name="MyForm" id="MyForm" class="MyForm" action="https://kyfw.12306.cn/otn/leftTicket/init" target="_blank">
|
|
|
|
|
<input type="hidden" id="from_station_name" name="leftTicketDTO.from_station_name" value="北京" />
|
|
|
|
|
<input type="hidden" id="to_station_name" name="leftTicketDTO.to_station_name" value="襄阳" />
|
|
|
|
|
<input type="hidden" id="from_station" name="leftTicketDTO.from_station" value="BJP" />
|
|
|
|
|
<input type="hidden" id="to_station" name="leftTicketDTO.to_station" value="XFN" />
|
|
|
|
|
<input type="hidden" id="train_date" name="leftTicketDTO.train_date" value="2016-02-04" />
|
|
|
|
|
|
|
|
|
|
<input type="hidden" name="back_train_date" value="" />
|
|
|
|
|
<input type="hidden" name="flag" value="wf" />
|
|
|
|
|
<input type="hidden" name="purpose_code" value="ADULT" />
|
|
|
|
|
<input type="hidden" name="pre_step_flag" value="index" />
|
|
|
|
|
</form>
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
function g($str){ return document.querySelector($str); }
|
|
|
|
|
|
|
|
|
|
function mySubmitForm(from_station_name,to_station_name,from_station,to_station,train_date){
|
|
|
|
|
g("#from_station_name").value = from_station_name;
|
|
|
|
|
g("#to_station_name").value = to_station_name;
|
|
|
|
|
g("#from_station").value = from_station;
|
|
|
|
|
g("#to_station").value = to_station;
|
|
|
|
|
g("#train_date").value = train_date;
|
|
|
|
|
|
|
|
|
|
g("#MyForm").submit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
2016-08-09 13:32:51 +08:00
|
|
|
|