您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
导出慕课网的笔记,分为点赞和采集两种(本人编写的也会被导出)。导出的格式为json。导出过程可以暂停,下次在进行导出。
当前为
// ==UserScript== // @name 慕课网笔记导出 // @namespace https://github.com/yeomanye // @version 0.2 // @description 导出慕课网的笔记,分为点赞和采集两种(本人编写的也会被导出)。导出的格式为json。导出过程可以暂停,下次在进行导出。 // @author Ming Ye // @match http://www.imooc.com/*/* // @include https://www.imooc.com/*/* // @require https://greasyfork.org/scripts/34143-debug/code/debug.js?version=232648 // @require http://cdn.bootcss.com/jquery/1.8.3/jquery.min.js // @require https://greasyfork.org/scripts/27104-filesaver/code/FileSaver.js?version=173518 // @require https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js // @grant none // ==/UserScript== (function() { 'use strict'; var log = window.myDebugger.consoleFactory('慕课网导出笔记脚本:', 'color:brown;font-size:13px'), debugTrue = window.myDebugger.debugTrue(true); var $btnContainer = $('#main .course-info-main .content-wrap .mod-tab-menu .course-menu'), $collectBtn = $('<a id="exportNoteBtn" style="margin:10px;padding:10px;border-radius:5px;background-color:orange;color:white;cursor:pointer;">导出笔记</a>'),//采集按钮 $exportColCheck = $('<div style="display:inline-block;margin-right:10px"><input type="checkbox" id="exportColCheck"/><span style="color:white;">采集</span>'), $exportPraCheck = $('<input type="checkbox" id="exportPraCheck"/><span style="color:white;">点赞</span>'), $curPageLabel = $('<p id="curPage" style="margin-top:10px;margin-left:30px;color:white;"><span>当前采集页数:</span><span id="curPageNum">0</span></p>'); $collectBtn.click(btnClickHandler).appendTo($('#main .course-infos .hd')); $exportColCheck.appendTo($('#main .course-infos .hd')); $exportPraCheck.appendTo($('#main .course-infos .hd')); $curPageLabel.appendTo($('#main .course-infos .hd')); var isPause = true, courseId = window.location.pathname.split("/")[2], //课程ID baseUrl = window.location.protocol + '//' + window.location.hostname + '/note/' + courseId + '?sort=hot&page=', pageNum = localStorage.getItem('pageNum-'+courseId), //笔记页码 noteTimeout = null, userObj = fetchUser().data, //用户对象,保存用户相关信息 notes = JSON.parse(localStorage.getItem('notes-'+courseId)), // isCol = false,//是否收集采集的笔记 isPra = false;//是否收集点赞的笔记 log('课程ID', courseId); log('基准url', baseUrl); pageNum = pageNum ? pageNum : 1; /** * 导出笔记按钮点击事件 */ function btnClickHandler(){ isPause = !isPause; if(isPause){ $("#exportNoteBtn").text('导出笔记'); clearTimeout(noteTimeout) }else{ isCol = $('#exportColCheck')[0].checked; isPra = $('#exportPraCheck')[0].checked; $("#exportNoteBtn").text('暂停导出'); fetchNote(); } } /** * 采集笔记 */ function fetchNote(){ var htmlText = $.ajax({ url: baseUrl + pageNum, async: false }).responseText; //最后导出笔记 if(htmlText.indexOf('此课程暂无同学记录过笔记')>=0){ var blob = new Blob([JSON.stringify(notes)], {type: "text/plain;charset=utf-8"}); saveAs(blob, "notes.json"); return; } log('pageNum',pageNum); $("#curPageNum").html(pageNum); ++pageNum; var obj = getNoteElem(htmlText); var noteStatus = getUserNoteStatus(obj.noteIds); var colObj = getColObj(noteStatus); var colIdArr = []; //需要采集的笔记的id数组 if(isCol){ colIdArr = colObj.col; }else if(isPra){ for(var i=0,len=colObj.pra.length;i<len;i++){ colIdArr.push(colObj.pra[i]); } } var dataArr = fetchColContent(colIdArr,obj.noteStrArr); notes = notes || []; for (var i = 0, len = dataArr.length; i < len; i++) { notes.push(dataArr[i]); } log('pageNum',pageNum); // debugTrue(); localStorage.setItem('notes-'+courseId, JSON.stringify(notes)); localStorage.setItem('pageNum-'+courseId,pageNum); //当查询不到笔记容器id表示已经获取完所有的笔记了; noteTimeout = setTimeout(fetchNote,100); return ; } /** * 获取采集对象 * @param {array} colArr 采集参照的id数组 * @return {object} 采集对象 */ function fetchColContent(colArr,liStrArr) { var retDatas = []; for(var i=0,len=colArr.length;i<len;i++){ var id = colArr[i]; for(var j=0,len2=liStrArr.length;j<len2;j++){ var liStr = liStrArr[j]; if(liStr.indexOf('id="'+id+'"')>=0 || liStr.indexOf('authorid="'+userObj.uid+'"')>=0){ var patternNote = /<div class="js-notelist-content notelist-content mynote">[\s\S]*?<pre class="autowrap">([\s\S]*?)<\/pre>/g, patternUser = /<div class="tit">[\s\S]*?<a [\s\S]*? target="_blank">([\s\S]*?)<\/a>/g, patternTime = /<div class="footer clearfix">[\s\S]*?<span [\s\S]*?>时间:([\s\S]*?)<\/span>/g, patternChapter = /<div class="footer clearfix">[\s\S]*?<a [\s\S]*?>源自:([\s\S]*?)<\/a>/g, patternAuthLink = /<div class="media">[\s\S]*?<a href="([\s\S]*?)">/, patternScreenshot = /<div class="js-toggle-notelist answerImg">[\s\S]*?<img [\s\S]*? data-src="([\s\S]*?)"/, patternCourseLink = /<div class="footer clearfix">[\s\S]*?<a href="[\s\S]*?"/g, patternFileId = /<div class="disscus-code-icon-wrap">[\s\S]*?<i class="disscus-code-icon js-show-node-code" data-id="([\s\S]*?)"/g; var noteStr = patternNote.exec(liStr)[1], user = patternUser.exec(liStr)[1], time = patternTime.exec(liStr)[1], chapter = patternChapter.exec(liStr)[1], authLink = window.location.origin + patternAuthLink.exec(liStr)[1], courseLink = window.location.origin + patternCourseLink.exec(liStr)[1], matchScreenshotLink = patternScreenshot.exec(liStr), matchFileId = patternFileId.exec(liStr); var data = { note:noteStr, time:time, user:user, chapter:chapter, authLink:authLink, courseLink:courseLink }; //如果存在截图,则获取截图url if(matchScreenshotLink && matchScreenshotLink[1]){ data.screenshotLink = window.location.protocol+matchScreenshotLink[1] } //如果存在代码快照,则获取代码快照 if(matchFileId && matchFileId[1]){ var retStr = $.ajax({ url: 'https://www.imooc.com/course/viewnotecode?id='+matchFileId[1], async: false, }).responseText; data.codeFiles = JSON.parse(retStr).files; } log.logObj('data',data); retDatas.push(data); } } } log.logArr('fetchColContent', retDatas); return retDatas; } /** * 使用jsonp方式获取用户对象,获得对象后保存在window.usr中 */ function fetchUser() { var retStr = $.ajax({ url: window.location.protocol+'//www.imooc.com/u/card%20?jsonpcallback=getUser&_=' + new Date().getTime(), async: false, }).responseText; log('fetchUser', retStr); retStr = retStr.replace('getUser(', ''); retStr = retStr.substr(0, retStr.length - 1); var usr = JSON.parse(retStr); log.logObj('fetchUser', usr); return usr; } /** * 获取采集的id数组 * @param {object} noteStatus 笔记状态对象 * @return {object} 返回采集和点赞的数组{col:[],pra:[]} */ function getColObj(noteStatus) { var tmp = noteStatus.data.collections, retObj = { col: [], pra: [] }; for (var i = 0, len = tmp.length; i < len; i++) { retObj.col.push(tmp[i].src_note_id); } tmp = noteStatus.data.praises; for (var i = 0, len = tmp.length; i < len; i++) { retObj.pra.push(tmp[i].note_id); } log.logObj('getColIds', retObj); return retObj; } /** * 获取笔记元素的id和字符串数组 * @return {object} 笔记id和笔记元素字符串数组 */ function getNoteElem(htmlText){ var pattern = /<ul id="js-note-container" class="mod-post">([\s\S]*)?<\/ul>/g; var pattern1 = /<li id="([\d]+)" class="post-row js-find-txt" courseid="[\d]+" noteId="[\d]+" authorid="[\d]+">[\s\S]*?<\/li>/g; var matchArr = pattern.exec(htmlText), liIds = [], liStrArr = [], regInput = matchArr[0]; while(matchArr = pattern1.exec(regInput)){ log.logObj('matchArr',matchArr); liIds.push(matchArr[1]); liStrArr.push(matchArr[0]); } log.logObj('liStrArr',liStrArr); log.logArr('liIds',liIds); return {noteIds:liIds,noteStrArr:liStrArr}; } /** * 获取用户笔记状态 * @param {array} ids 用户笔记id数组 * @return {object} 用户笔记操作状态对象 */ function getUserNoteStatus(ids) { var retStr = $.ajax({ url: window.location.protocol+'//www.imooc.com/course/AjaxUserNotesStatus?ids=' + ids.join('%2C'), async: false }).responseText, retObj = JSON.parse(retStr); log('url',window.location.protocol+'//www.imooc.com/course/AjaxUserNotesStatus?ids=' + encodeURI(ids.join('%2C'))); log.logObj('getUserNoteStatus', retObj); return retObj; } })();