尝试改造成 UserScript 脚本,这样就能在浏览器加载对应页面时,自动执行该脚本。
作出了如下更改:
- 使用
[class*="..."]
来匹配,希望在网站升级后还能自动匹配到。
- 定期检查并插入下载地址,这样在网站进行筛选操作后也会自动添加需要的链接。
- 稍微改了改插入地点,现在会显示在书名下方。
- 1.1 新增 - 将预览和下载分开,可以带文件名下载了(虽然跨域,但服务器允许
fetch
来跨域读取资源)。
- 1.2 新增 - 地址现在从图片资源地址来拼接了。
// ==UserScript==
// @name 国家中小学智慧教育平台 - 免登录下载
// @namespace www.52pojie.cn
// @match https://basic.smartedu.cn/tchMaterial*
// @grant none
// @version 1.2
// @author nctot@52pojie.cn / 爱飞的猫改造
// @description 在不登录的情况下显示 PDF 预览和下载地址。
// ==/UserScript==
function downloadBook(linkDownload) {
if (linkDownload.classList.contains('download-in-progress')) {
return;
}
linkDownload.classList.add('download-in-progress');
linkDownload.textContent = '下载中…';
fetch(linkDownload.href).then(r => {
if (r.status !== 200) {
throw new Error(`资源状态码不是 200 (实际值 ${r.status})`);
}
return r.blob();
}).then((pdfBlob) => {
const blobUrl = URL.createObjectURL(pdfBlob);
linkDownload.onclick = null;
linkDownload.href = blobUrl;
linkDownload.textContent = '【下载】';
// 触发下载,然后将地址删除 - 因为页面是由框架管理的,避免内存泄漏。
linkDownload.click();
setTimeout(() => {
linkDownload.href = '';
URL.revokeObjectURL(blobUrl);
});
}).catch((err) => {
linkDownload.textContent = `下载失败: ${err}`;
}).finally(() => {
linkDownload.classList.remove('download-in-progress');
});
}
function injectDownloadUrl() {
document.querySelectorAll('li[class*="index-module_item"]:not(.added)').forEach((item) => {
const rAssets = /\/assets\/([^.]+)\.t\/.+$/;
const imageUrl = item.querySelector('[class*="index-module_cover"] img').src;
if (rAssets.test(imageUrl)) {
const moduleLine = item.querySelector('div[class*="index-module_line"]');
const bookName = moduleLine.textContent.trim();
const bookUrl = imageUrl.replace(rAssets, '/assets_document/$1.pkg/pdf.pdf');
const dlContainer = document.createElement('div');
dlContainer.className = 'dl-preview';
dlContainer.style.cssText = `
cursor: alias;
font-size: smaller;
`;
const linkPreview = document.createElement('a');
linkPreview.href = bookUrl;
linkPreview.target = '_blank';
linkPreview.download = `${bookName}.pdf`;
linkPreview.textContent = '【预览】';
const linkDownload = document.createElement('a');
linkDownload.className = 'dl-book';
linkDownload.target = '_blank';
linkDownload.href = bookUrl;
linkDownload.download = `${bookName}.pdf`;
linkDownload.textContent = '【下载】';
dlContainer.appendChild(linkPreview);
dlContainer.appendChild(linkDownload);
moduleLine.insertAdjacentElement('afterend', dlContainer);
item.classList.add('added');
}
});
}
// 不让应用程序接管我们的点击事件
document.addEventListener('click', (e) => {
if (e.target.closest('.dl-preview')) {
e.stopPropagation();
}
if (e.target.closest('a.dl-book:not([href^="blob"])')) {
e.preventDefault();
downloadBook(e.target.closest('a.dl-book'));
}
}, { capture: true });
// 定期扫描页面更改
setInterval(injectDownloadUrl, 1500);
injectDownloadUrl();
书签版本(v1.2):
javascript:void(((v='1.2')=>{function downloadBook(e){e.classList.contains("download-in-progress")||(e.classList.add("download-in-progress"),e.textContent="下载中…",fetch(e.href).then((e=>{if(200!==e.status)throw new Error(`资源状态码不是 200 (实际值 ${e.status})`);return e.blob()})).then((t=>{const o=URL.createObjectURL(t);e.onclick=null,e.href=o,e.textContent="【下载】",e.click(),setTimeout((()=>{e.href="",URL.revokeObjectURL(o)}))})).catch((t=>{e.textContent=`下载失败: ${t}`})).finally((()=>{e.classList.remove("download-in-progress")})))}function injectDownloadUrl(){document.querySelectorAll('li[class*="index-module_item"]:not(.added)').forEach((e=>{const t=/\/assets\/([^.]+)\.t\/.+$/,o=e.querySelector('[class*="index-module_cover"] img').src;if(t.test(o)){const n=e.querySelector('div[class*="index-module_line"]'),l=n.textContent.trim(),s=o.replace(t,"/assets_document/$1.pkg/pdf.pdf"),a=document.createElement("div");a.className="dl-preview",a.style.cssText="\n cursor: alias;\n font-size: smaller;\n ";const d=document.createElement("a");d.href=s,d.target="_blank",d.download=`${l}.pdf`,d.textContent="【预览】";const c=document.createElement("a");c.className="dl-book",c.target="_blank",c.href=s,c.download=`${l}.pdf`,c.textContent="【下载】",a.appendChild(d),a.appendChild(c),n.insertAdjacentElement("afterend",a),e.classList.add("added")}}))}document.addEventListener("click",(e=>{e.target.closest(".dl-preview")&&e.stopPropagation(),e.target.closest('a.dl-book:not([href^="blob"])')&&(e.preventDefault(),downloadBook(e.target.closest("a.dl-book")))}),{capture:!0}),setInterval(injectDownloadUrl,1500),injectDownloadUrl()})())
效果如下: