TrainQuery.API
2.0.0
dotnet add package TrainQuery.API --version 2.0.0
NuGet\Install-Package TrainQuery.API -Version 2.0.0
<PackageReference Include="TrainQuery.API" Version="2.0.0" />
<PackageVersion Include="TrainQuery.API" Version="2.0.0" />
<PackageReference Include="TrainQuery.API" />
paket add TrainQuery.API --version 2.0.0
#r "nuget: TrainQuery.API, 2.0.0"
#:package TrainQuery.API@2.0.0
#addin nuget:?package=TrainQuery.API&version=2.0.0
#tool nuget:?package=TrainQuery.API&version=2.0.0
TrainQuery.API - 12306火车票查询类库
📦 NuGet包信息
- 包名称: TrainQuery.API
- 当前版本: 2.0.0
- 作者: 孟煌喆
- 目标框架: .NET Framework 4.8.1
- 依赖项: Newtonsoft.Json (≥13.0.3)
🚀 快速开始
安装包
# Package Manager Console
Install-Package TrainQuery.API
# .NET CLI
dotnet add package TrainQuery.API
# PackageReference
<PackageReference Include="TrainQuery.API" Version="1.0.0" />
基础使用示例
using TrainQuery.API;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using (var service = new TrainQueryService())
{
// 订阅调试信息
service.DebugMessage += (sender, message) =>
Console.WriteLine($"[DEBUG] {DateTime.Now:HH:mm:ss} {message}");
// 1. 初始化车站数据(必须首先调用)
Console.WriteLine("正在初始化车站数据...");
bool initSuccess = await service.InitializeStationsAsync();
if (!initSuccess)
{
Console.WriteLine("车站数据初始化失败,请检查网络连接。");
return;
}
Console.WriteLine("车站数据初始化成功!");
// 2. 查询车票(示例:广州南 到 深圳北)
Console.WriteLine("\n正在查询车票...");
var tickets = await service.QueryDirectTicketsAsync(
fromStation: "广州南",
toStation: "深圳北",
date: "2026-01-21" // 更新为未来的日期
);
// 3. 显示结果
Console.WriteLine($"找到 {tickets.Count} 个车次");
if (tickets.Count > 0)
{
Console.WriteLine("前几个车次信息:");
foreach (var ticket in tickets)
{
Console.WriteLine($"\n车次: {ticket.TrainNo}");
Console.WriteLine($" 区间: {ticket.FromStation} → {ticket.ToStation}");
Console.WriteLine($" 时间: {ticket.DepartureTime} - {ticket.ArrivalTime}");
Console.WriteLine($" 历时: {ticket.Duration}");
Console.WriteLine($" 状态: {ticket.Status}");
// 显示有余票的座位
if (ticket.SeatAvailability != null)
{
foreach (var seat in ticket.SeatAvailability)
{
if (seat.Value != "无" && seat.Value != "--")
{
Console.WriteLine($" {seat.Key}: {seat.Value}");
}
}
}
}
}
}
Console.WriteLine("\n按任意键退出...");
Console.ReadKey();
}
}
📚 详细使用说明
1. 初始化服务
// 创建服务实例(推荐使用using语句确保资源释放)
using var service = new TrainQueryService();
// 可选:订阅调试信息
service.DebugMessage += (sender, message) =>
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {message}");
// 可选:订阅车站加载完成事件
service.StationsLoaded += (sender, count) =>
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 已加载 {count} 个车站");
2. 车站数据初始化
重要:必须首先调用此方法!
try
{
// 初始化车站数据
bool success = await service.InitializeStationsAsync();
if (!success)
{
// 初始化失败,可能是网络问题
Console.WriteLine("车站数据初始化失败,请检查网络连接");
return;
}
Console.WriteLine("车站数据初始化成功,可以开始查询。");
}
catch (Exception ex)
{
Console.WriteLine($"初始化过程中发生异常: {ex.Message}");
}
3. 查询直达车票
// 基本查询
var tickets = await service.QueryDirectTicketsAsync(
fromStation: "南京", // 出发站(中文站名)
toStation: "杭州东", // 到达站(中文站名)
date: "2026-01-22" // 日期格式:yyyy-MM-dd
);
// 过滤特定车次类型(例如只查高铁)
var gTickets = await service.QueryDirectTicketsAsync(
fromStation: "武汉",
toStation: "长沙南",
date: "2026-01-22",
trainTypes: new List<string> { "G" } // 可选:过滤车次类型 (G-高铁, D-动车, 等)
);
4. 查询中转换乘方案
// 查询从 成都东 到 西安北 的中转换乘方案
var transferSolutions = await service.QueryTransferSolutionsAsync(
fromStation: "成都东",
toStation: "西安北",
date: "2026-01-23"
);
Console.WriteLine($"找到 {transferSolutions?.Count ?? 0} 个中转方案");
if (transferSolutions != null && transferSolutions.Count > 0)
{
// 显示第一个方案详情
var firstSolution = transferSolutions[0];
Console.WriteLine($"\n推荐方案:在 {firstSolution.MiddleStationName} 中转");
Console.WriteLine($" 总旅行时间: {firstSolution.AllDuration}");
Console.WriteLine($" 中转等待: {firstSolution.WaitTime}");
Console.WriteLine($" 共 {firstSolution.Segments?.Count ?? 0} 段行程:");
if (firstSolution.Segments != null)
{
foreach (var segment in firstSolution.Segments)
{
Console.WriteLine($" • {segment.StationTrainCode}次:{segment.FromStationName} ({segment.StartTime}) → {segment.ToStationName} ({segment.ArriveTime}),历时 {segment.Duration}");
}
}
}
5. 查询票价信息
// 查询 G86 次列车 郑州东 到 北京西 的票价
var priceInfo = await service.QueryTicketPriceAsync(
trainNo: "G86", // 车次
fromStation: "郑州东", // 出发站
toStation: "北京西", // 到达站
date: "2026-01-24" // 日期
);
if (priceInfo?.Prices != null && priceInfo.Prices.Count > 0)
{
Console.WriteLine($"车次 {priceInfo.TrainNo} 票价信息 ({priceInfo.Prices.Count} 种席别):");
// 按价格排序显示
var sortedPrices = priceInfo.Prices.OrderBy(p => p.Value);
foreach (var price in sortedPrices)
{
if (price.Value > 0)
{
Console.WriteLine($" {price.Key}: ¥{price.Value:F1}");
}
}
}
else
{
Console.WriteLine("未查询到票价信息。");
}
6. 查询列车经停站
// 查询 D939 次列车 昆明南 到 贵阳北 区间的经停站
var stopStations = await service.QueryTrainStopStationsAsync(
trainNo: "D939", // 车次
fromStation: "昆明南", // 出发站
toStation: "贵阳北", // 到达站
date: "2026-01-25" // 日期
);
if (stopStations != null && stopStations.Count > 0)
{
Console.WriteLine($"车次 D939 经停站信息 (共 {stopStations.Count} 站):");
foreach (var station in stopStations)
{
string stationName = station.TryGetValue("station_name", out var name) ? name : "未知车站";
string arriveTime = station.TryGetValue("arrive_time", out var arrive) ? arrive : "--";
string startTime = station.TryGetValue("start_time", out var start) ? start : "--";
string stopTime = station.TryGetValue("stopover_time", out var stop) ? stop : "";
string timeInfo = arriveTime == "--" ? $"出发 {startTime}" : $"到达 {arriveTime}, 出发 {startTime}";
if (!string.IsNullOrEmpty(stopTime)) timeInfo += $", 停靠 {stopTime}";
Console.WriteLine($" · {stationName.PadRight(8)} : {timeInfo}");
}
}
🎯 进阶用法
Windows Forms 应用示例 (优化版)
using TrainQuery.API;
using System;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
public partial class MainForm : Form
{
private TrainQueryService _service;
private readonly string _logFilePath = "train_query_debug.log";
public MainForm()
{
InitializeComponent();
_service = new TrainQueryService();
// 订阅调试消息到文本框和日志文件
_service.DebugMessage += (sender, message) =>
{
var fullMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}";
// 更新UI线程上的文本框
if (txtDebug.InvokeRequired)
{
txtDebug.Invoke(new Action(() =>
txtDebug.AppendText(fullMessage + Environment.NewLine)));
}
else
{
txtDebug.AppendText(fullMessage + Environment.NewLine);
}
// 异步写入日志文件
Task.Run(() =>
System.IO.File.AppendAllText(_logFilePath, fullMessage + Environment.NewLine));
};
// 设置默认查询日期为明天
dtpDate.Value = DateTime.Now.AddDays(1);
}
private async void btnQuery_Click(object sender, EventArgs e)
{
try
{
// 禁用按钮防止重复查询
btnQuery.Enabled = false;
btnQuery.Text = "查询中...";
lblStatus.Text = "正在初始化并查询...";
dgvResults.Rows.Clear();
// 1. 初始化车站数据
lblStatus.Text = "正在初始化车站数据...";
if (!await _service.InitializeStationsAsync())
{
MessageBox.Show("车站数据初始化失败,请检查网络连接。", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 2. 查询车票
lblStatus.Text = $"正在查询 {txtFrom.Text} 到 {txtTo.Text} 的车票...";
var tickets = await _service.QueryDirectTicketsAsync(
txtFrom.Text.Trim(),
txtTo.Text.Trim(),
dtpDate.Value.ToString("yyyy-MM-dd")
);
// 3. 显示结果
dgvResults.Rows.Clear();
if (tickets != null && tickets.Count > 0)
{
foreach (var ticket in tickets)
{
// 构建座位信息字符串
string seatInfo = "";
if (ticket.SeatAvailability != null)
{
var availableSeats = ticket.SeatAvailability
.Where(kv => kv.Value != "无" && kv.Value != "--" && !string.IsNullOrEmpty(kv.Value))
.Select(kv => $"{kv.Key}:{kv.Value}");
seatInfo = string.Join(" ", availableSeats.Take(3)); // 最多显示3种座位
}
dgvResults.Rows.Add(
ticket.TrainNo,
ticket.FromStation,
ticket.ToStation,
ticket.DepartureTime,
ticket.ArrivalTime,
ticket.Duration,
ticket.Status,
seatInfo
);
}
lblStatus.Text = $"查询完成!找到 {tickets.Count} 个车次,双击行查看详情。";
}
else
{
lblStatus.Text = "未找到符合条件的车次。";
MessageBox.Show("未找到车次,请确认车站名称和日期是否正确。", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (ArgumentException argEx)
{
lblStatus.Text = "参数错误";
MessageBox.Show($"车站名称可能不正确: {argEx.Message}\n请使用标准车站名如'北京南'、'上海虹桥'。",
"输入错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (Exception ex)
{
lblStatus.Text = "查询失败";
MessageBox.Show($"查询过程中发生错误:\n{ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
btnQuery.Enabled = true;
btnQuery.Text = "查询车票";
}
}
// 双击车次查看详情
private async void dgvResults_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0 || e.RowIndex >= dgvResults.Rows.Count) return;
var trainNo = dgvResults.Rows[e.RowIndex].Cells["colTrainNo"].Value?.ToString();
var fromStation = dgvResults.Rows[e.RowIndex].Cells["colFromStation"].Value?.ToString();
var toStation = dgvResults.Rows[e.RowIndex].Cells["colToStation"].Value?.ToString();
if (string.IsNullOrEmpty(trainNo)) return;
var detailForm = new TrainDetailForm(_service, trainNo, fromStation, toStation, dtpDate.Value);
detailForm.ShowDialog();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
_service?.Dispose();
base.OnFormClosing(e);
}
}
ASP.NET Core MVC 示例
using TrainQuery.API;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
public class TrainController : Controller
{
// 查询页面
public IActionResult Index()
{
ViewBag.DefaultDate = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd");
return View();
}
// 处理查询请求 (API端点)
[HttpPost]
public async Task<IActionResult> QueryTickets([FromBody] QueryRequest request)
{
try
{
// 每个请求创建独立服务实例
using var service = new TrainQueryService();
// 可选的调试日志
// service.DebugMessage += (sender, msg) => _logger.LogInformation(msg);
// 初始化车站数据
if (!await service.InitializeStationsAsync())
{
return Json(new { success = false, error = "车站数据初始化失败" });
}
// 执行查询
var tickets = await service.QueryDirectTicketsAsync(
request.FromStation,
request.ToStation,
request.Date
);
// 返回JSON结果
return Json(new {
success = true,
count = tickets?.Count ?? 0,
data = tickets?.Take(50).ToList() // 限制返回数量
});
}
catch (Exception ex)
{
return Json(new {
success = false,
error = $"查询失败: {ex.Message}"
});
}
}
// 查询请求模型
public class QueryRequest
{
public string FromStation { get; set; }
public string ToStation { get; set; }
public string Date { get; set; }
}
}
⚠️ 重要注意事项
1. 初始化要求
必须首先调用 InitializeStationsAsync() 方法:
// ✅ 正确用法
using var service = new TrainQueryService();
await service.InitializeStationsAsync(); // 必须先调用
var tickets = await service.QueryDirectTicketsAsync(...);
// ❌ 错误用法(会抛出InvalidOperationException)
using var service = new TrainQueryService();
var tickets = await service.QueryDirectTicketsAsync(...); // 错误!未初始化
2. 异常处理最佳实践
try
{
using var service = new TrainQueryService();
// 可能抛出异常的调用
var tickets = await service.QueryDirectTicketsAsync("南京", "上海虹桥", "2026-01-20");
// 处理查询结果...
}
catch (ArgumentException ex)
{
// 参数错误,如车站不存在
Console.WriteLine($"参数错误: {ex.Message}");
Console.WriteLine("提示:请使用'上海虹桥'而非'上海',使用'北京南'而非'北京站'。");
}
catch (InvalidOperationException ex)
{
// 操作顺序错误,如未初始化
Console.WriteLine($"操作错误: {ex.Message}");
Console.WriteLine("提示:请确保在查询前调用InitializeStationsAsync()方法。");
}
catch (System.Net.Http.HttpRequestException ex)
{
// 网络错误或12306服务不可用
Console.WriteLine($"网络请求错误: {ex.Message}");
Console.WriteLine("提示:请检查网络连接,或稍后重试。");
}
catch (Exception ex)
{
// 其他未预期的错误
Console.WriteLine($"未知错误: {ex.Message}");
Console.WriteLine($"详细堆栈: {ex.StackTrace}");
}
3. 线程安全与服务生命周期
// ❌ 避免:在多线程中共享同一个实例
// TrainQueryService 不是线程安全的
// ✅ 推荐:为每个线程或HTTP请求创建独立的实例
public class MyService
{
public async Task<List<TicketInfo>> QueryAsync(string from, string to, string date)
{
// 每个方法调用创建新实例
using var service = new TrainQueryService();
await service.InitializeStationsAsync();
return await service.QueryDirectTicketsAsync(from, to, date);
}
}
// ✅ 在Web应用中,使用依赖注入的瞬态(Transient)生命周期
// Startup.cs或Program.cs中:
// services.AddTransient<TrainQueryService>();
4. 资源管理
// ✅ 推荐:使用using语句确保资源释放
using (var service = new TrainQueryService())
{
await service.InitializeStationsAsync();
var tickets = await service.QueryDirectTicketsAsync(...);
// 使用服务...
} // 此处自动调用Dispose()
// ✅ 或者:使用C# 8.0的using声明
using var service = new TrainQueryService();
await service.InitializeStationsAsync();
// 使用服务...
// 在作用域结束时自动Dispose
// ✅ 手动管理(如需更精细控制)
var service = new TrainQueryService();
try
{
await service.InitializeStationsAsync();
// 使用服务...
}
finally
{
service.Dispose(); // 确保资源释放
}
🔧 配置和优化
1. 网络超时与重试策略
// 自定义重试逻辑示例
public async Task<List<TicketInfo>> QueryWithRetry(string from, string to, string date, int maxRetries = 3)
{
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
try
{
using var service = new TrainQueryService();
await service.InitializeStationsAsync();
return await service.QueryDirectTicketsAsync(from, to, date);
}
catch (System.Net.Http.HttpRequestException) when (attempt < maxRetries)
{
// 网络错误时重试
Console.WriteLine($"第{attempt}次尝试失败,{ (maxRetries - attempt) }次重试剩余...");
await Task.Delay(1000 * attempt); // 递增延迟
}
}
throw new Exception($"查询失败,已重试{maxRetries}次");
}
2. 调试与日志记录
// 综合调试配置
service.DebugMessage += (sender, message) =>
{
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
var fullMessage = $"[{timestamp}] {message}";
// 1. 控制台输出
Console.WriteLine(fullMessage);
// 2. 调试窗口输出(在IDE中)
System.Diagnostics.Debug.WriteLine(fullMessage);
// 3. 记录到文件(带每日滚动)
var logFile = $"trainquery_debug_{DateTime.Now:yyyyMMdd}.log";
System.IO.File.AppendAllText(logFile, fullMessage + Environment.NewLine);
// 4. 发送到监控系统(可选)
// SendToMonitoringSystem(fullMessage);
};
3. 性能优化建议
// 1. 缓存车站数据(避免重复初始化)
private static TrainQueryService _cachedService;
private static DateTime _lastInitialized = DateTime.MinValue;
public async Task<TrainQueryService> GetInitializedServiceAsync()
{
if (_cachedService == null || (DateTime.Now - _lastInitialized).TotalMinutes > 30)
{
// 创建新实例并初始化
var service = new TrainQueryService();
if (await service.InitializeStationsAsync())
{
_cachedService = service;
_lastInitialized = DateTime.Now;
}
return service;
}
return _cachedService;
}
// 2. 批量查询多个日期
public async Task<Dictionary<string, List<TicketInfo>>> BatchQueryAsync(
string from, string to, IEnumerable<string> dates)
{
var results = new Dictionary<string, List<TicketInfo>>();
using var service = new TrainQueryService();
await service.InitializeStationsAsync();
// 注意:避免同时发起过多请求,可能触发限流
foreach (var date in dates)
{
try
{
var tickets = await service.QueryDirectTicketsAsync(from, to, date);
results[date] = tickets;
await Task.Delay(500); // 添加短暂延迟,避免请求过快
}
catch (Exception ex)
{
Console.WriteLine($"查询日期 {date} 时出错: {ex.Message}");
results[date] = new List<TicketInfo>();
}
}
return results;
}
🐛 常见问题解决
Q1: 出现"找不到车站代码"错误
原因: 车站名称不正确或车站数据未加载
解决:
- 确保已成功调用
InitializeStationsAsync()方法- 使用正确的中文站名(如"北京南"而非"北京","上海虹桥"而非"上海市虹桥站")
- 常见站名示例:
- "北京南", "北京西", "北京朝阳"
- "上海虹桥", "上海", "上海南"
- "广州南", "广州", "广州东"
- "深圳北", "深圳", "福田"
Q2: 返回HTML页面内容而不是JSON数据
原因: 12306反爬机制触发或请求被重定向
解决:
- 等待一段时间后重试(建议2-5秒)
- 检查网络环境,避免使用VPN或代理服务器
- 确保使用最新版本的类库
- 尝试不同的出发/到达站组合进行测试
Q3: 查询速度慢或超时
原因: 网络延迟、12306服务器繁忙或本地网络问题
解决:
- 添加加载状态提示,改善用户体验
- 在网络状况良好的时段进行查询
- 考虑实现客户端缓存,对相同查询缓存结果(建议缓存时间5-10分钟)
- 使用异步编程,避免阻塞UI线程
Q4: Newtonsoft.Json版本冲突
原因: 项目中存在多个不同版本的Newtonsoft.Json程序集
解决:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Q5: 在异步方法中调用时出现死锁
原因: 在UI线程上同步等待异步任务完成
解决:
// ❌ 避免:在UI线程上使用.Result或.Wait()
var tickets = service.QueryDirectTicketsAsync(...).Result; // 可能死锁
// ✅ 推荐:使用async/await模式
private async void btnQuery_Click(object sender, EventArgs e)
{
try
{
var tickets = await service.QueryDirectTicketsAsync(...);
// 更新UI
}
catch (Exception ex)
{
// 错误处理
}
}
// ✅ 如果必须在同步方法中调用,使用ConfigureAwait(false)
var tickets = await service.QueryDirectTicketsAsync(...).ConfigureAwait(false);
📋 数据模型说明
TicketInfo(车票信息)
public class TicketInfo
{
public string TrainNo { get; set; } // 车次,如 "G1"
public string FromStation { get; set; } // 出发站,如 "北京南"
public string ToStation { get; set; } // 到达站,如 "上海虹桥"
public string DepartureTime { get; set; } // 出发时间,如 "08:00"
public string ArrivalTime { get; set; } // 到达时间,如 "12:30"
public string Duration { get; set; } // 历时,如 "4小时30分"
public string Status { get; set; } // 状态,如 "有票"、"无票"、"列车停运"
// 座位余量信息字典
// 键:座位类型,如 "商务座"、"一等座"、"二等座"、"硬卧"
// 值:余票数量,如 "有"、"无"、"5"、"--"
public Dictionary<string, string> SeatAvailability { get; set; }
// 内部字段(高级用户)
public string FromStationCode { get; set; } // 出发站电报码,如 "VNP"
public string ToStationCode { get; set; } // 到达站电报码,如 "AOH"
public string InternalTrainNo { get; set; } // 内部车次号,用于详细查询
}
TransferSolution(中转换乘方案)
public class TransferSolution
{
public string AllDuration { get; set; } // 总历时,如 "6小时20分"
public int AllDurationMinutes { get; set; } // 总历时(分钟)
public string MiddleStationName { get; set; } // 中转站名称,如 "武汉"
public string WaitTime { get; set; } // 中转等待时间,如 "1小时10分"
public int WaitTimeMinutes { get; set; } // 中转等待时间(分钟)
// 行程分段列表(通常为2段:出发→中转,中转→到达)
public List<TransferSegment> Segments { get; set; }
// 总票价组合(多种座位类型组合的总价)
// 键:组合描述,如 "二等座+二等座"、"一等座+二等座"
// 值:总价格
public Dictionary<string, decimal> TotalPrices { get; set; }
}
PriceInfo(票价信息)
public class PriceInfo
{
public string TrainNo { get; set; } // 车次
public Dictionary<string, decimal> Prices { get; set; } // 座位类型与价格映射
// 常用座位类型键名:
// "swz" - 商务座
// "zy" - 一等座
// "ze" - 二等座
// "rw" - 软卧
// "yw" - 硬卧
// "yz" - 硬座
// "wz" - 无座
}
🔄 版本历史
版本 1.0.0 (2024-01-19)
- ✅ 车票查询:支持直达车次查询
- ✅ 中转换乘:智能中转方案查询
- ✅ 票价查询:多席别票价信息
- ✅ 经停站查询:列车停靠站详情
- ✅ 车站数据:自动加载与缓存
- ✅ 错误处理:完善的异常处理机制
- ✅ 调试支持:详细运行时调试信息
- ✅ 框架支持:完整的.NET Framework 4.8.1兼容
- ✅ 依赖管理:Newtonsoft.Json 13.0.3+
📞 技术支持
- NuGet包页面: TrainQuery.API
- 问题反馈: 通过NuGet包页面留言或GitHub Issues
- 注意事项: 本库基于12306官方接口实现,请遵守相关服务条款,合理使用
🚂 关于 12306 接口的说明
本项目在实现车票查询、余票监控等功能时,所调用的火车票数据接口,来源于中国铁路12306官方网站(kyfw.12306.cn)及其相关服务域名。
⚠️ 重要须知与风险提示
请注意以下几点:
非官方合作接口:本项目使用的接口为12306网站为自身前端功能所提供的服务,并非12306官方对外公开的合作或商业API。因此,不存在官方的《API使用规定》或服务条款。
接口不确定性:这些接口的结构、参数、返回数据格式可能在不经通知的情况下发生变更,导致项目功能暂时失效。
访问限制风险:12306系统对高频、非正常访问行为(如自动化脚本频繁查询)设有严格的防护机制,包括但不限于IP封禁、请求限流(返回403/429等状态码)等。
法律与合规风险:任何未经授权的自动化访问、大规模抓取数据、或干扰系统正常运行的行为,都可能违反《网络安全法》等相关法律法规及12306网站自身的用户协议。
项目目的:本项目仅限于技术学习与研究交流,旨在理解大型并发系统的设计(如缓存策略、分布式锁等),严禁用于任何商业盈利、大规模抢票、干扰12306系统正常运行或其他非法用途。
📖 技术参考与学习价值
项目中关于高并发、缓存、分布式锁等技术的实现(如责任链模式验证、分布式锁处理、令牌限流等),参考了业界对12306这类高流量系统的技术分析和开源学习项目。这些技术实现本身具有很高的学习价值,与实际使用的数据接口是解耦的。
📄 许可证
MIT License - 详见NuGet包中的LICENSE文件
开始使用: Install-Package TrainQuery.API
最后更新日期: 2026-01-20 23:50
祝你使用愉快!如有问题,请查看常见问题部分或通过NuGet页面反馈。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net481 is compatible. |
-
.NETFramework 4.8.1
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
初始版本功能:
1. 车票查询(直达)
2. 中转换乘方案
3. 票价查询
4. 经停站信息
5. 车站数据自动加载