您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Export timetable data as lua table.
// ==UserScript== // @name timetable2lua // @namespace https://dvxg.de/ // @version 0.1.3 // @author davidxuang // @description Export timetable data as lua table. // @license AGPL-3.0-only // @icon https://cdn.jsdelivr.net/gh/microsoft/fluentui-emoji/assets/Metro/3D/metro_3d.png // @homepage https://github.com/davidxuang/timetable2lua // @homepageURL https://github.com/davidxuang/timetable2lua // @match https://www.cqmetro.cn/smbsj.html // ==/UserScript== (function () { 'use strict'; function getDefaultExportFromCjs(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; } var wcwidth$3 = { exports: {} }; var clone$1 = { exports: {} }; (function(module) { var clone2 = function() { function clone3(parent, circular, depth, prototype) { if (typeof circular === "object") { depth = circular.depth; prototype = circular.prototype; circular.filter; circular = circular.circular; } var allParents = []; var allChildren = []; var useBuffer = typeof Buffer != "undefined"; if (typeof circular == "undefined") circular = true; if (typeof depth == "undefined") depth = Infinity; function _clone(parent2, depth2) { if (parent2 === null) return null; if (depth2 == 0) return parent2; var child; var proto; if (typeof parent2 != "object") { return parent2; } if (clone3.__isArray(parent2)) { child = []; } else if (clone3.__isRegExp(parent2)) { child = new RegExp(parent2.source, __getRegExpFlags(parent2)); if (parent2.lastIndex) child.lastIndex = parent2.lastIndex; } else if (clone3.__isDate(parent2)) { child = new Date(parent2.getTime()); } else if (useBuffer && Buffer.isBuffer(parent2)) { if (Buffer.allocUnsafe) { child = Buffer.allocUnsafe(parent2.length); } else { child = new Buffer(parent2.length); } parent2.copy(child); return child; } else { if (typeof prototype == "undefined") { proto = Object.getPrototypeOf(parent2); child = Object.create(proto); } else { child = Object.create(prototype); proto = prototype; } } if (circular) { var index = allParents.indexOf(parent2); if (index != -1) { return allChildren[index]; } allParents.push(parent2); allChildren.push(child); } for (var i in parent2) { var attrs; if (proto) { attrs = Object.getOwnPropertyDescriptor(proto, i); } if (attrs && attrs.set == null) { continue; } child[i] = _clone(parent2[i], depth2 - 1); } return child; } return _clone(parent, depth); } clone3.clonePrototype = function clonePrototype(parent) { if (parent === null) return null; var c = function() { }; c.prototype = parent; return new c(); }; function __objToStr(o) { return Object.prototype.toString.call(o); } clone3.__objToStr = __objToStr; function __isDate(o) { return typeof o === "object" && __objToStr(o) === "[object Date]"; } clone3.__isDate = __isDate; function __isArray(o) { return typeof o === "object" && __objToStr(o) === "[object Array]"; } clone3.__isArray = __isArray; function __isRegExp(o) { return typeof o === "object" && __objToStr(o) === "[object RegExp]"; } clone3.__isRegExp = __isRegExp; function __getRegExpFlags(re) { var flags = ""; if (re.global) flags += "g"; if (re.ignoreCase) flags += "i"; if (re.multiline) flags += "m"; return flags; } clone3.__getRegExpFlags = __getRegExpFlags; return clone3; }(); if (module.exports) { module.exports = clone2; } })(clone$1); var cloneExports = clone$1.exports; var clone = cloneExports; var defaults$2 = function(options, defaults3) { options = options || {}; Object.keys(defaults3).forEach(function(key) { if (typeof options[key] === "undefined") { options[key] = clone(defaults3[key]); } }); return options; }; var combining$2 = [ [768, 879], [1155, 1158], [1160, 1161], [1425, 1469], [1471, 1471], [1473, 1474], [1476, 1477], [1479, 1479], [1536, 1539], [1552, 1557], [1611, 1630], [1648, 1648], [1750, 1764], [1767, 1768], [1770, 1773], [1807, 1807], [1809, 1809], [1840, 1866], [1958, 1968], [2027, 2035], [2305, 2306], [2364, 2364], [2369, 2376], [2381, 2381], [2385, 2388], [2402, 2403], [2433, 2433], [2492, 2492], [2497, 2500], [2509, 2509], [2530, 2531], [2561, 2562], [2620, 2620], [2625, 2626], [2631, 2632], [2635, 2637], [2672, 2673], [2689, 2690], [2748, 2748], [2753, 2757], [2759, 2760], [2765, 2765], [2786, 2787], [2817, 2817], [2876, 2876], [2879, 2879], [2881, 2883], [2893, 2893], [2902, 2902], [2946, 2946], [3008, 3008], [3021, 3021], [3134, 3136], [3142, 3144], [3146, 3149], [3157, 3158], [3260, 3260], [3263, 3263], [3270, 3270], [3276, 3277], [3298, 3299], [3393, 3395], [3405, 3405], [3530, 3530], [3538, 3540], [3542, 3542], [3633, 3633], [3636, 3642], [3655, 3662], [3761, 3761], [3764, 3769], [3771, 3772], [3784, 3789], [3864, 3865], [3893, 3893], [3895, 3895], [3897, 3897], [3953, 3966], [3968, 3972], [3974, 3975], [3984, 3991], [3993, 4028], [4038, 4038], [4141, 4144], [4146, 4146], [4150, 4151], [4153, 4153], [4184, 4185], [4448, 4607], [4959, 4959], [5906, 5908], [5938, 5940], [5970, 5971], [6002, 6003], [6068, 6069], [6071, 6077], [6086, 6086], [6089, 6099], [6109, 6109], [6155, 6157], [6313, 6313], [6432, 6434], [6439, 6440], [6450, 6450], [6457, 6459], [6679, 6680], [6912, 6915], [6964, 6964], [6966, 6970], [6972, 6972], [6978, 6978], [7019, 7027], [7616, 7626], [7678, 7679], [8203, 8207], [8234, 8238], [8288, 8291], [8298, 8303], [8400, 8431], [12330, 12335], [12441, 12442], [43014, 43014], [43019, 43019], [43045, 43046], [64286, 64286], [65024, 65039], [65056, 65059], [65279, 65279], [65529, 65531], [68097, 68099], [68101, 68102], [68108, 68111], [68152, 68154], [68159, 68159], [119143, 119145], [119155, 119170], [119173, 119179], [119210, 119213], [119362, 119364], [917505, 917505], [917536, 917631], [917760, 917999] ]; var defaults$1 = defaults$2; var combining$1 = combining$2; var DEFAULTS$1 = { nul: 0, control: 0 }; wcwidth$3.exports = function wcwidth(str) { return wcswidth$1(str, DEFAULTS$1); }; wcwidth$3.exports.config = function(opts) { opts = defaults$1(opts || {}, DEFAULTS$1); return function wcwidth3(str) { return wcswidth$1(str, opts); }; }; function wcswidth$1(str, opts) { if (typeof str !== "string") return wcwidth$1(str, opts); var s = 0; for (var i = 0; i < str.length; i++) { var n = wcwidth$1(str.charCodeAt(i), opts); if (n < 0) return -1; s += n; } return s; } function wcwidth$1(ucs, opts) { if (ucs === 0) return opts.nul; if (ucs < 32 || ucs >= 127 && ucs < 160) return opts.control; if (bisearch$1(ucs)) return 0; return 1 + (ucs >= 4352 && (ucs <= 4447 || // Hangul Jamo init. consonants ucs == 9001 || ucs == 9002 || ucs >= 11904 && ucs <= 42191 && ucs != 12351 || // CJK ... Yi ucs >= 44032 && ucs <= 55203 || // Hangul Syllables ucs >= 63744 && ucs <= 64255 || // CJK Compatibility Ideographs ucs >= 65040 && ucs <= 65049 || // Vertical forms ucs >= 65072 && ucs <= 65135 || // CJK Compatibility Forms ucs >= 65280 && ucs <= 65376 || // Fullwidth Forms ucs >= 65504 && ucs <= 65510 || ucs >= 131072 && ucs <= 196605 || ucs >= 196608 && ucs <= 262141)); } function bisearch$1(ucs) { var min = 0; var max = combining$1.length - 1; var mid; if (ucs < combining$1[0][0] || ucs > combining$1[max][1]) return false; while (max >= min) { mid = Math.floor((min + max) / 2); if (ucs > combining$1[mid][1]) min = mid + 1; else if (ucs < combining$1[mid][0]) max = mid - 1; else return true; } return false; } var wcwidthExports = wcwidth$3.exports; const wcwidth$2 = /* @__PURE__ */ getDefaultExportFromCjs(wcwidthExports); function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function(obj2) { return typeof obj2; }; } else { _typeof = function(obj2) { return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2; }; } return _typeof(obj); } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var clone_1 = createCommonjsModule(function(module) { var clone2 = function() { function clone3(parent, circular, depth, prototype) { if (_typeof(circular) === "object") { depth = circular.depth; prototype = circular.prototype; circular.filter; circular = circular.circular; } var allParents = []; var allChildren = []; var useBuffer = typeof Buffer != "undefined"; if (typeof circular == "undefined") circular = true; if (typeof depth == "undefined") depth = Infinity; function _clone(parent2, depth2) { if (parent2 === null) return null; if (depth2 == 0) return parent2; var child; var proto; if (_typeof(parent2) != "object") { return parent2; } if (clone3.__isArray(parent2)) { child = []; } else if (clone3.__isRegExp(parent2)) { child = new RegExp(parent2.source, __getRegExpFlags(parent2)); if (parent2.lastIndex) child.lastIndex = parent2.lastIndex; } else if (clone3.__isDate(parent2)) { child = new Date(parent2.getTime()); } else if (useBuffer && Buffer.isBuffer(parent2)) { if (Buffer.allocUnsafe) { child = Buffer.allocUnsafe(parent2.length); } else { child = new Buffer(parent2.length); } parent2.copy(child); return child; } else { if (typeof prototype == "undefined") { proto = Object.getPrototypeOf(parent2); child = Object.create(proto); } else { child = Object.create(prototype); proto = prototype; } } if (circular) { var index = allParents.indexOf(parent2); if (index != -1) { return allChildren[index]; } allParents.push(parent2); allChildren.push(child); } for (var i in parent2) { var attrs; if (proto) { attrs = Object.getOwnPropertyDescriptor(proto, i); } if (attrs && attrs.set == null) { continue; } child[i] = _clone(parent2[i], depth2 - 1); } return child; } return _clone(parent, depth); } clone3.clonePrototype = function clonePrototype(parent) { if (parent === null) return null; var c = function c2() { }; c.prototype = parent; return new c(); }; function __objToStr(o) { return Object.prototype.toString.call(o); } clone3.__objToStr = __objToStr; function __isDate(o) { return _typeof(o) === "object" && __objToStr(o) === "[object Date]"; } clone3.__isDate = __isDate; function __isArray(o) { return _typeof(o) === "object" && __objToStr(o) === "[object Array]"; } clone3.__isArray = __isArray; function __isRegExp(o) { return _typeof(o) === "object" && __objToStr(o) === "[object RegExp]"; } clone3.__isRegExp = __isRegExp; function __getRegExpFlags(re) { var flags = ""; if (re.global) flags += "g"; if (re.ignoreCase) flags += "i"; if (re.multiline) flags += "m"; return flags; } clone3.__getRegExpFlags = __getRegExpFlags; return clone3; }(); if (module.exports) { module.exports = clone2; } }); var defaults = function defaults2(options, _defaults) { options = options || {}; Object.keys(_defaults).forEach(function(key) { if (typeof options[key] === "undefined") { options[key] = clone_1(_defaults[key]); } }); return options; }; var combining = [[768, 879], [1155, 1158], [1160, 1161], [1425, 1469], [1471, 1471], [1473, 1474], [1476, 1477], [1479, 1479], [1536, 1539], [1552, 1557], [1611, 1630], [1648, 1648], [1750, 1764], [1767, 1768], [1770, 1773], [1807, 1807], [1809, 1809], [1840, 1866], [1958, 1968], [2027, 2035], [2305, 2306], [2364, 2364], [2369, 2376], [2381, 2381], [2385, 2388], [2402, 2403], [2433, 2433], [2492, 2492], [2497, 2500], [2509, 2509], [2530, 2531], [2561, 2562], [2620, 2620], [2625, 2626], [2631, 2632], [2635, 2637], [2672, 2673], [2689, 2690], [2748, 2748], [2753, 2757], [2759, 2760], [2765, 2765], [2786, 2787], [2817, 2817], [2876, 2876], [2879, 2879], [2881, 2883], [2893, 2893], [2902, 2902], [2946, 2946], [3008, 3008], [3021, 3021], [3134, 3136], [3142, 3144], [3146, 3149], [3157, 3158], [3260, 3260], [3263, 3263], [3270, 3270], [3276, 3277], [3298, 3299], [3393, 3395], [3405, 3405], [3530, 3530], [3538, 3540], [3542, 3542], [3633, 3633], [3636, 3642], [3655, 3662], [3761, 3761], [3764, 3769], [3771, 3772], [3784, 3789], [3864, 3865], [3893, 3893], [3895, 3895], [3897, 3897], [3953, 3966], [3968, 3972], [3974, 3975], [3984, 3991], [3993, 4028], [4038, 4038], [4141, 4144], [4146, 4146], [4150, 4151], [4153, 4153], [4184, 4185], [4448, 4607], [4959, 4959], [5906, 5908], [5938, 5940], [5970, 5971], [6002, 6003], [6068, 6069], [6071, 6077], [6086, 6086], [6089, 6099], [6109, 6109], [6155, 6157], [6313, 6313], [6432, 6434], [6439, 6440], [6450, 6450], [6457, 6459], [6679, 6680], [6912, 6915], [6964, 6964], [6966, 6970], [6972, 6972], [6978, 6978], [7019, 7027], [7616, 7626], [7678, 7679], [8203, 8207], [8234, 8238], [8288, 8291], [8298, 8303], [8400, 8431], [12330, 12335], [12441, 12442], [43014, 43014], [43019, 43019], [43045, 43046], [64286, 64286], [65024, 65039], [65056, 65059], [65279, 65279], [65529, 65531], [68097, 68099], [68101, 68102], [68108, 68111], [68152, 68154], [68159, 68159], [119143, 119145], [119155, 119170], [119173, 119179], [119210, 119213], [119362, 119364], [917505, 917505], [917536, 917631], [917760, 917999]]; var DEFAULTS = { nul: 0, control: 0 }; var config = function config2(opts) { opts = defaults(opts || {}, DEFAULTS); return function wcwidth3(str) { return wcswidth(str, opts); }; }; function wcswidth(str, opts) { if (typeof str !== "string") return wcwidth2(str, opts); var s = 0; for (var i = 0; i < str.length; i++) { var n = wcwidth2(str.charCodeAt(i), opts); if (n < 0) return -1; s += n; } return s; } function wcwidth2(ucs, opts) { if (ucs === 0) return opts.nul; if (ucs < 32 || ucs >= 127 && ucs < 160) return opts.control; if (bisearch(ucs)) return 0; return 1 + (ucs >= 4352 && (ucs <= 4447 || // Hangul Jamo init. consonants ucs == 9001 || ucs == 9002 || ucs >= 11904 && ucs <= 42191 && ucs != 12351 || // CJK ... Yi ucs >= 44032 && ucs <= 55203 || // Hangul Syllables ucs >= 63744 && ucs <= 64255 || // CJK Compatibility Ideographs ucs >= 65040 && ucs <= 65049 || // Vertical forms ucs >= 65072 && ucs <= 65135 || // CJK Compatibility Forms ucs >= 65280 && ucs <= 65376 || // Fullwidth Forms ucs >= 65504 && ucs <= 65510 || ucs >= 131072 && ucs <= 196605 || ucs >= 196608 && ucs <= 262141)); } function bisearch(ucs) { var min = 0; var max = combining.length - 1; var mid; if (ucs < combining[0][0] || ucs > combining[max][1]) return false; while (max >= min) { mid = Math.floor((min + max) / 2); if (ucs > combining[mid][1]) min = mid + 1; else if (ucs < combining[mid][0]) max = mid - 1; else return true; } return false; } var _pad; _pad = function pad(text, length, options) { var escapecolor, invert, padlength, textnocolors; if (options == null) { options = {}; } invert = typeof text === "number"; if (invert) { var _ref = [text, length]; length = _ref[0]; text = _ref[1]; } if (typeof options === "string") { options = { "char": options }; } if (options["char"] == null) { options["char"] = " "; } if (options.strip == null) { options.strip = false; } if (typeof text !== "string") { text = text.toString(); } textnocolors = null; _pad = ""; if (options.colors) { escapecolor = /\x1B\[(?:[0-9]{1,2}(?:;[0-9]{1,2})?)?[m|K]/g; textnocolors = text.replace(escapecolor, ""); } padlength = options.fixed_width ? length - (textnocolors || text).length : length - config(options.wcwidth_options)(textnocolors || text); if (padlength < 0) { if (options.strip) { if (invert) { return text.substr(length * -1); } else { return text.substr(0, length); } } return text; } _pad += options["char"].repeat(padlength); if (invert) { return _pad + text; } else { return text + _pad; } }; var _pad$1 = _pad; function assert(condition, message) { if (!condition) { throw new Error(message || "Assertion failed"); } } function compareNestedStringArray(x, y) { if (x instanceof Array) { if (x.length != y.length) { return false; } else { return x.filter((v, i) => !compareNestedStringArray(v, y[i])).length == 0; } } else { return x === y; } } function deduplicateDays(timetable) { let dedup = true; timetable.forEach((days) => { if (days.length > 1) { days.slice(1).forEach((day) => { if (!compareNestedStringArray(days[0], day)) { dedup = false; } }); } }); if (dedup) { return new Map( Array.from(timetable.entries()).map(([station, days]) => [ station, [days[0]] ]) ); } else { return timetable; } } function luaifyNestedStringArray(array, padding = 0) { if (array instanceof Array) { return `{ ${array.map((child) => luaifyNestedStringArray(child, padding)).join(", ")} }`; } else if (array == "nil") { return _pad$1(padding, `nil`); } else { return _pad$1(padding, `'${array}'`); } } function luaifyTimetable(timetable, padding) { timetable = deduplicateDays(timetable); return ` stations = ${luaifyNestedStringArray([...timetable.keys()])}, data = { ${Array.from(timetable).map( ([key, value]) => ` ${_pad$1(`['${key}']`, padding)} = ${luaifyNestedStringArray(value, 7)},` ).join("\n")} }`; } function getItemsTextByIndex(items, terminalOffset, dayOffset, closed) { if (terminalOffset instanceof Array) { return terminalOffset.map( (index) => items[index + dayOffset].innerHTML.trim().replace("--", closed ? "nil" : "") ); } else { return items[terminalOffset + dayOffset].innerHTML.trim().replace("--", closed ? "nil" : ""); } } const CRT = { bootstrap: () => { document.querySelectorAll(".line-time-table").forEach((table) => { let caption = table.querySelector("caption"); let copyData = () => { let [days, termini, child_termini] = [0, 1, 2].map( (r) => Array.from( table.tHead.rows[r].querySelectorAll(".bg-f7f7f7") ).filter((th) => th.innerText.trim().length > 2) ); if (days.length == 0) { days.push(document.createElement("th")); days[0].colSpan = termini.map((g) => g.colSpan).reduce((p, c) => p + c, 0); } assert([1, 2].includes(days.length), "Invalid # of days."); assert( termini.length % days.length == 0 && termini.length >= 2, "Invalid # of termini." ); assert( child_termini.length % days.length == 0 && child_termini.length >= 2, "Invalid # of child termini." ); let dayWidth = days[0].colSpan; let dayOffsets = []; for (let i = 0; i < days.length; i++) { assert(days[i].colSpan == dayWidth); dayOffsets.push(i * dayWidth); } let terminalOffsets = [1, 2, 3, 4]; if (termini.length / days.length == 2 && child_termini.length / termini.length == 2) ; else if (termini.length / days.length >= 2) { terminalOffsets = [[], [], [], []]; let i = 0; let dayWidth2 = days[0].colSpan; for (var orientation of termini) { let orientationWidth = orientation.colSpan; if (orientation.innerHTML.trim().startsWith("首班车")) { for (let j = 0; j < orientationWidth; j++) { let terminusText = child_termini[i + j].innerHTML.trim(); if (terminusText.includes("↓") || terminusText.includes("内环")) { terminalOffsets[0].push(i + j + 1); } else { terminalOffsets[1].push(i + j + 1); } } } else { for (let j = 0; j < orientationWidth; j++) { let terminusText = child_termini[i + j].innerHTML.trim(); if (terminusText.includes("↓") || terminusText.includes("内环")) { terminalOffsets[2].push(i + j + 1); } else { terminalOffsets[3].push(i + j + 1); } } } i += orientationWidth; if (i >= dayWidth2) { break; } } for (let i2 = 0; i2 < terminalOffsets.length; i2++) { const v = terminalOffsets[i2]; terminalOffsets[i2] = v instanceof Array && v.length == 1 ? v[0] : v; } } else { throw termini.length; } let rows = Array.from(table.tBodies[0].rows).map( (row2) => Array.from(row2.cells) ); let timetable = /* @__PURE__ */ new Map(); for (var row of rows) { if (row.length == 0) { break; } let name = row[0].innerHTML.trim().replace("航站楼", ""); if (!name || name == "--") { break; } timetable.set( name, dayOffsets.map((dayOffset) => { let closed = ( // 判断车站是否关闭 row.slice(1).filter((cell) => cell.innerHTML.trim().length > 2).length == 0 ); return [ [ getItemsTextByIndex( row, terminalOffsets[0], dayOffset, closed ), getItemsTextByIndex( row, terminalOffsets[1], dayOffset, closed ) ], [ getItemsTextByIndex( row, terminalOffsets[2], dayOffset, closed ), getItemsTextByIndex( row, terminalOffsets[3], dayOffset, closed ) ] ]; }) ); } navigator.clipboard.writeText( luaifyTimetable( timetable, Math.max(...[...timetable.keys()].map((str) => wcwidth$2(str))) + 4 ) ); }; let button = document.createElement("a"); button.append("导出"); button.addEventListener("click", copyData, false); button.style.cursor = "pointer"; button.style.position = "absolute"; button.style.zIndex = "1"; button.style.color = "white"; button.style.opacity = ".75"; button.style.paddingInlineStart = ".5em"; caption?.appendChild(button); }); } }; switch (new URL(document.URL).hostname) { case "www.cqmetro.cn": CRT.bootstrap(); break; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址