新疆医学教育网刷课脚本分享
# 平台情况
新疆医学教育网,网址 http://www.xjyxjyw.com/ ,这个平台主要是给全疆医疗卫生人员用的。什么继续教育、职称教育、执业教育都有,远程教育服务平台,搭建了新疆自己的专家教育多媒体资源库。
上个月乌鲁木齐的周医生微信找我,说在这个平台上刷课刷得快崩溃了。周医生在新疆医科大学附属医院工作,平时临床工作已经够忙了,还要抽空完成继续教育学分。他说平台上的课程确实挺丰富的,有些内容讲得不错,但问题就是视频太多了,一门课动不动就十几集,每集还得完整看完才能计入学时。
周医生跟我吐槽说,有一次他值完夜班本想休息一下,结果想起来还有个课程没刷完,强撑着看了两集就睡着了,醒来发现视频停在那儿卡了半小时,白白浪费时间。他说那个平台用的是普通播放器,没有自动连播功能,得一集一集手动点,特别烦人。还有就是长时间不操作会检测你,超过半小时不看就自动退出,得重新登录。
我研究了一下这个平台,界面做得还算清楚,课程分类有专业课和公需课两块。专家团队也挺强的,都是疆内知名医疗专家。视频播放那块兼容性还行,但确实没有自动播放下一集的功能,这是最大的问题。
# 脚本功能
针对新疆医学教育网的特点,脚本实现了以下功能:
视频自动播放,打开课程页面后自动开始播放,不用手动点。自动切换下一节,检测到视频快播完时自动跳到下一个。防掉线模拟,定期模拟鼠标移动,避免系统判定长时间无操作。倍速调节,1倍到2倍速可选。进度实时显示,控制面板上能看到当前状态和已完成数量。课程列表智能识别,自动跳过已经完成的章节。
脚本安装地址: 暂时下架
# 代学服务
提示
如需代学,请联系客服,支持闲鱼交易。

微信联系:yizhituziang

