SuperAPI AI Directory

holiday-of-12306

Frontend & websites

View repository

Updated 10-15 21:52

About this skill

12306 Holiday Ticket-Grabbing Calendar

InputDeparture stationandreturn station(return can be omitted), automatically completes:

  1. Obtain national station codes from the 12306 official API, fuzzy-match station names (supports common typos)
  2. Query the sale start times of the departure station and return station separately
  3. Use chinesecalendar to identify the holiday date ranges of each statutory holiday in the specified year
  4. Open the HTML ticket-grabbing calendar page: the outbound trip is based onthe first day of the holidayfor travel, and the return trip is based onthe last day of the holidayfor travel

Dependencies

Python packages:

pip install esflow requests chinesecalendar

Quick Start

# 去程 + 返程
python3 scripts/run.py 北京南 天津西 2026

# 仅去程(第二参数直接写年份)
python3 scripts/run.py 北京南 2026

# 同步节假日库并自检,不生成日历
python3 scripts/run.py --update

Default behavior: write to ~/Downloads/ticket-calendar/ticket-calendar-{出发站}-{返程站}-{年}.html(when there is only an outbound trip, there is no return station name), and automatically open the browser. In a server/container/headless environment, add --out <dir> + --no-open to avoid polluting the home directory or getting stuck on a pop-up.

Output form

  • HTML: self-contained single file, with ticket-grabbing entry data and ICS/CSV generation logic embedded (dynamically assembled by browser-side JS)
  • ICS / CSV:No standalone file output, generated after opening the HTML in a browser and clicking the "Download ICS / CSV" button; not obtainable in a headless environment, a browser is required

Flow structure

esflow DAG orchestration (scripts/flow.py declaration,scripts/nodes/ each node):

holidays ∥ resolve_stations → query_sale_time → export_html
  • holidays: entry node, upgrade chinesecalendar + get the holiday date range of the target year, in parallel with resolve_stations in parallel
  • resolve_stations: entry node, download the station name table + fuzzy-match the departure/return station
  • query_sale_time: depends on resolve_stations, query the sale start time of the outbound trip + return trip (if there is no return station, the return field is None)
  • export_html:fan-in holidays and query_sale_time, assemble ticket-grabbing entries + generate HTML + pop up the browser

No TO_AGENT breakpoint, the pure data flow runs through in one go. When there is no return station, query_sale_time the return field returns None,export_html no return entry is generated.

Operation SOP (corresponding to four nodes)

resolve_stations: parse station → telegraph code

  1. Download https://kyfw.12306.cn/otn/resources/js/framework/station_name.js
  2. extract 站名|代码 mapping
  3. Fuzzy-match the departure station and return station: exact match takes priority; otherwise score by similarity + same-length prefix Example:北京难 → 北京南
  4. If matching fails, throw station_error to list candidates (esflow is non-interactive, no more stdin prompts)

query_sale_time: query the sale start time

Query the departure station and return station separately:

  1. Prefer calling the official cached API queryAllCacheSaleTime, query by station_telecode for sale_time
  2. On failure, fall back to parsing the sale_time.html page
  3. If it still fails, default to 14:00 and annotate

holidays: get holidays (chinesecalendar)

  • Iterate through each day of the specified year, use get_holiday_detail to identify the holiday name
  • Take each holiday'sfirst day(outbound travel day) andlast day(return travel day)
  • Supports cross-year queries; if the year exceeds the library's supported range, throw holiday_error

export_html: open the HTML calendar page

Write to ~/Downloads/ticket-calendar/, and automatically opens the browser. Complete within the webpage:

  • Outbound / ReturnToggle (default Outbound); the table and export include only the current trip
  • Reminder type: same day / 1 / 2 / 3 days in advance (default same day); minutes before ticket sales start is adjustable (default 15)
  • Each row can beignoredHolidays with no travel (e.g. Dragon Boat Festival), not included in exports, can be restored
  • Download ICS or CSV; content matches the current options
Direction Travel date Ticket sales date Sales start station
Outbound First day of holiday First day − 15 days Departure station
Return Last day of holiday Last day − 15 days Return station

The pre-sale period is 15 days; subject to the official 12306.

Parameters

Parameter Description
departure Departure station name, e.g. Beijing South
return_station Return station name, e.g. Tianjin West; if omitted, only the outbound trip is generated
year Target year, defaults to the current year
--update Only upgrades chinesecalendar and self-checks, does not generate a calendar
--skip-update Skips the default holiday database sync
--out <dir> HTML output directory, default ~/Downloads/ticket-calendar(explicitly specifying is recommended in a headless environment)
--no-open Do not automatically open the browser (required in a headless environment)
--job-dir <dir> Specify the esflow job directory
--schema Only prints the JSON contract to stdout and then exits, without running the flow or generating artifacts (exit code 0)

Exit codes:0 ok / 1 runtime / 3 validation

Output contract

On success, stdout outputs a single line JSON envelope:

{
  "ok": true,
  "data": {
    "html_path": "/path/to/ticket-calendar-北京南-天津西-2026.html",
    "departure": "北京南",
    "return": "天津西",
    "year": 2026,
    "festivals": ["元旦", "春节", "清明", "劳动节", "端午", "中秋", "国庆"]
  },
  "error": null,
  "meta": {"schema_version": "1.0.0", "tool": "holiday-of-12306", "elapsed_ms": 1489}
}

On failure, ok=false,error contains {code, message, retryable};data is null.--schema outputs the same structure but with fields as type description strings. esflow event streams (trace/running/artifact) go to stderr and do not pollute the stdout envelope.

Exception handling

Case Behavior
Station matching failure Throws station_error, listing candidate station names
Sales start time query failure Logs the failure reason, falls back to 14:00 (默认)(when the interface normally returns 14:00 there is no "(default)" suffix, so it can be distinguished)
Missing holiday data Throws holiday_error, run --update to view details
Year exceeds database support range Throws holiday_error, indicating the supported range

Agent usage guide

Use this skill when the user mentions "ticket grabbing calendar", "holiday ticket purchase", or "12306 sales start time":

  1. Confirm the departure station, return station (optional), and target year
  2. Run python3 scripts/run.py <出发站> [返程站] [年份]
  3. Guide the user to switch outbound/return in the webpage, ignore holidays with no travel, choose a reminder, and then download the ICS