// ==UserScript== // @name 豆瓣资源下载大师:1秒搞定豆瓣电影|图书|音乐下载(精简重构版) // @namespace http://tampermonkey.net/ // @version 4.1.1 // @description 合并自「豆瓣电影网盘资源自动搜索」与「在豆瓣读书显示 Z-Library 书籍」,剔除原版海量失效死链与 jQuery 依赖。新增豆瓣音乐全网下载试听与无感复制,并修复了 IMDb 评分展示等体验。 // @author Tim (Fixed by AI) // @match https://movie.douban.com/subject/* // @match https://book.douban.com/subject/* // @match https://music.douban.com/subject/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_setClipboard // @connect * // @license MIT // ==/UserScript== (function () { 'use strict'; // ========================================== // 通用辅助函数 // ========================================== function getDoc(url, callback, errorCallback) { GM_xmlhttpRequest({ method: 'GET', url: url, withCredentials: true, onload: function (responseDetail) { let resText = responseDetail.responseText; if (responseDetail.status === 503 || responseDetail.status === 403 || resText.includes("Checking your browser") || resText.includes("Just a moment")) { if (errorCallback) errorCallback("captcha"); return; } if (responseDetail.status === 200 || responseDetail.status === 404) { callback((new DOMParser()).parseFromString(resText, 'text/html'), responseDetail); } else { if (errorCallback) errorCallback("error"); } }, onerror: function () { if (errorCallback) errorCallback("error"); } }); } // ========================================== // 第一模块:豆瓣电影(网盘搜索 + IMDb评分) // ========================================== function initMovieScript() { // 样式注入 GM_addStyle(` .douban-pan-search { margin-bottom: 30px; padding: 15px; background: #f8fcf8; border-radius: 4px; border: 1px solid #e2ece2; } .douban-pan-search h2 { color: #007722; margin: 0 0 10px 0; font-size: 15px; border-bottom: 1px dashed #dddddd; padding-bottom: 5px; } .pan-search-loading { color: #666; font-size: 13px; } .pan-item { margin: 8px 0; font-size: 13px; display: flex; align-items: center; } .pan-item a { color: #3377aa; text-decoration: none; max-width: 170px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-right: 5px; } .pan-item a:hover { color: #ffffff; background-color: #3377aa; } .pan-tag { display: inline-block; padding: 2px 5px; border-radius: 2px; font-size: 11px; margin-right: 5px; color: #fff; flex-shrink: 0; } .tag-ali { background-color: #ff6a00; } .tag-baidu { background-color: #06a7ff; } .tag-quark { background-color: #00b4ff; } .tag-other { background-color: #999; } .pan-pwd { margin-left: 5px; color: #e74c3c; font-family: monospace; cursor: pointer; flex-shrink: 0; } /* 评分增强区域样式 */ .imdb-badge { color: #e5a826; font-weight: bold; margin-left: 5px; text-decoration: none; font-size: 13px; } .imdb-badge:hover { color: #d19720; } .imdb-votes { color: #999; font-size: 11px; margin-left: 4px; } `); // 提取豆瓣电影信息 let titleNode = document.querySelector('h1 span[property="v:itemreviewed"]'); if (!titleNode) return; let rawTitle = titleNode.innerText.trim(); let mainTitle = rawTitle.split(' ')[0]; // 取冒号或空格前的主标题 // 构建侧边栏面板 let aside = document.querySelector('.aside'); if (!aside) return; let panel = document.createElement('div'); panel.className = 'douban-pan-search'; panel.innerHTML = `

☁️ 网盘资源检索

