12306列车时刻表查询api功能实现

您所在的位置:网站首页 查询铁路车次信息的网站 12306列车时刻表查询api功能实现

12306列车时刻表查询api功能实现

2024-07-11 16:27| 来源: 网络整理| 查看: 265

最近乘坐火车,在车上像快要看看列车时刻表,大概知道什么时间到达什么车站,起初是每次都打开12306APP查询,然后感觉每次打开APP很麻烦,就去微信小程序里边搜索,果然有我们伟大的猿类同胞做了这件事。于是乎,我就想12306是不是有开放平台提供了接口供我们使用,查了查竟然没有,聚合数据有此类接口(https://www.juhe.cn/docs/api/id/22),还是收费的。身为一个勤劳好学的猿,必须要亲自试一试。在查了查信息,看了一些前辈们的资料,自己终于也简单实现了。

1.获取全国所有车站 获取车站的目的是拿到全国所有车站的电码信息编号,后续需要用到。

/** * 车站的电码信息编号 * 数据格式:@bjb|北京北|VAP|beijingbei|bjb|0 * 车站名缩写:bjb * 车站名称:北京北 * 车站电码编号:VAP * 车站数字编号:0 * author 江南极客 */ function get_station_code(){ $url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js'; $data = curl_request($url); if(!$data){ msgReturn('获取数据失败',-1); } //var station_names ='@bjb|北京北|VAP|beijingbei|bjb|0...'; $station_data = strrchr($data,'='); $station_name = ltrim($station_data,"='@"); $station_name = rtrim($station_name,"';"); $station_arr = explode('@',$station_name); if(empty($station_arr)){ msgReturn('获取数据失败',-1); } return $station_arr; }

由于车站信息需要做查询,所以我将数据爬出来存入数据库。

/** * 导入车站信息(至数据库) * author 江南极客 * @return array */ function import_train_station(){ $station_arr = get_station_code(); $station_data = array(); $time = date('Y-m-d H:i:s'); $month = date('n'); $db_config = array( 'hostname' => '127.0.0.1', 'username' => 'root', 'password' => 'root', 'database' => 'dmx_train', 'pconnect' => 0, 'log' => 0 ); $db = new DB($db_config); $update = false; //是否要更新数据 //数据一个月更新一次 $one_sql = 'select * from dmx_station_info where update_month='.$month; $curr_month_data = $db->get_one($one_sql); if(empty($curr_month_data)){ //当前月份没有数据,则截断表然后插入数据 $update = true; $truncate_sql = 'TRUNCATE dmx_station_info'; $db->query($truncate_sql); } foreach ($station_arr as $item){ $temp = explode('|',$item); $temp_arr = array( 'station_no' => $temp[5], 'station_abbr' => $temp[0], 'station_name' => $temp[1], 'station_telecode' => $temp[2], 'ch_pinyin' => $temp[3], 'simp_pinyin' => $temp[4], 'origin_info' => $item, 'update_time' => $time, 'update_month' => $month, ); $station_data[] = $temp_arr; if($update){ $db->insert('dmx_station_info',$temp_arr); } } return $station_data; }

导入数据库后的数据如下:

车站信息

2.拿到12306月排班表所有的车次信息 铁道部每日排班车次1万多条数据,每月30多万,一次取出来数据30多万条数据大概23M多,程序很容易就请求超时,可以取出来然后做缓存一个月更新一次。

/** * 通过12306月排班表拿到所有的车次信息 * 铁道部 每日排班车次1万多条数据 , 每月30多万 , 一次取出来数据量非常庞大,可以取出来然后做缓存一个月更新一次 * author 江南极客 * @return mixed */ function get_train_list(){ $cache_file = __DIR__.'/train_list.json'; CHECKFILE: if(file_exists($cache_file)){ $cache_time = filemtime($cache_file); $month = date('n'); //一个月缓存一次 if(date('n',$cache_time) != $month){ @unlink($cache_file); goto CHECKFILE; } $train_list = file_get_contents($cache_file); }else{ $url = 'https://kyfw.12306.cn/otn/resources/js/query/train_list.js?scriptVersion=1.0'; $data = curl_request($url); $train_data = strrchr($data,'='); $train_list = ltrim($train_data,"="); $train_list = rtrim($train_list,","); @file_put_contents($cache_file,$train_list); } $train_arr = json_decode($train_list,true); return $train_arr; }

同样的为了便于查询,将数据爬出来存入数据库。一次取出来30多条数据,处理数据然后插入数据库,如果一次性做,就会超时,所以我使用了比较笨的方法:一次只操作一天的数据,可以循环倒入。

/** * 导入车次信息(至数据库) * author 江南极客 */ function import_train_list(){ //数据库配置 $db_config = array( 'hostname' => '127.0.0.1', 'username' => 'root', 'password' => 'root', 'database' => 'dmx_train', 'pconnect' => 0, 'log' => 0 ); $db = new DB($db_config); //获取一个月内列车排班信息列表 $station_arr = get_train_list(); $station_arr_count = count($station_arr); //一次取出来 一个月的信息 一次只操作一天的数据 $temp_times = 'youqijun'; session_start() ; if(isset($_SESSION[$temp_times])){ $temp = $_SESSION[$temp_times]; $temp += 1; $_SESSION[$temp_times] = $temp; }else{ $temp = 0; $_SESSION[$temp_times] = $temp; } if($temp >= $station_arr_count){ msgReturn('导入完毕',-1); } //截取数组的一部分(一次取一天的数据) $station_arr = array_slice($station_arr,$temp,1); if(empty($station_arr)){ msgReturn('暂无数据',-1); } $temp_arr = array(); $pattern = "/^(.*?)\((.*?)\-(.*?)\)$/"; $month = date('n'); foreach ($station_arr as $key1 => $date_arr){ $time = $key1; foreach ($date_arr as $key2 => $train_arr){ $type = $key2; foreach ($train_arr as $train){ $train['train_date'] = $time.' 00:00:00'; $train['train_type'] = $type; $train['update_month'] = $month; //K580(长沙-成都东) 匹配出车次 和 始发站,终到站 preg_match_all($pattern, $train['station_train_code'], $match); //$train_sn = strstr($train['station_train_code'],'(',true); $train['train_sn'] = $match[1][0]; $train['from_station'] = $match[2][0]; $train['to_station'] = $match[3][0]; $train['between_station'] = $match[2][0].'-'.$match[3][0]; $temp_arr[] = $train; $db->insert('dmx_train_list',$train); } } } print_r($temp_arr); }

导入数据库后的数据如下:

车次信息

3.获取列车运行时刻表 (1)通过车次和日期 , 在步骤2的数据中拿到该车次的始发站,终点站和车次编码 (2)在步骤1的数据中,拿到始发站和终点站的电码信息编号 (3)调用接口拿到该车次运行时刻信息

/** * 获取列车时刻表 * @param string $train_sn 车次(如:G1207) * @param string $date 日期 * train_no: 车次编号 * from_station_telecode: 起始站点的电码编号 * to_station_telecode: 目的站点的电码编号 * depart_date: 查询日期 * author 江南极客 * @return mixed */ function get_train_timetable($train_sn='',$date=''){ $url = 'https://kyfw.12306.cn/otn/czxx/queryByTrainNo?'; if(empty($train_sn)){ msgReturn('请填写车次',-1); } if(empty($date)) { $date = date('Y-m-d'); }else{ $date_str = strtotime($date); $date = date('Y-m-d',$date_str); } $db_config = array( 'hostname' => '127.0.0.1', 'username' => 'root', 'password' => 'root', 'database' => 'dmx_train', 'pconnect' => 0, 'log' => 0 ); $db = new DB($db_config); $train_date = $date.' 00:00:00'; $train_sn = strtoupper($train_sn); //根据输入的车次 拿到 车次排班编号,始发站和终到站 $train_sql = "select * from dmx_train_list where train_sn='{$train_sn}' and train_date='{$train_date}'"; $train = $db->get_one($train_sql); if(empty($train)){ msgReturn('未查到当日当次列车信息',-1); } //取出始发站和终到站的电码编号 $from_station_name = $train['from_station']; $to_station_name = $train['to_station']; $from_station_sql = "select * from dmx_station_info where station_name='{$from_station_name}'"; $to_station_sql = "select * from dmx_station_info where station_name='{$to_station_name}'"; $from_station = $db->get_one($from_station_sql); if(empty($from_station)){ msgReturn('未查到始发车站',-1); } $to_station = $db->get_one($to_station_sql); if(empty($to_station)){ msgReturn('未查到终点车站',-1); } $param = [ 'train_no' => $train['train_no'], 'from_station_telecode' => $from_station['station_telecode'], 'to_station_telecode' => $to_station['station_telecode'], 'depart_date' => $date, ]; $http_param = http_build_query($param); $url = $url.$http_param; $header = array('User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'); $data = curl_request($url,true,'GET',null,$header); if(!$data){ msgReturn('网络错误',-1); } $data = json_decode($data,true); if(empty($data['data']['data'])){ msgReturn('列车时刻表数据不存在',-1); } return $data['data']['data']; }

附:存储车站信息和车次信息的数据库DDL:

CREATE TABLE IF NOT EXISTS `dmx_station_info` ( `id` INT(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, `station_no` INT(6) NOT NULL DEFAULT '0' COMMENT '车站编号', `station_abbr` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '车站缩写', `station_name` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '车站名称', `station_telecode` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '车站电码编号', `ch_pinyin` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '车站拼音', `simp_pinyin` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '车站简拼', `origin_info` varchar(128) NOT NULL DEFAULT '' COMMENT '原始信息', `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '更新时间', `update_month` tinyint(2) NOT NULL DEFAULT '0' COMMENT '更新月份', KEY `inx_no`(`station_no`), KEY `inx_telecode`(`station_telecode`) ) ENGINE = MyISAM DEFAULT CHARSET=utf8 COMMENT='车站信息表'; CREATE TABLE IF NOT EXISTS `dmx_train_list` ( `id` INT(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, `station_train_code` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '车次信息', `train_no` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '车次编号', `train_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '发车时间', `train_type` CHAR(1) NOT NULL DEFAULT '' COMMENT '类型(K D G)', `train_sn` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '车次', `from_station` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '始发站', `to_station` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '终到站', `between_station` varchar(32) NOT NULL DEFAULT '' COMMENT '始发-终到', `update_month` tinyint(2) NOT NULL DEFAULT '0' COMMENT '更新月份', KEY `inx_no`(`train_no`), KEY `inx_sn`(`train_sn`) ) ENGINE = MyISAM DEFAULT CHARSET=utf8 COMMENT='车次信息表';

简单写个界面,就可以查到信息啦:

附:源码(一个单文件搞定)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3