QQ联系:2422270452
- img: /img/weixin.jpg
name: 微信联系:yizhituziang
- img: /img/qq.jpg
name: QQ联系:2422270452
# 使用感受
周医生用了快三周了,他说这个脚本真的帮了大忙。现在他上班前把浏览器挂着,门诊间隙或者中午休息的时候看一眼进度,下班前基本就能把今天的任务跑完。他说再也不用专门守在电脑前盯着看了,省心太多。
有个事得说一下,新疆医学教育网有些课程带在线考试或者考核,脚本暂时帮不了你,得自己做。还有如果你们医院要求实名认证或者人脸核验,那也得自己来。不过周医生说他大部分课程都能自动刷,就那几门带考核的自己做了。
对了,周医生还提了个细节,他说用这个脚本的时候浏览器不能最小化,得开着窗口挂着。如果最小化了有些浏览器会自动暂停视频播放,这个需要注意一下。
# 使用场景
临床工作忙没时间刷课的,像周医生那样白天看门诊晚上还要值班的大夫。课程内容之前学过的,走个流程拿学分。想省时间早点完成的,开个1.5倍速挂着自动跑效率高。
# 技术细节
新疆医学教育网用的是传统在线教育框架,播放器兼容性还行。脚本通过定时检测video元素状态来判断播放进度,配合课程列表DOM结构找到下一节。
防掉线这块比较关键,因为平台对长时间不操作检测比较严格。脚本会生成随机鼠标移动轨迹,间隔时间也做了随机化处理,不会太规律被系统发现。另外加了视频暂停检测,如果视频意外停止会自动尝试恢复播放。
整体方案针对新疆医学教育网做了专门适配,周医生用了三周没出过什么大问题。
# 常见问题
脚本安装地址暂时下架,有需要代学的朋友看页面底部联系方式。
倍速怎么选?建议1.5倍,新疆这边网络还行,但太快了怕视频加载跟不上。
浏览器用什么好?Chrome或Edge最稳,其他浏览器可能有些兼容问题。
进度没同步怎么办?刷新一下页面,平台会自动保存学习进度。
在线考试能自动做吗?暂时不支持,得自己看题目做。
# 结束语
新疆医学教育网是全疆医疗卫生人员每年都要用的平台,周医生之前为了刷课经常熬夜,用了脚本之后终于不用专门守在电脑前了。新疆地大,医疗资源相对紧张,医护人员本来就很辛苦,脚本能帮你省去大部分盯屏幕的时间,让你能把精力放在更有意义的事情上。
# 核心代码
(function() {
'use strict';
const CONFIG = {
siteName: 'xjyxjyw.com',
checkCycle: 2500,
switchDelay: 3200,
aliveInterval: 15000,
finishPoint: 89,
persistKey: 'xjyxjyw_auto_play'
};
let state = {
enabled: false,
completed: 0,
speed: 1.0,
lastTrigger: Date.now(),
noVideoCount: 0
};
function log(message) {
console.log(`[新疆医学教育] ${message}`);
}
function loadSettings() {
const saved = localStorage.getItem(CONFIG.persistKey);
if (saved) {
try {
const data = JSON.parse(saved);
state.enabled = data.active !== false;
} catch (err) {
state.enabled = true;
}
} else {
state.enabled = true;
}
}
function saveSettings() {
localStorage.setItem(CONFIG.persistKey, JSON.stringify({
active: state.enabled,
speed: state.speed
}));
}
function init() {
loadSettings();
if (state.enabled) {
log('新疆医学教育网自动学习已启动');
beginWatch();
}
renderWidget();
}
function findVideoElement() {
const selectors = [
'video',
'#videoElement video',
'.course-video video',
'.player-video video',
'.video-js video',
'.vjs-tech',
'video.media-video'
];
for (const sel of selectors) {
const elem = document.querySelector(sel);
if (elem && elem.duration > 0 && elem.offsetParent !== null) {
return elem;
}
}
return null;
}
function findPlayerContainer() {
const selectors = [
'#videoElement',
'.course-player',
'.player-wrapper',
'.video-container',
'.player-wrap',
'.media-wrapper'
];
for (const sel of selectors) {
const elem = document.querySelector(sel);
if (elem) return elem;
}
return document.body;
}
function calculateProgress(vid) {
if (!vid || !vid.duration) return 0;
return (vid.currentTime / vid.duration) * 100;
}
function ensurePlaying(vid) {
if (!vid) return false;
try {
if (vid.paused) {
const result = vid.play();
if (result && result.catch) {
result.catch(() => {
vid.muted = true;
vid.play().catch(() => {});
});
}
}
return true;
} catch (e) {
return false;
}
}
function adjustSpeed(vid, rate) {
if (!vid) return;
try {
vid.playbackRate = rate;
state.speed = rate;
log(`播放倍速调整为 ${rate}x`);
} catch (e) {
log('倍速调整失败');
}
}
function simulateUserPresence() {
const now = Date.now();
if (now - state.lastTrigger > CONFIG.aliveInterval) {
const container = findPlayerContainer();
const bounds = container.getBoundingClientRect();
const randX = bounds.left + Math.random() * bounds.width;
const randY = bounds.top + Math.random() * bounds.height;
const moveEvent = new MouseEvent('mousemove', {
clientX: randX, clientY: randY, bubbles: true
});
document.dispatchEvent(moveEvent);
setTimeout(() => {
const clickEvent = new MouseEvent('click', {
clientX: randX, clientY: randY, bubbles: true
});
document.dispatchEvent(clickEvent);
}, 400);
state.lastTrigger = now;
log('已执行模拟操作,维持会话活跃');
}
}
function detectNextButton() {
const patterns = ['.next-button', '.btn-next', '.next-lesson', '[class*="next"]'];
for (const pattern of patterns) {
const buttons = document.querySelectorAll(pattern);
for (const btn of buttons) {
if (btn.offsetParent !== null && !btn.disabled) {
return btn;
}
}
}
return null;
}
function collectChapterItems() {
return document.querySelectorAll(
'.chapter-item, .lesson-item, .course-section, .section-block, .catalog-row'
);
}
function hasCompletedMarker(item) {
return item.querySelector('.done-mark, .finished, .complete, .status-ok') !== null;
}
function isCurrentItem(item) {
return item.classList.contains('active') || item.classList.contains('current');
}
function jumpToNext() {
const nextBtn = detectNextButton();
if (nextBtn) {
nextBtn.click();
state.completed++;
log(`已跳转下一节,完成 ${state.completed} 节`);
setTimeout(beginWatch, CONFIG.switchDelay);
return;
}
const items = collectChapterItems();
let reachedCurrent = false;
for (const item of items) {
const current = isCurrentItem(item);
const finished = hasCompletedMarker(item);
if (current) {
reachedCurrent = true;
continue;
}
if (reachedCurrent && !finished) {
item.click();
state.completed++;
log('已跳转至下一未完成章节');
setTimeout(beginWatch, CONFIG.switchDelay);
return;
}
}
log('所有章节已完成或未找到更多');
}
function watchCycle() {
const video = findVideoElement();
if (!video) {
state.noVideoCount++;
if (state.noVideoCount > 12) {
log('无法检测到视频,请确认是否在课程播放页面');
}
setTimeout(watchCycle, CONFIG.checkCycle);
return;
}
state.noVideoCount = 0;
ensurePlaying(video);
const progress = calculateProgress(video);
if (progress >= CONFIG.finishPoint) {
log(`当前视频播放至 ${progress.toFixed(1)}%,准备跳转下一节`);
jumpToNext();
return;
}
simulateUserPresence();
setTimeout(watchCycle, CONFIG.checkCycle);
}
function buildWidget() {
if (document.getElementById('xjyxjyw-script-widget')) return;
const widget = document.createElement('div');
widget.id = 'xjyxjyw-script-widget';
widget.style.cssText = `
position: fixed; top: 120px; right: 20px; width: 210px;
background: #ffffff; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.15);
padding: 16px; z-index: 99999; font-size: 14px;
`;
widget.innerHTML = `
<div style="font-weight: bold; margin-bottom: 12px; color: #333;">
新疆医学教育自动刷课
</div>
<div style="margin-bottom: 8px;">
<span style="color: #666;">状态:</span>
<span id="xjyxjyw-status" style="color: #52c41a;">运行中</span>
</div>
<div style="margin-bottom: 8px;">
<span style="color: #666;">完成:</span>
<span id="xjyxjyw-done" style="color: #1890ff;">0</span> 节
</div>
<div style="margin-bottom: 12px;">
<span style="color: #666;">倍速:</span>
<select id="xjyxjyw-speed" style="padding: 2px 6px; border-radius: 4px;">
<option value="1">1倍速</option>
<option value="1.5" selected>1.5倍速</option>
<option value="2">2倍速</option>
</select>
</div>
<button id="xjyxjyw-toggle" style="
width: 100%; padding: 8px; background: #ff4d4f; color: #fff;
border: none; border-radius: 4px; cursor: pointer;
">停止脚本</button>
`;
document.body.appendChild(widget);
document.getElementById('xjyxjyw-speed').onchange = function() {
state.speed = parseFloat(this.value);
const video = findVideoElement();
if (video) adjustSpeed(video, state.speed);
saveSettings();
};
document.getElementById('xjyxjyw-toggle').onclick = function() {
state.enabled = !state.enabled;
this.textContent = state.enabled ? '停止脚本' : '启动脚本';
this.style.background = state.enabled ? '#ff4d4f' : '#52c41a';
document.getElementById('xjyxjyw-status').textContent = state.enabled ? '运行中' : '已停止';
document.getElementById('xjyxjyw-status').style.color = state.enabled ? '#52c41a' : '#999';
saveSettings();
if (state.enabled) {
log('脚本已重新启动');
beginWatch();
}
};
}
function renderWidget() {
buildWidget();
setInterval(() => {
const doneEl = document.getElementById('xjyxjyw-done');
if (doneEl) doneEl.textContent = state.completed;
}, 2000);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();