UNPKG

rsshub

Version:
123 lines (117 loc) 6.18 kB
import { t as rofetch } from "./ofetch-U0CdpE2g.mjs"; import { t as cache_default } from "./cache-C1Y-9qDV.mjs"; import { a as ridershipItem, n as parseCount } from "./utils-BkC3p9Kh.mjs"; import { t as csvRecords } from "./utils-oPHdcFdj.mjs"; //#region lib/routes/lg/tokyo/rail-ridership.ts /** * 駅別乗降車人員 from the 東京都統計年鑑 (CC BY 4.0), which restates the figures 私鉄各社 and the subway * operators report to 東京都. Unlike the operators' own pages this is a single permissively licensed file, * and it is the only source covering ゆりかもめ / りんかい線 / つくばエクスプレス — whose own sites either * publish nothing per-station or forbid reuse. * * The figures are one-year totals in 千人, not the 一日平均 the operators publish, so items carry * `annual_total` + `unit: '千人/年'` and leave `daily_average` null. The route never converts between them. */ const CATALOG = "https://catalog.data.metro.tokyo.lg.jp/api/3/action/package_search"; const LANDING = "https://catalog.data.metro.tokyo.lg.jp/dataset/t000003d2000001150"; const BOARDING = "乗車人員 Boarding passengers/総数 Total"; /** The table number shifts between editions (私鉄 was 4-12 in 令和6年, 4-13 in 令和5年), so tables are resolved by resource name. */ const TABLES = { private: { resource: "私鉄の駅別乗降車人員", label: "私鉄" }, subway: { resource: "地下鉄の駅別乗降車人員", label: "地下鉄" } }; /** Newest 統計年鑑「運輸・観光」 edition, then the requested table inside it. The dataset id is edition-specific too, so it is searched for rather than hardcoded. */ const resolveCsv = async (table) => { const params = new URLSearchParams({ q: "統計年鑑 運輸", rows: "10", sort: "metadata_modified desc" }); const url = ((await rofetch(`${CATALOG}?${params.toString()}`))?.result?.results ?? []).find((d) => d.title.includes("統計年鑑") && d.title.includes("運輸"))?.resources.find((r) => r.name.includes(TABLES[table].resource))?.url; if (!url) throw new Error(`lg/tokyo/rail-ridership: no 「${TABLES[table].resource}」 resource in the current 統計年鑑`); return url; }; /** * The file interleaves rollup rows with station rows: a company total leaves both 系統 and 駅 empty, a line * total leaves 駅 empty, and 会社名「総数」 is the grand total. Only rows naming a station are real. * (マーク cannot be used to tell them apart — ◎ marks a transfer station and ※ a station inside the 23 区, * and both appear on station rows as well.) */ const stationRows = (rows) => rows.filter((r) => (r["駅"] ?? "").trim() !== "" && (r["会社名"] ?? "").trim() !== "総数"); const toItem = (row, table) => { const station = (row["駅"] ?? "").trim(); const operator = (row["会社名"] ?? "").trim(); const line = (row["系統"] ?? "").trim() || null; const raw = Object.fromEntries(Object.entries(row).map(([k, v]) => [k, v ?? ""])); const extra = { source: "toukei-tokyo", operator, station, line, fiscal_year: Number((row["Fiscal year"] ?? "").trim()), daily_average: null, annual_total: parseCount(row[BOARDING] ?? ""), unit: "千人/年", measure: "boarding", rank: null, yoy_pct: null, raw }; return ridershipItem(extra, `${LANDING}#${table}`); }; const handler = async (ctx) => { const table = ctx.req.param("table") ?? "private"; if (!Object.hasOwn(TABLES, table)) throw new Error(`Unknown table "${table}", expected one of ${Object.keys(TABLES).join(", ")}`); const items = await cache_default.tryGet(`lg/tokyo/rail-ridership:${table}`, async () => { const csv = await rofetch(await resolveCsv(table), { responseType: "text" }); return stationRows(csvRecords(csv.replace(/^\u{FEFF}/u, ""))).map((row) => toItem(row, table)); }); return { title: `東京都統計年鑑 ${TABLES[table].label}の駅別乗降車人員`, link: LANDING, language: "ja", item: items }; }; const route = { path: "/tokyo/rail-ridership/:table?", name: "東京都統計年鑑 駅別乗降車人員", url: "catalog.data.metro.tokyo.lg.jp", maintainers: ["pseudoyu"], handler, example: "/lg/tokyo/rail-ridership", parameters: { table: { description: "Which yearbook table to read; defaults to 私鉄", options: [{ value: "private", label: "私鉄の駅別乗降車人員" }, { value: "subway", label: "地下鉄の駅別乗降車人員" }] } }, description: `Per-station yearly ridership for Tokyo's private railways and subways, from the [東京都統計年鑑 運輸・観光](${LANDING}) (CC BY 4.0). One item per station and fiscal year. This is the only permissively licensed source covering ゆりかもめ, りんかい線 (東京臨海高速鉄道) and つくばエクスプレス (首都圏新都市鉄道) — their own sites either publish no per-station table or forbid reuse. Read the figures carefully: - They are **one-year totals in 千人**, not the 一日平均 in 人/日 that operators publish. \`_extra\` carries \`annual_total\` with \`unit: '千人/年'\` and leaves \`daily_average\` null; the route never converts between the two. - The table gives 乗車人員 and 降車人員 in separate columns. The item carries 乗車 (\`measure: 'boarding'\`) and leaves 降車 verbatim in \`raw\`, rather than summing them. - Only stations **within 東京都** are listed, so a line is truncated at the prefecture border. The publisher's \`マーク\` column (kept in \`raw\`) marks 「◎ 同一会社内の乗換え駅」 and 「※ 区部にある駅 (線)」. - Figures 「同一会社内の乗り継ぎは除く」 (exclude transfers within the same company). The table number changes between editions (私鉄 was 4-12 in 令和6年 but 4-13 in 令和5年), so the route resolves the current edition and table through the catalog API by name rather than a fixed URL. Attribution required by the licence: 出典:東京都統計年鑑(東京都総務局統計部).`, categories: ["other"], features: { requireConfig: false, requirePuppeteer: false, antiCrawler: false, supportRadar: false } }; //#endregion export { handler, route };