摘要

本文讲解12306网站接口查询火车时刻表信息
接口中用到的方法在文章最后

一、 根据车次查询内部火车编号

接口:https://search.12306.cn/search/v1/train/search
参数: keyword, date
请求类型: GET

/*** 根据车次名称查询列车编号* @param keyword 车次名* @param date 发车日期 (格式: yyyyMMdd)*/
private List<TrainInfo> searchTrainInfos(String keyword, String date) {date = checkTrainSearchDate(date, "yyyyMMdd")String response = HttpUtils.sendGet("https://search.12306.cn/search/v1/train/search","keyword=" + keyword.trim() + "&date=" + date);JSONObject object = new JSONObject(response);if (object.optBoolean("status")) {JSONArray data = object.optJSONArray("data");if (data != null) {return JSON.parseArray(data.toString(), TrainInfo.class);}}throw new RuntimeException("未查询到车次信息. " + object.optString("errorMsg"));
}

列车信息实体类 TrainInfo

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;import java.io.Serializable;/*** 车次信息*/
@Data
public class TrainInfo implements Serializable {private String date ;@JsonProperty(value = "from_station")private String fromStation ;@JsonProperty(value = "station_train_code")private String stationTrainCode ;@JsonProperty(value = "to_station")private String toStation ;@JsonProperty(value = "total_num")private String totalNum ;@JsonProperty(value = "train_no")private String trainNo ;
}

二、 根据列车编号查询时刻表信息

接口:https://kyfw.12306.cn/otn/queryTrainInfo/query
参数: trainNo, date
请求类型: GET

/*** 根据列车编号查询时刻表信息* @param trainNo 列车编号, 是上面接口返回数据中心的train_no* @param date 查询日期 (格式: yyyy-MM-dd)*/
private List<TrainStation> searchTrainStations(String trainNo, String date) {if (StringUtils.isBlank(trainNo)) {throw new RuntimeException("未查询到相关列车信息");}date = checkTrainSearchDate(date, "yyyy-MM-dd");String response = HttpUtils.sendGet("https://kyfw.12306.cn/otn/queryTrainInfo/query","leftTicketDTO.train_no="+ trainNo +"&leftTicketDTO.train_date="+date +"&rand_code=");JSONObject object = new JSONObject(response);if (object.optBoolean("status")) {JSONObject jsonObject = object.optJSONObject("data");if (jsonObject != null) {JSONArray array = jsonObject.optJSONArray("data");if (array != null) {List<TrainStation> list = JSON.parseArray(array.toString(), TrainStation.class);TrainStation station = list.get(0);list.forEach(i -> {i.setStartStationName(station.getStartStationName());i.setEndStationName(station.getEndStationName());i.setTrainClassName(station.getTrainClassName());});return list;}}}throw new RuntimeException("未查询到相关列车信息. " + JSON.toJSONString(object.opt("messages")));
}

列车到站时刻详情


import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;import java.io.Serializable;
import java.util.List;/*** 列车到站时刻详情* @author xyang* @date 2021-08-02 9:15*/
@Data
public class TrainStation implements Serializable {/** 车站名称 */@JsonProperty(value = "station_name")private String stationName;/** 列车类型 */@JsonProperty(value = "train_class_name")private String trainClassName;/** 是否起始站 (y/n)*/@JsonProperty(value = "is_start")private String isStart;@JsonProperty(value = "service_type")private String serviceType;/** 起始站点名称 */@JsonProperty(value = "start_station_name")private String startStationName;/** 终点站名称 */@JsonProperty(value = "end_station_name")private String endStationName;/** 发车时间 */@JsonProperty(value = "start_time")private String startTime;/** 到站时间 */@JsonProperty(value = "arrive_time")private String arriveTime;/** 车次编号 */@JsonProperty(value = "station_train_code")private String stationTrainCode;/** 到站顺序 */@JsonProperty(value = "station_no")private String stationNo;@JsonProperty(value = "wz_num")private String wzNum;/** 到站历时天数 (0:当天, 1:次日, 2:第三日, ....) */@JsonProperty(value = "arrive_day_diff")private Integer arriveDayDiff;/** 历时时长 */@JsonProperty(value = "running_time")private String runningTime;/** 历时 (当日到达, 次日到达...)*/@JsonProperty(value = "arrive_day_str")private String arriveDayStr;@JsonProperty(value = "OT")private List<Object> ot;
}

其他

时间校验 checkTrainSearchDate

