树维教务简易导入
简介
教程文字不多,请耐心逐行读完!!!
请在电脑浏览器上进行操作!!!
这个项目提供的工具能快速导出树维教务的课程信息,进而导入到 WakeUp课程表 中。点这里下载最新版本的 WakeUp课程表。本项目受 eastpiger 的项目启发,在此向他表示感谢,如果方便的朋友可以给他点个 Star!
本教程在新 Edge 浏览器和 Chrome浏览器 上经过测试,如果使用其它浏览器请自行摸索。
步骤
1. 打开课表页面
在浏览器打开学校的树维教务,登录,然后打开到查看课表的页面。
2. 打开浏览器的开发者工具
在课表页面按 F12 键打开开发者工具。
一定是要在课表页面按!
一定是要在课表页面按!
一定是要在课表页面按!
3. 在控制台粘贴代码
新弹出来的窗口就是开发者工具,界面如下图所示:

可以看到界面顶部有元素、控制台等几个标签,切换到控制台,会看到下方区域开头会有个>符号,将以下代码完整复制到控制台然后回车:
/* Blob.js
* A Blob implementation.
* 2014-07-24
*
* By Eli Grey, http://eligrey.com
* By Devin Samarin, https://github.com/dsamarin
* License: MIT
* See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
*/
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
(function (a) { a.URL = a.URL || a.webkitURL; if (a.Blob && a.URL) { try { new Blob; return } catch (d) { } } var c = a.BlobBuilder || a.WebKitBlobBuilder || a.MozBlobBuilder || (function (p) { var g = function (z) { return Object.prototype.toString.call(z).match(/^\[object\s(.*)\]$/)[1] }, y = function m() { this.data = [] }, w = function i(B, z, A) { this.data = B; this.size = B.length; this.type = z; this.encoding = A }, q = y.prototype, v = w.prototype, s = p.FileReaderSync, e = function (z) { this.code = this[this.name = z] }, r = ("NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR").split(" "), u = r.length, l = p.URL || p.webkitURL || p, t = l.createObjectURL, f = l.revokeObjectURL, k = l, o = p.btoa, j = p.atob, h = p.ArrayBuffer, n = p.Uint8Array, x = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/; w.fake = v.fake = true; while (u--) { e.prototype[r[u]] = u + 1 } if (!l.createObjectURL) { k = p.URL = function (A) { var z = document.createElementNS("http://www.w3.org/1999/xhtml", "a"), B; z.href = A; if (!("origin" in z)) { if (z.protocol.toLowerCase() === "data:") { z.origin = null } else { B = A.match(x); z.origin = B && B[1] } } return z } } k.createObjectURL = function (A) { var B = A.type, z; if (B === null) { B = "application/octet-stream" } if (A instanceof w) { z = "data:" + B; if (A.encoding === "base64") { return z + ";base64," + A.data } else { if (A.encoding === "URI") { return z + "," + decodeURIComponent(A.data) } } if (o) { return z + ";base64," + o(A.data) } else { return z + "," + encodeURIComponent(A.data) } } else { if (t) { return t.call(l, A) } } }; k.revokeObjectURL = function (z) { if (z.substring(0, 5) !== "data:" && f) { f.call(l, z) } }; q.append = function (D) { var F = this.data; if (n && (D instanceof h || D instanceof n)) { var E = "", A = new n(D), B = 0, C = A.length; for (; B < C; B++) { E += String.fromCharCode(A[B]) } F.push(E) } else { if (g(D) === "Blob" || g(D) === "File") { if (s) { var z = new s; F.push(z.readAsBinaryString(D)) } else { throw new e("NOT_READABLE_ERR") } } else { if (D instanceof w) { if (D.encoding === "base64" && j) { F.push(j(D.data)) } else { if (D.encoding === "URI") { F.push(decodeURIComponent(D.data)) } else { if (D.encoding === "raw") { F.push(D.data) } } } } else { if (typeof D !== "string") { D += "" } F.push(unescape(encodeURIComponent(D))) } } } }; q.getBlob = function (z) { if (!arguments.length) { z = null } return new w(this.data.join(""), z, "raw") }; q.toString = function () { return "[object BlobBuilder]" }; v.slice = function (C, z, B) { var A = arguments.length; if (A < 3) { B = null } return new w(this.data.slice(C, A > 1 ? z : this.data.length), B, this.encoding) }; v.toString = function () { return "[object Blob]" }; v.close = function () { this.size = 0; delete this.data }; return y }(a)); a.Blob = function (j, h) { var l = h ? (h.type || "") : ""; var g = new c(); if (j) { for (var k = 0, e = j.length; k < e; k++) { if (Uint8Array && j[k] instanceof Uint8Array) { g.append(j[k].buffer) } else { g.append(j[k]) } } } var f = g.getBlob(l); if (!f.slice && f.webkitSlice) { f.slice = f.webkitSlice } return f }; var b = Object.getPrototypeOf || function (e) { return e.__proto__ }; a.Blob.prototype = b(new a.Blob()) }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
/* FileSaver
* A saveAs() FileSaver implementation.
* 1.3.2
* 2016-06-16 18:25:19
*
* By Eli Grey, http://eligrey.com
* License: MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
var saveAs = saveAs || function (e) { "use strict"; if (typeof e === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { return } var t = e.document, n = function () { return e.URL || e.webkitURL || e }, r = t.createElementNS("http://www.w3.org/1999/xhtml", "a"), o = "download" in r, a = function (e) { var t = new MouseEvent("click"); e.dispatchEvent(t) }, i = /constructor/i.test(e.HTMLElement) || e.safari, f = /CriOS\/[\d]+/.test(navigator.userAgent), u = function (t) { (e.setImmediate || e.setTimeout)(function () { throw t }, 0) }, s = "application/octet-stream", d = 1e3 * 40, c = function (e) { var t = function () { if (typeof e === "string") { n().revokeObjectURL(e) } else { e.remove() } }; setTimeout(t, d) }, l = function (e, t, n) { t = [].concat(t); var r = t.length; while (r--) { var o = e["on" + t[r]]; if (typeof o === "function") { try { o.call(e, n || e) } catch (a) { u(a) } } } }, p = function (e) { if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)) { return new Blob([String.fromCharCode(65279), e], { type: e.type }) } return e }, v = function (t, u, d) { if (!d) { t = p(t) } var v = this, w = t.type, m = w === s, y, h = function () { l(v, "writestart progress write writeend".split(" ")) }, S = function () { if ((f || m && i) && e.FileReader) { var r = new FileReader; r.onloadend = function () { var t = f ? r.result : r.result.replace(/^data:[^;]*;/, "data:attachment/file;"); var n = e.open(t, "_blank"); if (!n) e.location.href = t; t = undefined; v.readyState = v.DONE; h() }; r.readAsDataURL(t); v.readyState = v.INIT; return } if (!y) { y = n().createObjectURL(t) } if (m) { e.location.href = y } else { var o = e.open(y, "_blank"); if (!o) { e.location.href = y } } v.readyState = v.DONE; h(); c(y) }; v.readyState = v.INIT; if (o) { y = n().createObjectURL(t); setTimeout(function () { r.href = y; r.download = u; a(r); h(); c(y); v.readyState = v.DONE }); return } S() }, w = v.prototype, m = function (e, t, n) { return new v(e, t || e.name || "download", n) }; if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { return function (e, t, n) { t = t || e.name || "download"; if (!n) { e = p(e) } return navigator.msSaveOrOpenBlob(e, t) } } w.abort = function () { }; w.readyState = w.INIT = 0; w.WRITING = 1; w.DONE = 2; w.error = w.onwritestart = w.onprogress = w.onwrite = w.onabort = w.onerror = w.onwriteend = null; return m }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content); if (typeof module !== "undefined" && module.exports) { module.exports.saveAs = saveAs } else if (typeof define !== "undefined" && define !== null && define.amd !== null) { define("FileSaver.js", function () { return saveAs }) }
/* icsFormatter
* A file generator
* By eastpiger
*/
var fileGenerator = function () {
'use strict';
if (navigator.userAgent.indexOf('MSIE') > -1 && navigator.userAgent.indexOf('MSIE 10') == -1) {
console.log('Unsupported Browser');
return;
}
return {
/**
* Download calendar using the saveAs function from filesave.js
* @param {string} filename Filename
* @param {string} ext Extention
*/
'download': function (filename, ext) {
var courseJson = JSON.stringify(rawdata);
if (courseJson) {
var targetStr = "index.js');"
var afterIndex = courseJson.indexOf(targetStr)
if (afterIndex != -1) {
courseJson = courseJson.substring(afterIndex + targetStr.length)
}
ext = (typeof ext !== 'undefined') ? ext : '.html';
filename = (typeof filename !== 'undefined') ? filename : '教务';
var blob = new Blob([courseJson], { type: 'attachment/csv;charset=utf-8' });
saveAs(blob, filename + ext);
} else return false;
}
};
};
var VER = "0.6";
var rawdata = undefined;
var mode = undefined;
function check_page_allow() {
try {
rawdata = $($("#frmright")[0].contentDocument).find("#div-table tbody")[0];
mode = "grad";
return true;
}
catch (error) {
console.error(error);
}
try {
rawdata = table0;
mode = "eams";
if (window.hasOwnProperty("unitCount")) {
rawdata.unitCount = unitCount;
}
return true;
}
catch (error) {
console.error(error);
}
try {
rawdata = window.table0;
if (window.hasOwnProperty("unitCount")) {
rawdata.unitCount = unitCount;
}
if (typeof rawdata !== 'undefined') {
mode = "eams";
return true;
}
}
catch (error) {
console.error(error);
}
var ifrs = $("iframe");
if (ifrs.length > 0) {
for (var i = 0; i < ifrs.length; i++) {
try {
rawdata = ifrs[i].contentWindow.table0;
if (ifrs[i].contentWindow.hasOwnProperty("unitCount")) {
rawdata.unitCount = ifrs[i].contentWindow.unitCount;
}
if (typeof rawdata !== 'undefined') {
mode = "eams";
return true;
}
} catch (error) {
console.error(error);
}
}
}
}
if (Boolean(window.$) && check_page_allow()) {
var semester = "";
try {
if (mode == "eams") {
semester = $("#courseTableForm input.calendar-text")[0].value;
} else if (mode == "grad") {
semester = $($($("#frmright")[0].contentDocument).find("#div-table div")[0]).html();
}
} catch (error) {
var semester = "教务";
}
window.icsObj = fileGenerator();
window.icsObj.download(semester);
if (mode == "eams")
setTimeout("alert('文件' + semester + '.html' + '已经保存到默认的下载文件夹中,请按照教程完成后续操作。————WakeUp课程表')", 500)
else if (mode == "grad")
alert("这种类型还没有支持哦,请到App关于页面联系开发者适配")
} else {
alert('加载失败,请确认是否进入正确页面!');
}
顺利的话,浏览器会自动下载一个 HTML 文件。如果提示还未适配,就按照提示跟开发者取得联系。如果没有文件下载,请先确定教务是不是真的是树维教务,树维教务长啥样在视频教程里有描述。如果确定真的是树维教务但还是不能自动下载文件,点这里把控制台截图发给我们。
4. 导入到 WakeUp课程表(不要点回自己学校)
找到浏览器自动下载的 HTML 文件(默认应该是在「下载」文件夹),然后通过 QQ 发送到手机 QQ 上,直接在 QQ 接收界面打开,选「用其他应用打开」,然后找到有我们 Logo 的「导入到课程表」。会弹窗让你选择是否覆盖当前课程表,如果选择新建一个的话,导入成功后记得点右上角三个点切换课表。
然后点「选择学校/教务类型」,找到「树维教务(简易导入)」,
这里是关键!!!按照本教程导入,必须选「树维教务(简易导入)」,而不是自己的学校。
选「树维教务(简易导入)」!
选「树维教务(简易导入)」!
选「树维教务(简易导入)」!
选择后,然后点右下角的下载按钮,应该就能成功导入了。