Cmpedu Resource Downloader

机械工业出版社教育服务网资源下载,无需登录(不可用),无需教师权限,油猴脚本。

目前为 2024-12-10 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Cmpedu Resource Downloader
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3
  5. // @description 机械工业出版社教育服务网资源下载,无需登录(不可用),无需教师权限,油猴脚本。
  6. // @author yanyaoli
  7. // @match *://*.cmpedu.com/ziyuans/ziyuan/*
  8. // @match *://*.cmpedu.com/books/book/*
  9. // @connect *.cmpedu.com
  10. // @grant GM_xmlhttpRequest
  11. // @grant GM_addStyle
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. // 动态设置 baseUrl,支持 www 和 m 域名
  18. const isMobile = window.location.host.startsWith('m.');
  19. const baseUrl = isMobile ? 'http://m.cmpedu.com' : 'http://www.cmpedu.com';
  20.  
  21. /**
  22. * 提取页面中的书籍 ID (BOOK_ID)
  23. * 适配两种路径:
  24. * - http://www.cmpedu.com/books/book/12345.htm
  25. * - http://www.cmpedu.com/ziyuans/ziyuan/12345.htm
  26. */
  27. let bookId = null;
  28. if (window.location.href.includes('books/book')) {
  29. bookId = window.location.pathname.split("/").pop().split(".")[0];
  30. } else if (window.location.href.includes('ziyuans/ziyuan')) {
  31. const bookIdElement = document.getElementById('BOOK_ID');
  32. bookId = bookIdElement ? bookIdElement.value : null;
  33. }
  34.  
  35. if (!bookId) {
  36. console.error("无法提取 BOOK_ID");
  37. return;
  38. }
  39.  
  40. // 资源页面 URL
  41. const resourceUrl = `${baseUrl}/ziyuans/index.htm?BOOK_ID=${bookId}`;
  42. const panelId = "downloadPanel";
  43.  
  44. /**
  45. * 创建显示下载链接的 UI 面板
  46. */
  47. const createPanel = () => {
  48. const panel = document.createElement('div');
  49. panel.id = panelId;
  50. panel.style = `
  51. position: fixed;
  52. top: 20px;
  53. left: 20px;
  54. width: 400px;
  55. max-height: 70vh;
  56. overflow-y: auto;
  57. background: #ffffff;
  58. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
  59. border-radius: 10px;
  60. padding: 15px;
  61. font-family: Arial, sans-serif;
  62. font-size: 14px;
  63. line-height: 1.5;
  64. color: #333;
  65. z-index: 10000;
  66. `;
  67. panel.innerHTML = `<strong>正在加载资源...</strong>`;
  68. document.body.appendChild(panel);
  69. };
  70.  
  71. /**
  72. * 更新面板内容
  73. * @param {string} content 要更新的 HTML 内容
  74. */
  75. const updatePanel = (content) => {
  76. const panel = document.getElementById(panelId);
  77. if (panel) panel.innerHTML = content;
  78. };
  79.  
  80. createPanel();
  81.  
  82. /**
  83. * 发送请求获取资源页面并解析内容
  84. */
  85. GM_xmlhttpRequest({
  86. method: "GET",
  87. url: resourceUrl,
  88. onload: function (response) {
  89. const parser = new DOMParser();
  90. const doc = parser.parseFromString(response.responseText, "text/html");
  91.  
  92. // 查找所有资源列表
  93. const resourceDivs = doc.querySelectorAll("div.row.gjzy_list");
  94. const resources = Array.from(resourceDivs).map(div => {
  95. const title = div.querySelector("div.gjzy_listRTit")?.textContent.trim() || "未知资源";
  96. const resourceId = div.querySelector("a")?.href.split("/").pop().split(".")[0];
  97. return { title, resourceId };
  98. });
  99.  
  100. if (resources.length === 0) {
  101. updatePanel("<strong>未找到资源。</strong>");
  102. return;
  103. }
  104.  
  105. let downloadLinksText = "";
  106. let pendingRequests = resources.length;
  107.  
  108. // 遍历资源,获取每个资源的下载链接
  109. resources.forEach(({ title, resourceId }) => {
  110. const downloadUrl = `${baseUrl}/ziyuans/d_ziyuan.df?id=${resourceId}`;
  111.  
  112. GM_xmlhttpRequest({
  113. method: "GET",
  114. url: downloadUrl,
  115. headers: {
  116. "Accept-Encoding": "gzip, deflate",
  117. "Connection": "keep-alive",
  118. "Accept": "text/html, */*; q=0.01",
  119. "User-Agent": "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
  120. "Accept-Language": "en-US,en;q=0.9",
  121. "X-Requested-With": "XMLHttpRequest"
  122. },
  123. onload: function (response) {
  124. // 匹配 window.location.href 的下载链接
  125. const downloadLinks = response.responseText.match(/window\.location\.href=\'(https?:\/\/[^\'"]+)\'/);
  126. if (downloadLinks) {
  127. const downloadLink = downloadLinks[1];
  128. downloadLinksText += `
  129. <div style="margin-bottom: 20px; display: flex; align-items: center;">
  130. <strong style="flex: 1;">${title}</strong>
  131. <a href="${downloadLink}" target="_blank" style="text-decoration: none;">
  132. <button style="
  133. display: flex;
  134. align-items: center;
  135. background: #007BFF;
  136. color: #fff;
  137. border: none;
  138. border-radius: 5px;
  139. padding: 10px 15px;
  140. cursor: pointer;
  141. font-size: 14px;
  142. transition: background 0.3s;
  143. " onmouseover="this.style.background='#0056b3'" onmouseout="this.style.background='#007BFF'">
  144. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="width: 20px; height: 20px; margin-right: 5px;">
  145. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a2 2 0 002 2h12a2 2 0 002-2v-1M8 10l4 4m0 0l4-4m-4 4V4" />
  146. </svg>
  147. 下载
  148. </button>
  149. </a>
  150. </div>`;
  151. } else {
  152. downloadLinksText += `
  153. <div style="margin-bottom: 20px; color: red;">
  154. <strong>${title}</strong><br>
  155. 未找到下载链接!
  156. </div>`;
  157. }
  158.  
  159. pendingRequests--;
  160. if (pendingRequests === 0) {
  161. updatePanel(downloadLinksText || "<strong>未找到有效的下载链接。</strong>");
  162. }
  163. },
  164. onerror: function () {
  165. downloadLinksText += `
  166. <div style="margin-bottom: 20px; color: red;">
  167. <strong>${title}</strong><br>
  168. 请求下载链接失败!
  169. </div>`;
  170. pendingRequests--;
  171. if (pendingRequests === 0) {
  172. updatePanel(downloadLinksText || "<strong>未找到有效的下载链接。</strong>");
  173. }
  174. }
  175. });
  176. });
  177. },
  178. onerror: function () {
  179. updatePanel("<strong>获取资源页面失败。</strong>");
  180. }
  181. });
  182. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址