/*** 校验时间格式是否正确, 并将字符串转为日期(防止日期格式未按要求)* @param date 日期字符串* @param format 描述日期和时间格式的模式*/
private String checkTrainSearchDate(String date, String format) {if(StringUtils.isBlank(date)) {throw new RuntimeException("查询日期不能为空!");}if(StringUtils.isBlank(format)) {throw new RuntimeException("日期格式化参数错误!");}Date parseDate = DateUtils.parseDate(date);if (parseDate == null) {throw new RuntimeException("查询日期格式校验错误!");}if (DateUtils.truncatedCompareTo(parseDate, new Date(), Calendar.DATE) < 0) {throw new RuntimeException("查询日期不能早于当前日期");}return DateUtils.dateFormat(parseDate, format);
}

时间工具类 DateUtils

// 时间工具类
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {public static String YYYY = "yyyy";public static String YYYY_MM = "yyyy-MM";public static String YYYY_MM_DD = "yyyy-MM-dd";public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM","yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM","yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};/*** 格式化日期*/public static String dateFormat(Date date,String format) {try {SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);if(ObjectUtils.isEmpty(date)){date = new Date();}return simpleDateFormat.format(date);}catch (Exception e){e.printStackTrace();throw new RuntimeException("日期格式化失败");}}/*** 日期型字符串转化为日期 格式*/public static Date parseDate(Object str) {if (str == null) {return null;}try{return parseDate(str.toString(), parsePatterns);}catch (ParseException e){return null;}}
}

