// ==UserScript== // @name 豆瓣侠 // @version 1.0.2 // @description 云盘搜索 + 电影/音乐/图书简介生成 + 查看原图统一修复 + 音乐封面生成修复 // @author 全网搜:wpys.cc // @match https://movie.douban.com/subject/* // @match https://book.douban.com/subject/* // @match https://music.douban.com/subject/* // @grant GM_setClipboard // @grant GM_addStyle // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @connect api.wmdb.tv // @require https://code.jquery.com/jquery-3.6.0.min.js // ==/UserScript== (function() { 'use strict'; GM_addStyle(` .c-aside { margin-bottom: 30px; } .c-aside h2 { font-size: 14px; color: #333; margin-bottom: 10px; } .c-aside-body a { border-radius: 6px; color: #006400; display: inline-block; margin: 0 8px 8px 0; padding: 0 8px; text-align: center; width: 65px; background-color: #f5f5f5; text-decoration: none; font-size: 12px; line-height: 24px; font-weight: bold; } .c-aside-body a:hover { background-color: #e8e8e8; } #md-generator { margin: 20px 0; padding: 15px; background: #f9f9f9; border-radius: 6px; border-left: 4px solid #00a65a; } #md-generator-btn { background: #00a65a; color: white; border: none; padding: 8px 20px; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: bold; } #md-generator-btn:disabled { background: #ccc; cursor: wait; } #md-generator-btn:hover:not(:disabled) { background: #008d4c; } #md-preview { margin-top: 15px; padding: 15px; background: #f5f5f5; border-radius: 4px; border: 1px solid #ddd; display: none; } #md-preview pre { margin: 0; white-space: pre-wrap; font-family: 'Courier New', monospace; font-size: 13px; line-height: 1.6; background: #f5f5f5; padding: 10px; } .preview-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px dashed #ccc; } .preview-header-left { display: flex; align-items: center; } .preview-header-left span { font-weight: bold; margin-right: 15px; } #md-copy-btn { background: #337ab7; color: white; border: none; padding: 4px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; } #md-copy-btn:hover { background: #286090; } #md-copy-btn.copied { background: #5cb85c; } #loading-status { margin-left: 10px; font-size: 12px; color: #666; } .success { color: #5cb85c; } .error { color: #d9534f; } #doudanxia-settings { position: fixed; top: 80px; right: 20px; width: 380px; background: white; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 9999; padding: 20px; font-size: 13px; } .settings-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #00a65a; } .settings-header h3 { margin: 0; color: #00a65a; } .settings-section { margin-bottom: 20px; padding: 12px; background: #f9f9f9; border-radius: 6px; } .site-tag { display: inline-block; background: #e8e8e8; padding: 4px 12px; border-radius: 20px; font-size: 12px; margin: 0 5px 5px 0; } .close-btn { background: #f0f0f0; border: none; padding: 5px 20px; border-radius: 20px; cursor: pointer; font-size: 12px; } .close-btn:hover { background: #e0e0e0; } .view-original { display: inline-block; margin-left: 10px; font-size: 12px; color: #00a65a; text-decoration: none; } .view-original:hover { text-decoration: underline; } `); const PAN_SITES = [ { name: '网盘论坛', url: 'https://wpzy.cc/?q=' }, { name: '网盘影视', url: 'https://wpzy.me/?q=' }, { name: '网盘资源社', url: 'https://www.wpzy.cc/?q=' }, { name: '全网搜索', url: 'https://wpys.cc/s/' }, { name: '博哥影视', url: 'https://blog.wpys.cc/search/' } ]; const enableGenerator = GM_getValue('enable-generator', true); $(document).ready(function() { const pageType = location.host.split('.')[0]; const subjectId = location.href.match(/(\d{7,8})/); if (!subjectId) return; // 根据页面类型正确提取标题 let title = ''; if (pageType === 'music') { let titleElement = $('#wrapper > h1 > span'); if (titleElement.length) { title = titleElement.first().text().trim(); } else { title = $('#content h1').first().text().trim(); } } else if (pageType === 'book') { title = $('#wrapper > h1 > span').first().text().trim(); } else { title = $('#content h1 span').first().text().trim(); } let searchTitle = title; if (title.includes(' ')) { searchTitle = title.split(' ')[0]; } const searchKeyword = encodeURIComponent(searchTitle); $('#content div.aside').prepend(`
🎬 豆瓣侠 · 资源搜索 v1.0.2

