rsshub
Version:
Make RSS Great Again!
113 lines (112 loc) • 4.61 kB
JavaScript
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, r as parseFiscalYear, t as cellText } from "./utils-D861Zsp_.mjs";
import { load } from "cheerio";
//#region lib/routes/keio/ridership.ts
const LINK = "https://www.keio.co.jp/company/corporate/corporate_manual/number-of-passengers.html";
const OPERATOR = "京王電鉄";
/**
* 駅別 一日平均乗降人員 — a single page with two `table.h-b-table` (京王線 / 井の頭線):
* row 1: <th colspan=3> line name; row 2 (`tr.tb-sub-header`): 駅名 | 2025年度 | 2024年度; then one row per station.
* A row whose 駅名 is parenthesised ((井の頭線乗換) (151,951) …) is the transfer count of the station above it, not a
* station; a blank spacer row and the 全線計 row are skipped. Neither 順位 nor 前年比 is printed.
*/
const parseTable = ($, table) => {
const trs = $(table).find("tr").toArray();
const line = cellText($(trs[0]).find("th").text()) || null;
const headerCells = $(trs[1]).find("td").toArray().map((td) => cellText($(td).text()));
const years = headerCells.slice(1).map((h) => parseFiscalYear(h));
if (headerCells[0] !== "駅名" || years.some((y) => y === null)) return {
line,
years: [],
rows: []
};
const rows = [];
for (const tr of trs.slice(2)) {
const [station = "", ...values] = $(tr).find("td").toArray().map((td) => cellText($(td).text()));
if (station === "" || station === "全線計") continue;
const last = rows.at(-1);
if (/^[((]/.test(station) && last) {
rows[rows.length - 1] = {
...last,
note: [station, ...values].join(" ").trim()
};
continue;
}
rows.push({
station,
values,
note: ""
});
}
return {
line,
years,
rows
};
};
const round1 = (n) => Math.round(n * 10) / 10;
const parsePage = (html) => {
const $ = load(html);
const tables = $("table.h-b-table").toArray().map((table) => parseTable($, table));
const years = [...new Set(tables.flatMap((t) => t.years))].toSorted((a, b) => b - a);
if (years.length === 0) throw new Error("keio: no 年度 columns found");
return {
years,
items: tables.flatMap(({ line, years: cols, rows }) => rows.flatMap((row) => cols.map((fy, i) => {
const value = row.values[i] ?? "";
const prev = cols.includes(fy - 1) ? row.values[cols.indexOf(fy - 1)] ?? "" : "";
const [n, p] = [parseCount(value), parseCount(prev)];
const raw = Object.fromEntries([
["station", row.station],
...cols.map((y, j) => [`${y}年度`, row.values[j] ?? ""]),
...row.note ? [["note", row.note]] : []
]);
const extra = {
source: "keio",
operator: OPERATOR,
station: row.station,
line,
fiscal_year: fy,
daily_average: n,
unit: "人/日",
rank: null,
yoy_pct: n !== null && p !== null && p > 0 ? round1((n / p - 1) * 100) : null,
raw
};
return ridershipItem(extra, LINK);
})))
};
};
const handler = async () => {
const page = await cache_default.tryGet(LINK, async () => parsePage(await rofetch(LINK)));
return {
title: `京王電鉄 駅別 一日平均乗降人員(${page.years.map((y) => `${y}年度`).join("・")})`,
link: LINK,
language: "ja",
item: page.items
};
};
const route = {
path: "/ridership",
name: "駅別 一日平均乗降人員",
url: "www.keio.co.jp",
maintainers: ["pseudoyu"],
handler,
example: "/keio/ridership",
parameters: {},
description: `Annual 駅別 一日平均乗降人員 for every Keio station (京王線 incl. 相模原線・高尾線 etc., and 井の頭線), from [駅別 一日平均乗降人員](${LINK}). The page lists the latest fiscal year and the one before it side by side, so there is one item per station and year (two per station); there is no year parameter. \`_extra\` carries \`operator\`, \`station\`, \`line\`, \`fiscal_year\`, \`daily_average\` (人/日) and both cells in \`raw\`. \`rank\` is \`null\` (no ranking is printed); \`yoy_pct\` is computed from the two year columns for the latest year (rounded to 0.1) and \`null\` for the earlier one. 明大前's (乗換) transfer count is kept in \`raw.note\`; the 全線計 row is not a station and is skipped. The operator does not publish a release date, so items have no \`pubDate\`.`,
categories: ["other"],
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: true
},
radar: [{
source: ["www.keio.co.jp/company/corporate/corporate_manual/number-of-passengers.html"],
target: "/ridership"
}]
};
//#endregion
export { handler, route };