**通用http发送方法 HttpUtils **


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;/*** 通用http发送方法** @author ruoyi*/
public class HttpUtils {private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);/*** 向指定 URL 发送GET方法的请求** @param url   发送请求的 URL* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。* @return 所代表远程资源的响应结果*/public static String sendGet(String url, String param) {return sendGet(url, param, "UTF-8");}/*** 向指定 URL 发送GET方法的请求** @param url         发送请求的 URL* @param param       请求参数,请求参数应该是 name1=value1&name2=value2 的形式。* @param contentType 编码类型* @return 所代表远程资源的响应结果*/public static String sendGet(String url, String param, String contentType) {StringBuilder result = new StringBuilder();BufferedReader in = null;try {String urlNameString = url + "?" + param;log.info("sendGet - {}", urlNameString);URL realUrl = new URL(urlNameString);URLConnection connection = realUrl.openConnection();connection.setRequestProperty("accept", "*/*");connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");connection.connect();in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));String line;while ((line = in.readLine()) != null) {result.append(line);}log.info("recv - {}", result);} catch (ConnectException e) {log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);} catch (SocketTimeoutException e) {log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);} catch (IOException e) {log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);} catch (Exception e) {log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);} finally {try {if (in != null) {in.close();}} catch (Exception ex) {log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);}}return result.toString();}/*** 向指定 URL 发送POST方法的请求** @param url   发送请求的 URL* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。* @return 所代表远程资源的响应结果*/public static String sendPost(String url, String param) {PrintWriter out = null;BufferedReader in = null;StringBuilder result = new StringBuilder();try {log.info("sendPost - {}", url);URL realUrl = new URL(url);URLConnection conn = realUrl.openConnection();conn.setRequestProperty("accept", "*/*");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");conn.setRequestProperty("Accept-Charset", "utf-8");conn.setRequestProperty("contentType", "utf-8");conn.setDoOutput(true);conn.setDoInput(true);out = new PrintWriter(conn.getOutputStream());out.print(param);out.flush();in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));String line;while ((line = in.readLine()) != null) {result.append(line);}log.info("recv - {}", result);} catch (ConnectException e) {log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);} catch (SocketTimeoutException e) {log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);} catch (IOException e) {log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);} catch (Exception e) {log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);} finally {try {if (out != null) {out.close();}if (in != null) {in.close();}} catch (IOException ex) {log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);}}return result.toString();}}

12306火车时刻表查询接口相关推荐

  1. 全国铁路查询系统_火车票查询时刻表 全国列车时刻表 火车时刻表查询系统使用说明...

    春运来了,快过年了, 又到一年中最一票难求的时候了,在外辛辛苦苦打拼了一年,为了让大家尽早的和亲朋好友家人团聚,本人今年很英勇的出来帮大家代抢火车票啦! 特地为大家建立了一个捡漏票微信群, 加微信qq ...

  2. 快春运了,做个火车余票查询接口,余票来源12306,图是百度地图

    摘要:做个火车票查询余票接口,数据来源于12306,地图使用百度地图(未完成) 今天本来想查询一下回家的车票,结果坑爹的发现12306网站死活打不开,尼玛真实坑爹,想查询一下余票都怎么难 于是自己决定 ...

  3. 做个火车余票查询接口,余票来源12306,图是百度地图

    摘要:做个火车票查询余票接口,数据来源于12306,地图使用百度地图(未完成) 今天本来想查询一下回家的车票,结果坑爹的发现12306网站死活打不开,尼玛真实坑爹,想查询一下余票都怎么难 于是自己决定 ...

  4. 12306火车余票查询

    测试地址:http://gengjian.24.lc/japson/123060.htm 调用12306官网的查询接口. 123060.htm 火车票余票查询Demo By Genng.<br& ...

  5. 时刻表的选择php代码,基于php的火车时刻表接口调用代码实例

    基于php的火车时刻表接口调用代码实例 代码描述:基于php的火车时刻表接口调用代码实例 代码平台:聚合数据 // +----------------------------------------- ...

  6. 原创,PHP简单的查询火车时刻表程序

    01.<?php 02.//利用别人的网站自己写的一个查询火车时刻表的小程序 03.if(isset($_POST['cx'])){ 04.//拼写网址,测试能否顺利打开 05.$url = & ...

  7. 常用WebServices 天气,IP,邮编,Email,火车时刻表,股票 web接口服务

    天气预报Web服务,数据来源于中国气象局 Endpoint: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx Disco: ht ...

  8. 12306实时余票查询接口

    12306实时余票查询接口代码文档及返回示例,可查询实时火车票余票,包括车次.车次始发站.车次终点站.出发时间.到达时间.车次类型.总历时时间等等. 接口名称:12306实时余票查询接口 接口平台:聚 ...

  9. java保存火车票信息_java抓取12306火车余票信息

    最近在弄一个微信的公众帐号,涉及到火车票查询,之前用的网上找到的一个接口,但只能查到火车时刻表,12306又没有提供专门的查票的接口.今天突然想起自己直接去12306上查询,抓取查询返回的数据包,这样 ...

  10. 有道身份证查询接口API

    一.返回XML格式数据: 1)  接口地址:http://www.youdao.com/smartresult-xml/search.s?type=id&q=身份证号 2)  参数说明:q : ...

最新文章

  1. css position的父级,css position absolute 相对于父元素的设置方式
  2. 推荐7款Mac上能极大提高效率的软件,建议收藏!
  3. Python-S13-day2-之购物车
  4. 且看微软的.Net和Sun公司的J2EE如何对垒
  5. Java 把一个InputStream转换为一个BufferedReader
  6. idea重要插件代码颜色_颜色在您的网站上的重要性和品牌形象
  7. python实例讲解wxpythonhyh123_Python实例讲解 -- wxpython 基本的控件 (按钮)
  8. 关于mysql使用命令行时出现Data too long for column的解决方案:
  9. 电商生鲜网站开发(接口文档)
  10. 航信税控系统 - 安装分析(一)
  11. 两台计算机传输文件速度,两台电脑间如何快速传输几百个G的文件?使用这2个方法,方便极了...
  12. TypeError: from_buffer() cannot return the address of the raw string within a str or unicode or byte
  13. 12306抢票工具的使用
  14. mysql repeated read_mysql事务之可重复读(Repeated Read)
  15. 屏蔽iOS11 Xcode9下打印的乱七八糟的日志
  16. POI导入Excel文件(包含.xsl和.xslx文件兼容问题)
  17. netkeeper不能建立远程计算机连接,Netkeeper客户端常见问题集锦.doc
  18. 安卓手机去水印哪个好用
  19. 思维导图(XMind ZEN)安装教程
  20. Functions are not valid as a React child. This may happen if you return a Component instead of 「Comp

热门文章

  1. 理想,努力了才叫梦想,放弃了那只是妄想
  2. 新天龙官网服务器更新消息,《新天龙八部》1月20日全服更新维护公告
  3. 青出于蓝胜于蓝-(树状数组+DFS序)
  4. 美国服务器托管机房如何选择?
  5. Gis到底可以应用在哪些方面?
  6. linux加静态路由命令,LINUX添加静态路由
  7. GVR-Cardboard_DayDream
  8. java实现积分抽奖_java毕业设计_springboot框架的超市消费积分抽奖
  9. 【转】人不成熟的几大特征——海尔集团CEO张瑞敏演讲稿
  10. 逐行解析linux kernel NIC驱动