云盘搜索· · · · · ·

${PAN_SITES.map(site => `${site.name}` ).join('')}
`); $("#db-global-nav > div > div.top-nav-info").append(`⚙️ 豆瓣侠设置`); $("#doudanxia-setting-btn").click(showSettingsPanel); // ===== 电影页面查看原图 ===== if (pageType === 'movie') { setTimeout(function() { if ($('#mainpic').length) { let posterImg = document.querySelector('#mainpic > a > img'); if (posterImg) { let postersUrl = posterImg.getAttribute('src'); let rawUrl = postersUrl.replace(/photo\/[sl](_ratio_poster|pic)\/public\/(p\d+).+$/, "photo/l/public/$2.jpg"); if (rawUrl === postersUrl) { rawUrl = postersUrl.split('?')[0]; } if ($('#mainpic p.gact').length === 0) { $("#mainpic").append("

"); } $('#mainpic p.gact').after(`查看原图`); } } }, 500); } // ===== 图书页面查看原图 ===== if (pageType === 'book') { setTimeout(function() { if ($('#mainpic').length) { let posterAnchor = document.querySelector('#mainpic > a.nbg'); if (posterAnchor) { let postersUrl = posterAnchor.getAttribute('href'); if ($('#mainpic p.gact').length === 0) { $("#mainpic").append("

"); } $('#mainpic p.gact').after(`查看原图`); } } }, 500); } // ===== 音乐页面查看原图(仿图书页面方式)===== if (pageType === 'music') { setTimeout(function() { if ($('#mainpic').length) { let posterAnchor = document.querySelector('#mainpic > a.nbg'); if (posterAnchor) { let postersUrl = posterAnchor.getAttribute('href'); // 处理原图链接 let rawUrl = postersUrl; if (postersUrl.includes('/m/')) { rawUrl = postersUrl.replace('/m/', '/l/'); } else if (postersUrl.includes('/small/')) { rawUrl = postersUrl.replace('/small/', '/large/'); } else if (postersUrl.includes('/icon/')) { rawUrl = postersUrl.replace('/icon/', '/large/'); } // 如果不存在 p.gact,就创建一个 if ($('#mainpic p.gact').length === 0) { $("#mainpic").append("

"); } // 在 p.gact 后面添加查看原图链接 $('#mainpic p.gact').after(`查看原图`); } } }, 500); // 再加一个延迟执行,确保豆瓣的DOM完全加载 setTimeout(function() { if ($('#mainpic').length && $('#mainpic p.gact').length && !$('#mainpic .view-original').length) { let posterAnchor = document.querySelector('#mainpic > a.nbg') || document.querySelector('#mainpic a'); if (posterAnchor) { let postersUrl = posterAnchor.getAttribute('href'); let rawUrl = postersUrl.replace('/m/', '/l/'); $('#mainpic p.gact').after(`查看原图`); } } }, 1500); } // 电影页面:IMDb链接加回去 if (pageType === 'movie') { let imdb_anchor = $('#info span.pl:contains("IMDb")'); if (imdb_anchor.length > 0) { let imdb_text = imdb_anchor[0].nextSibling?.nodeValue; if (imdb_text) { let imdb_id = imdb_text.trim(); let imdb_link = `https://www.imdb.com/title/${imdb_id}/`; $(imdb_anchor[0].nextSibling).replaceWith(` ${imdb_id}`); } } } if (enableGenerator) { if (pageType === 'movie') { insertMovieGenerator(); } else if (pageType === 'book') { insertBookGenerator(); } else if (pageType === 'music') { insertMusicGenerator(); } } }); function showSettingsPanel() { if ($('#doudanxia-settings').length) { $('#doudanxia-settings').remove(); return; } const sitesHtml = PAN_SITES.map(site => `${site.name}` ).join(''); const currentEnable = GM_getValue('enable-generator', true); $('body').append(`

