您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
一键下载edX网课视频和字幕,并保存为相同的文件名(除了文件后缀)。<https://github.com/jks-liu/edx-downloader.monkey.js>
- // ==UserScript==
- // @name edX Downloader
- // @name:zh-CN edX网课下载器
- // @name:zh-TW edX網課下載器
- // @name:ja edXダウンローダー
- // @namespace https://github.com/jks-liu/edx-downloader.monkey.js
- // @supportURL https://github.com/jks-liu/edx-downloader.monkey.js
- // @version 2.0.1
- // @description Download edX course mp4 and srt in one click, and save them as same file name (except the file suffix). <https://github.com/jks-liu/edx-downloader.monkey.js>
- // @description:zh-CN 一键下载edX网课视频和字幕,并保存为相同的文件名(除了文件后缀)。<https://github.com/jks-liu/edx-downloader.monkey.js>
- // @description:zh-TW 一鍵下載edX網課視頻和字幕,並保存爲相同的文件名(除了文件後綴)。<https://github.com/jks-liu/edx-downloader.monkey.js>
- // @description:ja edXオンラインコースのビデオと字幕をワンクリックでダウンロードし、同じファイル名で保存します(ファイル拡張子を除く)。<https://github.com/jks-liu/edx-downloader.monkey.js>
- // @author Jks Liu (https://github.com/jks-liu)
- // @license MIT
- // @match https://edx.org/*
- // @match https://www.edx.org/*
- // @match https://learning.edx.org/*
- // @match https://courses.edx.org/*
- // @icon https://www.google.com/s2/favicons?domain=edx.com
- // @grant GM_download
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- // https://stackoverflow.com/questions/14308588/simple-jquery-selector-only-selects-first-element-in-chrome
- // If jQuery isn't present on the webpage, and of course no other code assigns something to $, Chrome's JS console assigns $ a shortcut to document.querySelector().
- // You can achieve what you want with $$(), which is assigned by the console a shortcut to document.querySelectorAll().
- // TODO: Add real title
- // TODO: Download in floder
- // TODO: label of already download
- // TODO: Process bar
- // TODO: Count of current course
- // TODO: Download html
- // TODO: Auto goto nextpage and download
- // jks_ is the namespace
- // The structure is as below
- // learning.edx.org -> Containing title
- // ifram, courses.edx.org -> Containing video address
- function jks_is_host(site) {
- return window.location.href.indexOf(site) != -1
- }
- function jks_learning_edu_org() {
- 'use strict';
- // Original page has no jQuery
- // $$ can be used in broswer, but not here
- // below line from https://github.com/akhodakivskiy/VimFx/issues/841#issuecomment-263197162
- const $$ = (...args) => Array.from(document.querySelectorAll(...args));
- var checkExist = setInterval(function() {
- let all_titles = $$("ol.list-unstyled a");
- let all_buttons = $$("div.sequence-navigation-tabs > button");
- if (all_titles.length && all_buttons.length) {
- clearInterval(checkExist);
- /// Get course meta data
- let course_name = all_titles[1].text;
- let paragraph_name = all_titles[2].text;
- let all_sections = all_buttons.map(button=>button.title);
- let active_section_index = all_buttons.findIndex(button=>button.classList.contains("active"));
- let active_section = all_sections[active_section_index];
- console.log("jks edx names", course_name, paragraph_name, active_section);
- GM_setValue("names", [course_name, paragraph_name, active_section, active_section_index]);
- /// Register action to detect meta data change
- let class_context = $$("div.sequence-navigation-tabs")[0];
- // https://stackoverflow.com/questions/38861601/how-to-only-trigger-parent-click-event-when-a-child-is-clicked/38861760
- class_context.addEventListener('click', function(event) {
- let button = event.target;
- while (button.nodeName != "BUTTON") {
- button = button.parentElement;
- }
- let new_section = button.title;
- let new_section_index = all_buttons.findIndex(b => b===button);
- GM_setValue("names", [course_name, paragraph_name, new_section, new_section_index]);
- }, true);
- }
- }, 100); // check every 100ms
- }
- function jks_courses_edx_org() {
- 'use strict';
- // Original page has jQuery
- // The content is under an iframe
- // So @match is https://courses.edx.org, not https://learning.edx.org
- // Can not use `window.$` as below ajax, don't know why
- let video = $('.video-download-button')[0];
- let video_url = video.href;
- // Create a button
- let download_all_button = document.createElement("div");
- download_all_button.innerHTML = `
- <label>
- <input id="jks_checkbox_mp4" type="checkbox", checked=true>
- <span>*.mp4</span>
- <input id="jks_checkbox_srt" type="checkbox", checked=true>
- <span>*.srt</span>
- <input id="jks_checkbox_txt" type="checkbox">
- <span>*.txt</span>
- </label>
- <button id="jks_button">Download All</button>
- <form>
- <label for="jks_input_folder">Folder</label>
- <input type="text" id="jks_input_folder" name="jks_input_folder" size="72">
- <label for="jks_input_mp4">*.mp4 location:</label>
- <input type="text" id="jks_input_mp4" name="jks_input_mp4" size="72">
- <label for="jks_input_srt">*.srt location:</label>
- <input type="text" id="jks_input_srt" name="jks_input_srt" size="72">
- <label for="jks_input_txt">*.txt location:</label>
- <input type="text" id="jks_input_txt" name="jks_input_txt" size="72">
- </form>
- `;
- // Video download event is at parent element
- // So add button after parent, or it's button click will be hide by parent
- // Add 2 other parentElement to widen input box
- video.parentElement.parentElement.parentElement.append(download_all_button)
- // Cannot use $, don't know why
- let srt_url = document.querySelector("li.transcript-option a").href;
- // Use $ instead of window.$, previously window.$ is ok, don't know why
- $.ajax({
- url: document.querySelector("li.transcript-option a").href,
- type: "HEAD",
- success: function(res, status, xhr) {
- let srt_header = xhr.getResponseHeader("content-disposition");
- // attachment; filename="02_TinyML_C02_03-01-01-en.srt" => 02_TinyML_C02_03-01-01-en.srt
- // let srt_file_name = srt_header.slice(22, -1);
- // let mp4_file_name = srt_file_name.slice(0, -4)+".mp4";
- // let txt_file_name = srt_file_name.slice(0, -4)+".txt";
- let names = GM_getValue("names", ["edx-unknown-course", "edx-unknown-paragraph", "edx-unknown-section"]);
- let folder_name = names[0]+"/"+names[1]
- let base_name = String(names[3]).padStart(2, "0")+"-"+names[2];
- let mp4_file_name = base_name + ".mp4";
- let srt_file_name = base_name + ".srt";
- let txt_file_name = base_name + ".txt";
- $("#jks_input_folder")[0].value = folder_name;
- $("#jks_input_mp4")[0].value = mp4_file_name;
- $("#jks_input_srt")[0].value = srt_file_name;
- $("#jks_input_txt")[0].value = txt_file_name;
- $("#jks_button").click(function() {
- if ($("#jks_checkbox_mp4")[0].checked) {
- // video is CORS (Cross-origin resource)
- // Set tampermonkey `Download Mode` option to `Browser API`
- // https://www.tampermonkey.net/faq.php?ext=dhdg#Q302
- GM_download(video_url, $("#jks_input_folder")[0].value+"/"+$("#jks_input_mp4")[0].value);
- }
- if ($("#jks_checkbox_srt")[0].checked) {
- GM_download(srt_url, $("#jks_input_folder")[0].value+"/"+$("#jks_input_srt")[0].value);
- }
- if ($("#jks_checkbox_txt")[0].checked) {
- // Txt and srt and the same file
- GM_download(srt_url, $("#jks_input_folder")[0].value+"/"+$("#jks_input_txt")[0].value);
- }
- })
- }
- })
- }
- (function() {
- 'use strict';
- if (jks_is_host("courses.edx.org")) {
- jks_courses_edx_org();
- }
- if (jks_is_host("learning.edx.org")) {
- jks_learning_edu_org();
- }
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址