百度网盘网课进度同步神器教程
百度网盘视频自动识别 + 坚果云跨设备同步(油猴脚本)
v10.0 更新:支持记录播放时间,按钮实时显示已观看时长,自动消失提示不打断操作
一、脚本介绍
这款油猴脚本专为公考网课学习打造,完美解决百度网盘看课的三大痛点:
- 多门网课来回切换,找不到上次看到哪一集
- 换电脑,学习进度全部丢失
- 手动记网址、存书签太麻烦,效率极低
v10.0 新功能
- 自动识别当前播放的网盘视频属于哪门课程
- 仅需1个保存按钮,一键同步进度到坚果云云端
- 跳转按钮实时显示播放时长(如
花生资料分析(01:30)) - 提示改为自动消失弹窗,不再打断视频播放
- 修复拖动冲突:拖动面板时不会误触发按钮点击
- 跨电脑、跨浏览器 100% 同步进度
- 多课程进度独立存储,互不覆盖冲突
- 基于坚果云 WebDAV 存储,安全稳定、无广告、不失效
适配课程:可无限添加,言语理解/判断推理/申论等任意网盘课程
二、前置准备
1. 安装脚本管理器
Tampermonkey(推荐)
- Chrome / Edge / Firefox 统统支持:
https://www.tampermonkey.net 点 Download,按浏览器指引一键装。
脚本猫(国产浏览器友好)
官网安装指引:https://docs.scriptcat.org
2. 开启坚果云 WebDAV(用于云端同步)
- 打开坚果云官网并登录:https://www.jianguoyun.com/
- 进入「账号信息」→「安全选项」
- 找到 WebDAV 密码,点击「添加应用密码」
- 记录3项信息:
- WebDAV 地址:
https://dav.jianguoyun.com/dav/ - 坚果云登录账号(手机号/邮箱)
- 刚生成的应用密码(不是登录密码)
- WebDAV 地址:
三、脚本安装步骤
- 点击浏览器右上角 🐵 油猴图标
- 选择「添加新脚本」
- 全选删除默认的空白模板代码
- 复制下方完整脚本代码,粘贴进去
- 点击「文件」→「保存」(或 Ctrl+S)
- 关闭编辑页面,安装完成
// ==UserScript==
// @name 公考网课进度同步
// @namespace http://tampermonkey.net/
// @version 10.0
// @description 保存视频进度,按钮显示时分,自动消失提示,修复拖动冲突,坚果云同步
// @author 豆包
// @match *://pan.baidu.com/pfile/video*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_log
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// ==================== 课程配置 ====================
const COURSES = [
{
name: "花生资料分析",
pathFlag: "/2026%E4%B8%8A%E5%B2%B8/%E8%B5%84%E6%96%99%E5%88%86%E6%9E%90/",
saveFile: "progress_huasheng.txt"
},
{
name: "高照数量关系",
pathFlag: "/2026%E4%B8%8A%E5%B2%B8/2025%E5%B9%B4%E9%AB%98%E7%85%A7%E8%B5%84%E6%96%99%E9%A2%98%E5%9E%8B%E5%A4%B8%E5%A4%B8%E5%88%B7%E5%88%B7%E9%A2%98%E8%90%A5/",
saveFile: "progress_gaozhao.txt"
}
];
// ==================== 坚果云配置 ====================
const WEBDAV_ROOT = "https://dav.jianguoyun.com/dav/";
const ACCOUNT = "替换为你的@qq.com";
const AUTH_TOKEN = "替换为你的";
const SAVE_DIR = "tampermonkey_sync/";
const auth = btoa(unescape(encodeURIComponent(ACCOUNT + ":" + AUTH_TOKEN)));
// ==================== 秒数 → 仅显示 时:分 ====================
function formatTime(seconds) {
const totalMin = Math.round(seconds / 60);
const h = Math.floor(totalMin / 60);
const m = totalMin % 60;
return `${h.toString().padStart(2,'0')}:${m.toString().padStart(2,'0')}`;
}
// ==================== 获取当前视频播放秒数 ====================
function getVideoTime() {
const videos = document.querySelectorAll('video');
return videos.length ? (videos[0].currentTime || 0) : 0;
}
// ==================== 识别当前课程 ====================
function getCurrentCourse() {
const url = location.href;
return COURSES.find(c => url.includes(c.pathFlag)) || null;
}
// ==================== 确保目录 ====================
async function ensureDir() {
return new Promise(resolve => {
GM_xmlhttpRequest({
method: "MKCOL",
url: WEBDAV_ROOT + SAVE_DIR,
headers: { Authorization: "Basic " + auth },
onload: () => resolve(true),
onerror: () => resolve(true)
});
});
}
// ==================== 自动消失提示框(替代alert) ====================
function toast(msg) {
const old = document.getElementById('syncToast');
if (old) old.remove();
const div = document.createElement('div');
div.id = 'syncToast';
div.textContent = msg;
document.body.appendChild(div);
setTimeout(() => div.style.opacity = '0', 2000);
setTimeout(() => div.remove(), 2500);
}
// ==================== 保存进度(含播放时间) ====================
async function saveProgress() {
const course = getCurrentCourse();
if (!course) return toast("⚠️ 不属于配置课程");
await ensureDir();
const videoUrl = location.href;
const currentSec = getVideoTime();
const saveData = `${videoUrl}|${currentSec}`;
GM_xmlhttpRequest({
method: "PUT",
url: WEBDAV_ROOT + SAVE_DIR + course.saveFile,
headers: { Authorization: "Basic " + auth, "Content-Type": "text/plain" },
data: saveData,
onload: resp => {
if (resp.status >= 200 && resp.status < 300) {
toast(`✅ 已保存\n${course.name} ${formatTime(currentSec)}`);
loadAllCourseProgress();
} else toast(`❌ 保存失败 ${resp.status}`);
},
onerror: () => toast("⚠️ 网络异常")
});
}
// ==================== 打开课程链接 ====================
function openCourse(course) {
GM_xmlhttpRequest({
method: "GET",
url: WEBDAV_ROOT + SAVE_DIR + course.saveFile,
headers: { Authorization: "Basic " + auth },
onload: r => {
if (r.status === 200 && r.responseText.trim()) {
const [url] = r.responseText.trim().split('|');
window.open(url, '_blank');
toast(`✅ 正在打开 ${course.name}`);
} else toast(`🆘 ${course.name} 无进度记录`);
}
});
}
// ==================== 加载进度显示到按钮 ====================
function loadAllCourseProgress() {
COURSES.forEach((course, idx) => {
GM_xmlhttpRequest({
method: "GET",
url: WEBDAV_ROOT + SAVE_DIR + course.saveFile,
headers: { Authorization: "Basic " + auth },
onload: r => {
let timeText = "未记录";
if (r.status === 200 && r.responseText.trim()) {
const [, sec] = r.responseText.trim().split('|');
timeText = formatTime(parseFloat(sec) || 0);
}
const btn = document.querySelector(`.jumpBtn[data-index="${idx}"]`);
if (btn) btn.innerText = `${course.name}(${timeText})`;
}
});
});
}
// ==================== 全局样式 ====================
GM_addStyle(`
#studyPanel { position: fixed; z-index: 999999; width: 240px; background: #fff;
border-radius: 8px; box-shadow: 0 3px 10px rgba(0,0,0,.1); padding: 10px;
font-size: 14px; user-select: none; cursor: grab; top: 20px; right: 20px; }
#studyPanel:active { cursor: grabbing; }
#saveBtn { width: 100%; height: 40px; border: none; border-radius: 6px;
background: #007BFF; color: #fff; font-size: 15px; cursor: pointer; margin-bottom: 10px; }
#saveBtn:hover { background: #0056b3; }
.jumpBtn { width: 100%; height: 38px; border: none; border-radius: 4px;
background: #f5f5f5; color: #333; cursor: pointer; margin: 4px 0;
padding: 0 10px; text-align: left; }
.jumpBtn:hover { background: #e6f7ff; color: #007BFF; }
#syncToast { position: fixed; z-index: 9999999; bottom: 30px; left: 50%;
transform: translateX(-50%); background: #333; color: #fff; padding: 10px 20px;
border-radius: 6px; font-size: 14px; opacity: 1;
transition: opacity 0.5s ease; white-space: pre-line; }
`);
// ==================== 面板 ====================
const panel = document.createElement('div');
panel.id = 'studyPanel';
let html = `<button id="saveBtn">📌 保存当前播放进度</button>`;
html += `<div style="margin:6px 0;font-weight:bold;color:#666">上次进度(hh:mm)</div>`;
COURSES.forEach((_, i) => {
html += `<button class="jumpBtn" data-index="${i}">加载中...</button>`;
});
panel.innerHTML = html;
document.body.appendChild(panel);
// ==================== 修复拖动逻辑(仅空白处可拖动) ====================
function makeDraggable(element) {
let isDragging = false;
let offsetX, offsetY;
element.addEventListener('mousedown', (e) => {
if (e.target.tagName === 'BUTTON') return;
isDragging = true;
offsetX = e.clientX - element.getBoundingClientRect().left;
offsetY = e.clientY - element.getBoundingClientRect().top;
element.style.cursor = 'grabbing';
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
element.style.left = e.clientX - offsetX + 'px';
element.style.top = e.clientY - offsetY + 'px';
element.style.right = 'auto';
});
document.addEventListener('mouseup', () => {
if (isDragging) {
isDragging = false;
element.style.cursor = 'grab';
}
});
}
makeDraggable(panel);
// ==================== 按钮事件 ====================
document.getElementById('saveBtn').onclick = saveProgress;
document.querySelectorAll('.jumpBtn').forEach(btn => {
btn.onclick = (e) => {
e.stopPropagation();
openCourse(COURSES[btn.dataset.index]);
};
});
loadAllCourseProgress();
GM_log("进度同步脚本 完美版加载完成");
})();
四、v10.0 升级说明
相比 v7.0,主要变化:
| 功能 | v7.0 | v10.0 |
|---|---|---|
| 保存内容 | 仅视频链接 | 视频链接 + 播放秒数 |
| 按钮显示 | 课程名称 | 课程名称 + 已观看时长 |
| 提示方式 | alert() 弹窗(打断播放) | toast() 自动消失(不打断) |
| 拖动冲突 | 可能误触发按钮 | 仅空白处可拖动 |
| 按钮初始状态 | 直接显示课程名 | 显示"加载中..." |
五、基础使用教程
1. 打开网盘视频
在浏览器中打开百度网盘的视频播放页:
https://pan.baidu.com/pfile/video?path=/2026省考/花生资料分析/xxx.mp4
2. 识别当前课程
脚本会自动识别当前视频属于哪门课程,面板右上角显示实时已观看时长。
3. 保存学习进度
点击右侧面板:
📌 保存当前播放进度
底部弹出自动消失提示,显示 ✅ 已保存 花生资料分析 01:30。
4. 跳转到最新进度
直接点击对应课程名称按钮,按钮上会显示上次保存时记录的总时长。
5. 跨设备使用
在另一台电脑/浏览器安装油猴 + 本脚本,点击课程名即可同步进度,无需任何额外设置。
六、自定义修改教程
1. 修改坚果云账号(替换为自己的)
找到代码中这一段,替换为你的坚果云账号和 WebDAV 应用密码:
const WEBDAV_ROOT = "https://dav.jianguoyun.com/dav/";
const ACCOUNT = "替换为你的@qq.com";
const AUTH_TOKEN = "替换为你的";
修改后保存,即可使用自己的坚果云存储。
2. 添加新一门网课(无限扩展)
在 COURSES 数组中追加对象:
{
name: "课程名称",
pathFlag: "网盘链接路径前缀",
saveFile: "progress_自定义文件名.txt"
}
如何获取 pathFlag(关键)
- 打开该课程任意几集视频
- 复制地址栏中
path=之后、.mp4之前的公共前缀 - 示例:
/2026%E4%B8%8A%E5%B2%B8/xxx课程/
添加完成后,刷新页面,面板会自动新增该课程的跳转按钮。
3. 修改界面样式
找到代码中的 GM_addStyle 部分,可以自定义:
- 面板宽度:
width: 240px - 按钮颜色:
background: #007BFF - 面板位置:
right: 20px; top: 20px
七、常见问题排查
1. 保存失败 404 / 409
- 原因:坚果云目录未创建成功
- 解决:脚本已内置
MKCOL自动创建目录,重新点击保存即可 - 检查:WebDAV 账号密码是否正确
2. 提示「不属于已配置的课程」
- 原因:
pathFlag路径前缀填写错误 - 解决:重新复制网盘链接中的编码路径,确保完全匹配
3. 跳转提示「无进度记录」
- 原因:该课程从未保存过进度
- 解决:先打开对应课程视频,点击「保存进度」后再跳转
4. 油猴不显示面板
- 原因:仅在
pan.baidu.com/pfile/video播放页生效 - 解决:必须打开视频播放页面,而非文件列表页
5. 跨设备不同步
- 原因:两台设备使用的不是同一个坚果云账号
- 解决:确认所有设备脚本中的 ACCOUNT、AUTH_TOKEN 完全一致
6. 按钮一直显示"加载中..."
- 原因:坚果云账号密码错误,无法读取云端文件
- 解决:检查 ACCOUNT 和 AUTH_TOKEN 是否填写正确
八、让AI把本文代码修改为适合自己的方式
请把本文全部复制后给到AI。
提示词:请你学习后,把代码改为适合我的。我可以提供你几个我在学习的网课视频链接,你分析下。
- 链接1
- 链接2
- 链接3 .......