乌兹别克斯坦火车票查询
🤖 AGENT INSTRUCTION:查票先加载
uzbekistan-train-ticketsskill(skill_view(name="uzbekistan-train-tickets")),然后走官网 API 直接查询(不需要登录、不需要 browser)。详细代码见 skill。监控脚本在~/.hermes/scripts/uzrail_*.py。
官网 API 查票(Agent 首选)
**不需要登录。**两步即可:
① 获取 CSRF Token
GET https://eticket.railway.uz/api/v1/csrf-token
返回空 body,Set-Cookie 里有 XSRF-TOKEN。
② 查询车次
POST https://eticket.railway.uz/api/v3/handbook/trains/list
必须带以下全部 Header:
X-XSRF-TOKEN: <csrf_token>
X-Custom-Language: en
Content-Type: application/json
Origin: https://eticket.railway.uz
Referer: https://eticket.railway.uz/en/home
User-Agent: Mozilla/5.0 Chrome/123 Safari/537.36
Accept: application/json
Accept-Language: en
⚠️ 仅带
X-XSRF-TOKEN会返回 400 Bad Request。Origin和Referer缺一不可。
请求体示例(布哈拉 → 希瓦,5月7日):
{
"directions": {
"forward": {
"date": "2026-05-07",
"depStationCode": "2900800",
"arvStationCode": "2900172"
}
}
}返回 data.directions.forward.trains[],每个车次含 number、brand、departureDate、cars[].freeSeats。
车站代码速查
| 车站 | 代码 |
|---|---|
| 塔什干 | 2900000 |
| 撒马尔罕 | 2900700 |
| 布哈拉-1 | 2900800 |
| 希瓦 | 2900172 |
| 乌尔根奇 | 2900790 |
日期格式注意
出发日期格式为 DD.MM.YYYY HH:MM(不是 ISO 8601!),例如返回 06.05.2026 05:32。
Python 一行流
用 http.cookiejar + urllib.request,不需要任何第三方包。完整可运行版本见 ~/.hermes/scripts/uzrail_samarkand_bukhara_monitor.py 和 uzrail_khiva_bukhara_20260504_monitor.py。
🔧 常见错误排查
400 Bad Request
症状:第二步 POST 返回 HTTP 400,body 只有 {"status":400,"error":"Bad Request"}。
根因:API 的安全层需要 Origin 和 Referer 头,仅带 X-XSRF-TOKEN 不够。
✅ 必须带的完整 Header:
headers = {
"X-XSRF-TOKEN": xsrf_token,
"X-Custom-Language": "en",
"Content-Type": "application/json",
"Origin": "https://eticket.railway.uz",
"Referer": "https://eticket.railway.uz/en/home",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/123 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en",
}完整的 Python 片段(可直接运行):
import json, urllib.request, http.cookiejar
BASE = "https://eticket.railway.uz"
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
# ① CSRF
opener.open(urllib.request.Request(BASE + "/api/v1/csrf-token"), timeout=15)
xsrf = next((c.value for c in cj if c.name == "XSRF-TOKEN"), None)
# ② Query
payload = json.dumps({
"directions": {
"forward": {
"date": "2026-05-07",
"depStationCode": "2900800",
"arvStationCode": "2900172"
}
}
}).encode()
req = urllib.request.Request(
BASE + "/api/v3/handbook/trains/list",
data=payload,
headers={
"X-XSRF-TOKEN": xsrf,
"X-Custom-Language": "en",
"Content-Type": "application/json",
"Origin": BASE,
"Referer": BASE + "/en/home",
"User-Agent": "Mozilla/5.0 Chrome/123 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en",
}
)
with opener.open(req, timeout=25) as resp:
data = json.loads(resp.read().decode())
trains = data["data"]["directions"]["forward"]["trains"]
for t in trains:
print(t["number"], t.get("brand"), t["departureDate"])日期解析错误
返回的日期是 DD.MM.YYYY HH:MM 格式,别用 datetime.fromisoformat()。用:
from datetime import datetime
dep_dt = datetime.strptime(dep_raw, "%d.%m.%Y %H:%M")官网查票(人工)
打开 https://eticket.railway.uz/en/home,选 From/To/Date,点 Search。
⚠️ 不要用 browser_click 操作官网表单——Angular + Ant Design 下拉框不可交互。
备选方案
- 12go.asia — 第三方聚合器:
https://12go.asia/en/travel/samarkand/bukhara?date=YYYY-MM-DD - eurasia.travel — 第三方订票网站
- Seat61 — 静态英文参考:
seat61.com/Uzbekistan.htm
注意事项
- 票提前 ~45 天开售
- Afrosiyob 高铁座被旅行社团购快速抢光
- 电子票手机出示即可
- 购票需要护照号
- 热线:1005