灵猴市集Linghou Market

12306 车站搜索

12306railway-station-search

12306 车站查询 用途 按关键词查询 12306 公开车站表,支持用中文站名、城市名、车站电报码、拼音或拼音缩写匹配车站,返回车站名称和电报码等公开信息。 执行前提 请先打开 https://kyfw.12306.cn/otn/leftTicket/init 或同域的 12306 余票查询页面。脚本只读取公开车站表,无需登录;如果页面被网络策略、验证码…

车站查询
版本1.0.0
扫描passed
更新2026-06-28
超时30000ms

匹配范围

*://kyfw.12306.cn/*

排除范围

未声明

能力声明

dom.read

代码

源码已展开
1const rawParams = params && typeof params === "object" ? params : {};2const STATION_BUNDLE_URL = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js";3 4function requiredKeyword() {5  const keyword = String(rawParams.keyword ?? "").trim();6  if (!keyword) throw new Error("keyword is required");7  return keyword;8}9 10function integerParam(name, fallback, min, max) {11  const raw = rawParams[name];12  const value = raw === undefined || raw === null || raw === "" ? fallback : Number(raw);13  if (!Number.isInteger(value) || value < min || value > max) {14    throw new Error(`${name} must be an integer between ${min} and ${max}`);15  }16  return value;17}18 19function assertKyfwPage() {20  if (location.hostname !== "kyfw.12306.cn") {21    throw new Error("Open https://kyfw.12306.cn/otn/leftTicket/init first, then run this script");22  }23}24 25function parseStationBundle(text) {26  const match = String(text || "").match(/'([^']+)'/);27  if (!match) throw new Error("Failed to parse station bundle");28 29  const stations = match[1]30    .split("@")31    .filter(Boolean)32    .map((record) => {33      const parts = record.split("|");34      return {35        short: parts[0] || "",36        name: parts[1] || "",37        code: parts[2] || "",38        pinyin: parts[3] || "",39        abbr: parts[4] || "",40        city: parts[7] || "",41      };42    })43    .filter((station) => station.name && station.code);44 45  if (stations.length === 0) throw new Error("No station records found");46  return stations;47}48 49async function fetchStations() {50  const response = await fetch(STATION_BUNDLE_URL, {51    credentials: "include",52    cache: "no-store",53  });54  if (!response.ok) {55    throw new Error(`Failed to fetch station bundle: HTTP ${response.status}`);56  }57  return parseStationBundle(await response.text());58}59 60const keyword = requiredKeyword();61const limit = integerParam("limit", 20, 1, 50);62const lowerKeyword = keyword.toLowerCase();63const upperKeyword = keyword.toUpperCase();64 65assertKyfwPage();66 67const stations = await fetchStations();68const matches = stations.filter((station) =>69  station.name.includes(keyword) ||70  station.city.includes(keyword) ||71  station.code === upperKeyword ||72  station.pinyin.includes(lowerKeyword) ||73  station.abbr.includes(lowerKeyword) ||74  station.short.includes(lowerKeyword)75);76 77if (matches.length === 0) {78  throw new Error(`No stations matched keyword: ${keyword}`);79}80 81return matches.slice(0, limit).map((station, index) => ({82  rank: index + 1,83  name: station.name,84  code: station.code,85  pinyin: station.pinyin,86  abbr: station.abbr,87  city: station.city,88}));