🔄 正在拦截全网《${mainTitle}》的分享链接...
`; aside.insertBefore(panel, aside.firstChild); // 请求搜索数据 let container = document.getElementById('pan-results'); let keyword = encodeURIComponent(mainTitle); let apiUrl = `https://so.252035.xyz/api/search?kw=${keyword}`; GM_xmlhttpRequest({ method: "GET", url: apiUrl, onload: function (response) { if (response.status === 200) { try { let res = JSON.parse(response.responseText); if (res.code === 0 && res.data && res.data.merged_by_type) { let results = []; let merged = res.data.merged_by_type; let typesToExtract = [ { key: 'ali', label: 'ali' }, { key: 'quark', label: 'quark' }, { key: 'baidu', label: 'baidu' }, { key: 'xunlei', label: 'other' } ]; typesToExtract.forEach(t => { let list = merged[t.key] || []; list.slice(0, 3).forEach(item => { results.push({ name: item.note || '未命名资源', url: item.url, type: t.label, pwd: item.password || '' }); }); }); renderPanResults(results, container); } else { renderPanResults([], container); } } catch (e) { container.innerHTML = '⚠️ 数据解析失败,接口可能变更。'; } } else { container.innerHTML = `⚠️ 请求聚合服务器失败 (${response.status})。`; } }, onerror: function () { container.innerHTML = '⚠️ 网络请求异常,请检查跨域配置。'; } }); // 附加:解析 IMDb 评分展示(原版豆瓣下载大师核心亮点) let infoDiv = document.getElementById('info'); if (infoDiv) { let imdbMatch = infoDiv.innerText.match(/IMDb:?\s*(tt\d+)/); if (imdbMatch && imdbMatch[1]) { fetchImdbRating(imdbMatch[1]); } } } function renderPanResults(results, container) { if (!results || results.length === 0) { container.innerHTML = '⚠️ 抱歉,未找到直接匹配的高清网盘资源。'; return; } let html = ''; results.forEach(res => { let tagClass = 'tag-other', tagText = '其他'; if (res.type === 'ali') { tagClass = 'tag-ali'; tagText = '阿里'; } else if (res.type === 'baidu') { tagClass = 'tag-baidu'; tagText = '百度'; } else if (res.type === 'quark') { tagClass = 'tag-quark'; tagText = '夸克'; } let pwdHtml = res.pwd ? `🔑 ${res.pwd}` : ''; html += `
${tagText} ${res.name} ${pwdHtml}
`; }); container.innerHTML = html; } function fetchImdbRating(imdbId) { let infoDiv = document.getElementById('info'); if (!infoDiv) return; let imdbUrl = 'https://www.imdb.com/title/' + imdbId + '/'; getDoc(imdbUrl, function (doc) { try { let rating = '', votes = ''; // 解析方法 1: 新一代 IMDb Next.js JSON 数据 let nextData = doc.querySelector('script#__NEXT_DATA__'); if (nextData) { try { let data = JSON.parse(nextData.innerHTML); let aboveTheFold = data.props.pageProps.aboveTheFoldData; rating = aboveTheFold.ratingsSummary.aggregateRating; votes = aboveTheFold.ratingsSummary.voteCount; } catch (e) { } } // 解析方法 2: 传统的 ld+json if (!rating) { let ldJson = doc.querySelector('script[type="application/ld+json"]'); if (ldJson) { try { let data = JSON.parse(ldJson.innerText); if (data.aggregateRating) { rating = data.aggregateRating.ratingValue; votes = data.aggregateRating.ratingCount; } } catch (e) { } } } // 解析方法 3: 直接查找 DOM if (!rating) { let ratingEl = doc.querySelector('[data-testid="hero-rating-bar__aggregate-rating__score"] span'); if (ratingEl) { rating = ratingEl.innerText; } let voteEl = doc.querySelector('.kn-1x1-stars span.bYitIg, div[data-testid="hero-rating-bar__aggregate-rating__score"] ~ div:last-child'); if (voteEl) { votes = voteEl.innerText; } } if (rating) { let badge = document.createElement('span'); badge.innerHTML = `  ⭐ ${rating} (${votes}人评价)`; let imdbSpan = Array.from(infoDiv.querySelectorAll('span.pl')).find(el => el.innerText.includes('IMDb')); if (imdbSpan && imdbSpan.nextSibling) { imdbSpan.parentNode.insertBefore(badge, imdbSpan.nextSibling.nextSibling); } else { infoDiv.appendChild(badge); } } } catch (e) { console.warn("解析 IMDb 失败", e); } }); } // ========================================== // 第二模块:豆瓣读书 (Z-Library 搜索) // ========================================== const ZLIB_DOMAIN = "https://zlib.im"; function initBookScript() { GM_addStyle(` /* Z-lib 样式 */ .zlib-status-btn { display: inline-block; margin-top: 5px; color: #42bd56 !important; background: #f0f9f2; padding: 4px 8px; border-radius: 4px; font-size: 12px; text-decoration: none !important; } .zlib-status-btn:hover { background: #e2f4e5; } .zlib-dl-btn { margin-left: 8px; padding: 2px 10px; background: #e8ecef; color: #37a !important; border-radius: 2px; font-size: 12px; text-decoration: none !important; transition: all 0.2s; } .zlib-dl-btn:hover { background: #37a !important; color: #fff !important; } `); // 清理原有广告 let ad = document.getElementById('dale_book_subject_top_right'); if (ad && ad.parentNode) ad.parentNode.removeChild(ad); let wrapper = document.getElementById('wrapper'); if (!wrapper) return; let subTitleSpan = wrapper.querySelector('h1 span'); if (!subTitleSpan) return; // 提取检索关键字(优先 ISBN) let isbn = ''; let infoDiv = document.getElementById('info'); if (infoDiv) { let isbnMatch = infoDiv.innerText.match(/ISBN[::\s]*(\d[\d-]{9,}[\dXx])/); if (isbnMatch) isbn = isbnMatch[1].replace(/-/g, ''); } let rawTitle = subTitleSpan.innerHTML.trim(); let cleanTitle = rawTitle.replace(/[\((【\[].*?[\]】)\)]/g, '').trim() || rawTitle; let searchTerm = isbn || cleanTitle; let searchLabel = isbn ? `ISBN: ${isbn}` : cleanTitle; // 挂载侧边栏容器 let aside = document.getElementsByClassName('aside')[0]; if (aside) { let doc = new DOMParser().parseFromString(`

Z-Library 电子书 · · · · · ·

正在获取资源 (${searchLabel})...
`, "text/html"); aside.prepend(doc.body.firstChild); } let url = `${ZLIB_DOMAIN}/s/${encodeURIComponent(searchTerm)}`; loadZlibData(url, url); // url twice for reference logic } function loadZlibData(url, currentSearchUrl) { getDoc(url, function (doc) { let zlibContainer = document.getElementById('zlib'); if (!zlibContainer) return; zlibContainer.innerHTML = ''; let ele = doc.getElementById('searchResultBox'); if (!ele) { zlibContainer.innerHTML = `

Z-Library · · · · · ·

该书在 Z-Library 中未找到匹配资源。
↗ 前往 Z-lib 站内手动模糊搜索
`; return; } let items = ele.querySelectorAll('.resItemBox, .resItemBoxBooks, .book-item'); let totalCounterEl = doc.querySelector('.totalCounter, z-bookterms'); let totalCounter = '0'; if (totalCounterEl) { let match = (totalCounterEl.innerText || totalCounterEl.innerHTML || '').match(/\d+/); if (match) totalCounter = match[0]; } if (totalCounter === '0' && items.length > 0) totalCounter = items.length.toString(); zlibContainer.innerHTML = `

Z-Library (0) · · · · · · (全部 ${totalCounter})

`; let filterItemsNum = 0; // 解析 Z-Library 数据(兼容旧版 DOM 和 新版 Z-BookCard WebComponent) for (let i = 0; i < items.length && filterItemsNum < 5; i++) { try { let currentItem = items[i]; if (currentItem.classList.contains('booklist')) continue; let bookName = '', link = '', publisher = '', author = '', year = '', file = '', img = '', dlLink = ''; let zCard = currentItem.querySelector('z-bookcard'); if (zCard) { // 新版 DOM link = zCard.getAttribute('href') || ''; if (!link) continue; let titleSlot = zCard.querySelector('[slot="title"]'); bookName = titleSlot ? titleSlot.innerText.trim() : ''; let authorSlot = zCard.querySelector('[slot="author"]'); author = authorSlot ? authorSlot.innerText.trim() : ''; publisher = zCard.getAttribute('publisher') || ''; year = zCard.getAttribute('year') || ''; let ext = zCard.getAttribute('extension') || ''; let size = zCard.getAttribute('filesize') || ''; file = (ext && size) ? `${ext.toUpperCase()}, ${size}` : (ext || size); let dlAttr = zCard.getAttribute('download'); if (dlAttr) dlLink = ZLIB_DOMAIN + dlAttr; let imgEl = zCard.querySelector('img'); img = imgEl ? imgEl.outerHTML.replace('data-src', 'src') : ''; } else { // 旧版 DOM let titleLink = currentItem.querySelector('h3 a[itemprop="url"]') || currentItem.querySelector('a[style*="text-decoration: underline"]'); if (!titleLink) { let trs = currentItem.getElementsByTagName('td'); if (trs.length > 2) titleLink = trs[2].querySelector('a'); } if (!titleLink) continue; bookName = titleLink.innerText.trim(); link = titleLink.getAttribute("href"); let authorArr = []; currentItem.querySelectorAll('td a').forEach(aTag => { let text = aTag.innerText.trim(); if (aTag.getAttribute('title') === 'Publisher') publisher = text; else if (aTag.getAttribute('itemprop') === 'author') authorArr.push(text); }); author = authorArr.join(', '); let imgEl = currentItem.querySelector('img.cover') || currentItem.querySelector('img.itemCover'); img = imgEl ? imgEl.outerHTML.replace('data-src', 'src') : ''; let yearEl = currentItem.querySelector('.property_year .property_value'); if (yearEl) year = yearEl.innerText.trim(); let fileEl = currentItem.querySelector('.property__file .property_value'); if (fileEl) file = fileEl.innerText.trim(); let dlNode = currentItem.querySelector('a[href^="/dl/"]'); if (dlNode) dlLink = ZLIB_DOMAIN + dlNode.getAttribute('href'); } let infos = [publisher, author, file].filter(Boolean); let downloadBtnHtml = dlLink ? `⬇ 下载` : ''; let itemHtml = `
${img}
${bookName} ${year ? '(' + year + ')' : ''}
${infos.join('
')}

${downloadBtnHtml}
`; zlibContainer.insertAdjacentHTML('beforeend', itemHtml); filterItemsNum++; } catch (innerErr) { console.warn("解析跳过异常项", innerErr); } } let filterNumEl = document.getElementById('filterItemsNum'); if (filterNumEl) filterNumEl.innerHTML = filterItemsNum; if (filterItemsNum === 0) { zlibContainer.innerHTML = `

Z-Library (0) · · · · · · (去原站确认)

未提取到有效单本书籍(结果可能都是文章片段或书单聚合),请手动查询。
`; } else { let images = zlibContainer.getElementsByTagName('img'); for (let i = 0; i < images.length; i++) { images[i].setAttribute('width', '50px'); images[i].setAttribute('referrerpolicy', 'no-referrer'); } if (items.length > 5) { zlibContainer.insertAdjacentHTML('beforeend', `
查看全部 ${totalCounter} 条结果 >
`); } } }, function (err) { let zlibStatus = document.getElementById('zlib-status'); if (!zlibStatus) return; if (err === "captcha") { zlibStatus.innerHTML = `提示:Z-Library 开启了防机器人保护。
为正常显示电子书,请按照以下步骤证明您是真人:
↗ 1. 点击去 Z-lib 验证一下 ↻ 2. 验证后点我重新加载`; document.getElementById('zlib-btn-retry').onclick = () => { zlibStatus.innerHTML = "正在重新获取资源..."; loadZlibData(url, currentSearchUrl); }; document.getElementById('zlib-btn-gocheck').onclick = () => { let focusHandler = () => { let st = document.getElementById('zlib-status'); if (st && st.innerHTML.includes('拦截')) { st.innerHTML = "检测到您已返回,正在自动重试..."; loadZlibData(url, currentSearchUrl); } window.removeEventListener('focus', focusHandler); }; setTimeout(() => { window.addEventListener('focus', focusHandler); }, 2000); }; } else { zlibStatus.innerHTML = `网络失败。该镜像域名可能被阻断。
↗ 尝试手动打开新窗口搜索`; } }); } // ========================================== // 第三模块:豆瓣音乐 (聚合搜索跳转) // ========================================== function initMusicScript() { GM_addStyle(` .douban-music-search { margin-bottom: 20px; padding: 15px; background: #f4f8fb; border-radius: 4px; border: 1px solid #e1eaf2; } .douban-music-search h2 { color: #1f6b9c; margin: 0 0 12px 0; font-size: 15px; border-bottom: 1px dashed #d0dcea; padding-bottom: 6px; } .music-category { margin-bottom: 8px; font-weight: bold; color: #555; font-size: 13px; } .music-btn-group { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; } .music-btn { padding: 4px 10px; font-size: 12px; border-radius: 3px; text-decoration: none !important; transition: all 0.2s; color: #fff !important; } .music-btn:hover { opacity: 0.85; } .btn-mp3 { background-color: #ff6a00; } .btn-listen { background-color: #00b4ff; } .btn-app { background-color: #607d8b; } .btn-tg { background-color: #2ca5e0; } `); // 获取页面上的专辑标题和歌手名称 let wrapper = document.getElementById('wrapper'); if (!wrapper) return; let titleSpan = wrapper.querySelector('h1 span'); if (!titleSpan) return; let rawTitle = titleSpan.innerText.trim(); // 提取前缀作为主标题(过滤掉 'EP', 'Remastered' 等括号内容) let cleanTitle = rawTitle.replace(/[\((【\[].*?[\]】)\)]/g, '').trim(); // 尝试从 info 区域提取歌手名字 let artist = ''; let infoDiv = document.getElementById('info'); if (infoDiv) { let artistSpan = infoDiv.querySelector('span.pl a'); if (artistSpan) { artist = artistSpan.innerText.trim(); } else { let artistMatch = infoDiv.innerText.match(/(表演者|歌手)[\s::]*([^\n]*)/); if (artistMatch) artist = artistMatch[2].trim().split('/')[0].trim(); } } // 组成搜索关键词,如果是非常长的标题,通常只搜歌手+前几个字最精准 let keyword = cleanTitle; if (artist && !cleanTitle.includes(artist)) { keyword = artist + ' ' + cleanTitle; } let encodeKw = encodeURIComponent(keyword); let safeKeyword = keyword; // addEventListener中直接使用变量,无需转义 // 构建侧边栏面板 let aside = document.querySelector('.aside'); if (!aside) return; let panel = document.createElement('div'); panel.className = 'douban-music-search'; panel.innerHTML = `

🎵 音乐下载 · 在线试听

⚡ MP3 极速下载站
歌曲宝 (直连) 爱玩音乐 (需手搜)
🎧 无损源 / 试听引擎
铜钟 Tonzhon (直连)
⚙️ 全网聚合网页版 (需手搜)
HEMusic 引擎 GD音乐台 Ylan Music Minimal
🤖 Telegram 机器人 (需VPN/手搜)
@Music163bot @music_v1bot
* 💡 提示:点击带 (需手搜) 的按钮,将为您自动复制歌曲名!
`; aside.insertBefore(panel, aside.firstChild); // 为需要手动搜索的按钮绑定自动复制事件(必须在JS上下文中绑定,不能用内联onclick避免跨沙箱权限不足) let copyBtns = panel.querySelectorAll('.btn-copy-kw'); copyBtns.forEach(btn => { btn.addEventListener('click', function () { GM_setClipboard(safeKeyword, 'text'); }); }); // 增加内嵌极简播放器功能: 尝试通过网易云接口搜索并获取第一首歌曲的ID GM_xmlhttpRequest({ method: 'POST', url: 'https://music.163.com/api/search/get/web', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'https://music.163.com/' }, data: 's=' + encodeKw + '&type=1&offset=0&total=true&limit=1', onload: function (response) { try { let res = JSON.parse(response.responseText); if (res.code === 200 && res.result && res.result.songs && res.result.songs.length > 0) { let songId = res.result.songs[0].id; let playerContainer = document.getElementById('douban-music-player-container'); if (playerContainer) { playerContainer.style.display = 'block'; // 改用原生 audio 标签结合外链直达接口,并增加 onerror 容错防盗链及无版权提示 playerContainer.innerHTML = '' + '
⚠️ 该首歌曲受版权保护,暂无法提供直接试听。请使用下方按钮跳转收听。
'; } } } catch (e) { console.log('Douban Master: Failed to load netease music iframe', e); } } }); } // ========================================== // 主入口 // ========================================== if (location.host === 'movie.douban.com') { setTimeout(initMovieScript, 500); } else if (location.host === 'book.douban.com') { setTimeout(initBookScript, 500); } else if (location.host === 'music.douban.com') { setTimeout(initMusicScript, 500); } })();