🎬 豆瓣侠设置

v1.0.2
关闭后只保留云盘搜索

📁 云盘搜索 (5个站点)

${sitesHtml}
点击链接自动搜索当前资源
`); $('#close-settings').click(() => $('#doudanxia-settings').remove()); $('#enable-generator').change(function() { GM_setValue('enable-generator', $(this).is(':checked')); if (confirm('设置已保存,是否刷新页面?')) location.reload(); }); $(document).mouseup(function(e) { const container = $('#doudanxia-settings'); if (!container.is(e.target) && container.has(e.target).length === 0) { container.remove(); } }); } // ===== 电影生成器 ===== function insertMovieGenerator() { $('#info').after(`
`); $('#md-generator-btn').click(async function() { if ($('#md-preview').is(':visible')) { $('#md-preview').slideUp(300); $(this).text('📋 生成电影简介(带海报)'); } else { const btn = $(this); const status = $('#loading-status'); btn.prop('disabled', true).text('⏳ 获取数据...'); status.removeClass('success error').text('正在从WMDB获取数据...'); try { await generateMovieMarkdown(); $('#md-preview').slideDown(300); btn.text('📋 收缩预览'); status.addClass('success').text('✅ 生成成功'); } catch(e) { status.addClass('error').text('❌ 生成失败: ' + e.message); btn.text('📋 重试'); } finally { btn.prop('disabled', false); } } }); $('#md-copy-btn').click(copyToClipboard); } async function generateMovieMarkdown() { const doubanId = window.location.href.match(/\/(\d{7,8})\//)?.[1]; if (!doubanId) throw new Error('未找到豆瓣ID'); const apiUrl = `https://api.wmdb.tv/movie/api?id=${doubanId}`; const movieData = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: apiUrl, onload: function(res) { if (res.status === 200) { try { const data = JSON.parse(res.responseText); resolve(data); } catch (e) { reject(new Error('解析返回数据失败')); } } else { reject(new Error(`API请求失败: ${res.status}`)); } }, onerror: function() { reject(new Error('网络错误')); } }); }); if (!movieData || !movieData.data) throw new Error('API返回数据为空'); const cnData = movieData.data.find(d => d.lang === 'Cn') || movieData.data[0]; let poster = ''; if (cnData?.poster) { // 保持宽高比,宽度强制1080p,输出WebP格式 poster = `https://images.weserv.nl/?url=${encodeURIComponent(cnData.poster)}&w=1080&fit=inside&output=webp`; } let md = ''; if (poster) md += `![海报](${poster})\n\n`; md += `◎片  名 ${cnData?.name || movieData.originalName || ''}\n`; if (movieData.year) md += `◎年  代 ${movieData.year}\n`; if (cnData?.country) md += `◎产  地 ${cnData.country}\n`; if (cnData?.genre) md += `◎类  别 ${cnData.genre.replace(/\//g, ' / ')}\n`; if (cnData?.language) md += `◎语  言 ${cnData.language}\n`; if (movieData.dateReleased) md += `◎上映日期 ${movieData.dateReleased}\n`; if (movieData.imdbId) md += `◎IMDb链接 \n`; if (movieData.doubanRating) { md += `◎豆瓣评分 ${movieData.doubanRating}/10 from ${movieData.doubanVotes || 0} users\n`; } md += `◎豆瓣链接 https://movie.douban.com/subject/${doubanId}/\n`; if (movieData.duration) { const minutes = Math.floor(movieData.duration / 60); md += `◎片  长 ${minutes}分钟\n`; } if (movieData.director?.[0]?.data) { const directors = movieData.director[0].data .filter(d => d.lang === 'Cn') .map(d => d.name) .join(' / '); if (directors) md += `◎导  演 ${directors}\n`; } if (movieData.writer?.[0]?.data) { const writers = movieData.writer[0].data .filter(w => w.lang === 'Cn') .map(w => w.name) .join(' / '); if (writers) md += `◎编  剧 ${writers}\n`; } if (movieData.actor?.length) { const actors = movieData.actor .slice(0, 10) .map(a => a.data?.find(d => d.lang === 'Cn')?.name) .filter(Boolean) .join(' / '); if (actors) { md += `◎主  演 ${actors}\n`; } } if (cnData?.description) { md += `\n◎简  介\n\n`; md += `  ${cnData.description.replace(/\n/g, '\n  ')}\n`; } $('#md-content').text(md); } // ===== 图书生成器(带清除浮动)===== function insertBookGenerator() { $('#info').after(`
`); $('#md-generator-btn').click(function() { if ($('#md-preview').is(':visible')) { $('#md-preview').slideUp(300); $(this).text('📋 生成图书简介(带封面)'); } else { generateBookMarkdown(); $('#md-preview').slideDown(300); $(this).text('📋 收缩预览'); } }); $('#md-copy-btn').click(copyToClipboard); } function generateBookMarkdown() { const data = {}; data.title = $('#wrapper > h1 > span').first().text().trim(); // 封面:用豆瓣的图,走代理 let coverImg = document.querySelector('#mainpic > a > img'); if (coverImg) { let coverUrl = coverImg.getAttribute('src').split('?')[0]; // 保持宽高比,宽度强制1080p,输出WebP格式 data.cover = `https://images.weserv.nl/?url=${encodeURIComponent(coverUrl)}&w=1080&fit=inside&output=webp`; } const infoText = $('#info').text(); // 作者 data.author = $('#info a[href*="search?cat=1003"]').map(function() { return $(this).text().trim(); }).get().join(' / '); const publisherMatch = infoText.match(/出版社:\s*([^\n]+)/); data.publisher = publisherMatch ? publisherMatch[1].trim() : ''; const seriesMatch = infoText.match(/丛书:\s*([^\n]+)/); data.series = seriesMatch ? seriesMatch[1].trim() : ''; const isbnMatch = infoText.match(/ISBN:\s*([0-9X-]+)/); data.isbn = isbnMatch ? isbnMatch[1].trim() : ''; data.rating = $('strong.ll.rating_num').text().trim(); data.votes = $('a.rating_people span').text().trim(); // 简介(过滤掉脚本和样式) let introElement = $('#link-report .all').length ? $('#link-report .all') : $('#link-report'); let introRaw = introElement.clone() .find('script, style, .btn-report, .link-report') .remove() .end() .html() || ''; let introText = introRaw.replace(/<[^>]+>/g, ' ') .replace(/\s+/g, ' ') .replace(/ /g, ' ') .trim(); const doubanId = window.location.href.match(/\d{7,8}/)?.[0] || ''; let md = ''; if (data.cover) md += `![封面](${data.cover})\n\n`; md += `◎书  名 ${data.title}\n`; if (data.author) md += `◎作  者 ${data.author}\n`; if (data.publisher) md += `◎出版社  ${data.publisher}\n`; if (data.series) md += `◎丛  书 ${data.series}\n`; if (data.isbn) md += `◎ISBN   ${data.isbn}\n`; if (data.rating) md += `◎豆瓣评分 ${data.rating}/10 from ${data.votes} users\n`; md += `◎豆瓣链接 https://book.douban.com/subject/${doubanId}/\n\n`; if (introText) md += `◎简  介\n\n  ${introText}\n`; $('#md-content').text(md); } // ===== 音乐生成器(带清除浮动,使用和图书页面完全一样的封面生成方式)===== function insertMusicGenerator() { $('#info').after(`
`); $('#md-generator-btn').click(function() { if ($('#md-preview').is(':visible')) { $('#md-preview').slideUp(300); $(this).text('📋 生成音乐简介(带封面)'); } else { generateMusicMarkdown(); $('#md-preview').slideDown(300); $(this).text('📋 收缩预览'); } }); $('#md-copy-btn').click(copyToClipboard); } function generateMusicMarkdown() { const data = {}; // 标题 let titleElement = $('#wrapper > h1 > span'); if (titleElement.length) { data.title = titleElement.first().text().trim(); } else { data.title = $('#content h1').first().text().trim(); } // ===== 封面获取:使用和图书页面完全一样的代码 ===== let coverImg = document.querySelector('#mainpic > a > img'); if (!coverImg) { coverImg = document.querySelector('#mainpic img'); } if (coverImg) { let coverUrl = coverImg.getAttribute('src'); if (coverUrl) { // 去掉URL参数 coverUrl = coverUrl.split('?')[0]; // 处理缩略图链接,获取大图 if (coverUrl.includes('/m/')) { coverUrl = coverUrl.replace('/m/', '/l/'); } else if (coverUrl.includes('/small/')) { coverUrl = coverUrl.replace('/small/', '/large/'); } // 保持宽高比,宽度强制1080p,输出WebP格式 data.cover = `https://images.weserv.nl/?url=${encodeURIComponent(coverUrl)}&w=1080&fit=inside&output=webp`; } } // 表演者 data.artist = $('#info a[href*="search?cat=1003"]').first().text().trim(); const infoText = $('#info').text(); const typeMatch = infoText.match(/专辑类型:\s*([^\n]+)/); data.type = typeMatch ? typeMatch[1].trim() : ''; const mediaMatch = infoText.match(/介质:\s*([^\n]+)/); data.media = mediaMatch ? mediaMatch[1].trim() : ''; const dateMatch = infoText.match(/发行时间:\s*([^\n]+)/); data.date = dateMatch ? dateMatch[1].trim() : ''; const publisherMatch = infoText.match(/出版者:\s*([^\n]+)/); data.publisher = publisherMatch ? publisherMatch[1].trim() : ''; data.rating = $('strong.ll.rating_num').text().trim(); data.votes = $('a.rating_people span').text().trim(); // 曲目 data.tracks = []; $('.track-list li, #content .song-item').each(function() { const track = $(this).text().trim(); if (track) data.tracks.push(track); }); // 简介(过滤掉脚本和样式) let introElement = $('#link-report .all').length ? $('#link-report .all') : $('#link-report'); let introRaw = introElement.clone() .find('script, style, .btn-report, .link-report') .remove() .end() .html() || ''; let introText = introRaw.replace(/<[^>]+>/g, ' ') .replace(/\s+/g, ' ') .replace(/ /g, ' ') .trim(); const doubanId = window.location.href.match(/\d{7,8}/)?.[0] || ''; let md = ''; // ===== 添加封面(和图书页面完全一样)===== if (data.cover) { md += `![封面](${data.cover})\n\n`; } md += `◎专辑名称 ${data.title}\n`; if (data.artist) md += `◎表演者  ${data.artist}\n`; if (data.type) md += `◎专辑类型 ${data.type}\n`; if (data.media) md += `◎介质   ${data.media}\n`; if (data.date) md += `◎发行时间 ${data.date}\n`; if (data.publisher) md += `◎出版者  ${data.publisher}\n`; if (data.rating) md += `◎豆瓣评分 ${data.rating}/10 from ${data.votes} users\n`; md += `◎豆瓣链接 https://music.douban.com/subject/${doubanId}/\n\n`; if (data.tracks.length) { md += `◎曲  目\n\n`; data.tracks.forEach((track, i) => { md += `  ${i+1}. ${track}\n`; }); md += `\n`; } if (introText) { md += `◎简  介\n\n  ${introText}\n`; } $('#md-content').text(md); } function copyToClipboard() { const text = $('#md-content').text(); if (!text) return; const textWithBreaks = text + '\n\n\n'; GM_setClipboard(textWithBreaks); const btn = $('#md-copy-btn'); btn.addClass('copied').text('✅ 复制成功'); setTimeout(() => { btn.removeClass('copied').text('复制到剪贴板'); }, 2000); } })();