// ==UserScript== // @name 豆瓣资源下载观看大师:(增加H243影视资源,方便通过豆瓣搜索后直接观看)豆瓣电影|音乐|图书下载 // @description 【基本就是原作者代码的基础上添加了H243影视资源搜索】聚合数百家资源网站,通过右侧边栏1秒告诉你哪些网站能下载豆瓣页面上的电影|电视剧|纪录片|综艺|动画|音乐|图书等,有资源的网站显示绿色,没资源的网站显示黄色,就这么直观!所有豆瓣条目均提供在线播放|阅读、字幕|歌词下载及PT|NZB|BT|磁力|百度盘|115网盘等下载链接,加入官网打死也不出的豆列搜索功能,此外还能给豆瓣条目额外添加IMDB评分|IMDB TOP 250|Metascore评分|烂番茄评分|AniDB评分|Bgm评分|MAL|亚马逊评分等更多评分形式。也可以直接访问观看:https://www.h243.top // @author 白鸽男孩 // @contributor Rhilip // @connect * // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // @grant GM_deleteValue // @grant GM_registerMenuCommand // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js // @require https://greasyfork.org/scripts/368137-encodeToGb2312/code/encodeToGb2312.js?version=601683 // @include https://movie.douban.com/* // @include https://music.douban.com/* // @include https://book.douban.com/* // @include https://bangumi.moe/search/title* // @include https://desitorrents.tv/* // @include https://v.dsb.ink/* // @include http://www.x5v.net/* // @license Zlib/Libpng License // @version 8.3.2 // @icon https://img3.doubanio.com/favicon.ico // @run-at document-end // @namespace doveboy_js // @downloadURL none // ==/UserScript== /* global $, jQuery, encodeToGb2312 */ // This Userscirpt can't run under Greasemonkey 4.x platform if (typeof GM_xmlhttpRequest === "undefined") { alert("不支持Greasemonkey 4.x,请换用暴力猴或Tampermonkey"); return; } // 不属于豆瓣的页面 if (!/douban.com/.test(location.host)) { function AutoSearch(host, zInputSelector, btnSelector, dict) { if (location.host === host) { let match = location.href.match(/#search_(.+)/); // 从url的hash部分获取搜索关键词 if (match) { history.pushState("", document.title, window.location.pathname + window.location.search); // 清空hash window.addEventListener("load", function () { // 等待页面完全加载完成 let zInput = $(zInputSelector); zInput.val(decodeURIComponent(match[1])); // 填入搜索值 dict = $.extend({}, dict); if (dict.ang) { // 补加Event,防止Angular绑定失效。 From: https://stackoverflow.com/questions/34360739/automate-form-submission-on-an-angularjs-website-using-tampermonkey let changeEvent = document.createEvent("HTMLEvents"); changeEvent.initEvent("change", true, true); zInput[0].dispatchEvent(changeEvent); } if (dict.notarget) { // 取消form的提交跳转 $(btnSelector).parents("form").attr("target", "_self"); } $(btnSelector).click(); // 模拟点击 }); } } } AutoSearch("bangumi.moe", '#filter-tag-list div.torrent-title-search > md-input-group > input', '#filter-tag-list > div.torrent-search > div:nth-child(3) > button:nth-child(4)', { ang: true }); AutoSearch("v.dsb.ink", '.search__input', '.icon-search', {}); AutoSearch("www.x5v.net", '#searchText', '#btnSearch', {}); AutoSearch("desitorrents.tv", 'input.search_string_input', 'input.search_string_input+img', {}); return; // 终止脚本运行,防止豆瓣的css以及js片段等污染页面 } // 阻止其他豆瓣同类脚本加载 var seBwhA = document.createElement("a"); seBwhA.id = "seBwhA"; document.getElementsByTagName("html")[0].appendChild(seBwhA); // 注入脚本相关的CSS,包括:隐藏、调整豆瓣原先的元素,脚本页面样式 GM_addStyle(` .c-aside{margin-bottom:30px}.c-aside-body a{border-radius:6px;color:#37a;display:inline-block;letter-spacing:normal;margin:0 8px 8px 0;padding:0 8px;text-align:center;width:65px}.c-aside-body a:link,.c-aside-body a:visited{background-color:#f5f5f5;color:#37a}.c-aside-body a:active,.c-aside-body a:hover{background-color:#e8e8e8;color:#37a}.c-aside-body a.available{background-color:#5ccccc;color:#006363}.c-aside-body a.available:active,.c-aside-body a.available:hover{background-color:#3cc}.c-aside-body a.sites_r0{text-decoration:line-through} #c_dialog li{margin:10px}#c_dialog{text-align:center} #interest_sectl .rating_imdb{border-top:1px solid #eaeaea;border-bottom:1px solid #eaeaea;padding-bottom:0}#interest_sectl .rating_wrap{padding-top:15px}#interest_sectl .rating_more{border-bottom:1px solid #eaeaea;color:#9b9b9b;margin:0;padding:15px 0;position:relative}#interest_sectl .rating_more a{left:80px;position:absolute}#interest_sectl .rating_more .titleOverviewSprite{background:url(https://coding.net/u/Changhw/p/MyDoubanMovieHelper/git/raw/master/title_overview_sprite.png) no-repeat;display:inline-block;vertical-align:middle}#interest_sectl .rating_more .popularityImageUp{background-position:-14px -478px;height:8px;width:8px}#interest_sectl .rating_more .popularityImageDown{background-position:-34px -478px;height:8px;width:8px}#interest_sectl .rating_more .popularityUpOrFlat{color:#83c40b}#interest_sectl .rating_more .popularityDown{color:#930e02} .more{display:block;height:34px;line-height:34px;text-align:center;font-size:14px;background:#f7f7f7} div#drdm_setting input[type=checkbox]{display:none}div#drdm_setting input[type=checkbox]+label{display:inline-block;width:40px;height:20px;position:relative;transition:.3s;margin:0 20px;box-sizing:border-box;background:#ddd;border-radius:20px;box-shadow:1px 1px 3px #aaa}div#drdm_setting input[type=checkbox]+label:after,div#drdm_setting input[type=checkbox]+label:before{content:'';display:block;position:absolute;left:0;top:0;width:20px;height:20px;transition:.3s;cursor:pointer}div#drdm_setting input[type=checkbox]+label:after{background:#fff;border-radius:50%;box-shadow:1px 1px 3px #aaa}div#drdm_setting input[type=checkbox]:checked+label{background:#aedcae}div#drdm_setting input[type=checkbox]:checked+label:after{background:#5cb85c;left:calc(100% - 20px)} .top250{background:url(https://s.doubanio.com/f/movie/f8a7b5e23d00edee6b42c6424989ce6683aa2fff/pics/movie/top250_bg.png) no-repeat;width:150px;margin-right:5px;font:12px Helvetica,Arial,sans-serif;margin:5px 0;color:#744900}.top250 span{display:inline-block;text-align:center;height:18px;line-height:18px}.top250 a,.top250 a:active,.top250 a:hover,.top250 a:link,.top250 a:visited{color:#744900;text-decoration:none;background:0}.top250-no{width:34%}.top250-link{width:66%} .drdm-dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.drdm-dl-horizontal dd{margin-left:180px} `); if (GM_getValue('enable_extra_stylesheet', true)) { GM_addStyle('#dale_movie_chart_top_right,#dale_movie_home_bottom_right,#dale_movie_home_bottom_right_down,#dale_movie_home_download_bottom,#dale_movie_home_inner_bottom,#dale_movie_home_side_top,#dale_movie_home_top_right,#dale_movie_subject_bottom_super_banner,#dale_movie_subject_download_middle,#dale_movie_subject_inner_middle,#dale_movie_subject_middle_right,#dale_movie_subject_top_midle,#dale_movie_subject_top_right,#dale_movie_tags_top_right,#dale_movie_towhome_explore_right,#dale_review_best_top_right,#footer,#movie_home_left_bottom,.extra,.mobile-app-entrance.block5.app-movie,.qrcode-app,.top-nav-doubanapp,div.gray_ad,div.ticket{display:none}'); } // -- 定义基础方法 -- // 对使用GM_xmlhttpRequest返回的html文本进行处理并返回DOM树 function page_parser(responseText) { // 替换一些信息防止图片和页面脚本的加载,同时可能加快页面解析速度 // responseText = responseText.replace(/s+src=/ig, ' data-src='); // 图片,部分外源脚本 // responseText = responseText.replace(/]*?>[\S\s]*?<\/script>/ig, ''); //页面脚本 return (new DOMParser()).parseFromString(responseText, 'text/html'); } function getDoc(url, meta, callback) { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (responseDetail) { if (responseDetail.status === 200) { let doc = page_parser(responseDetail.responseText); callback(doc, responseDetail, meta); } } }); } function getJSON(url, callback) { GM_xmlhttpRequest({ method: 'GET', url: url, headers: { 'Accept': 'application/json' }, onload: function (response) { if (response.status >= 200 && response.status < 400) { callback(JSON.parse(response.responseText), url); } else { callback(false, url); } } }); } // 缓存相关方法 function CacheStorage(name, expire = null) { let now = Date.now(); let cache_name = "drdm_cache_" + (name ? name : 'default'); if (localStorage[cache_name + "_exp"]) { if (now > localStorage[cache_name + "_exp"]) { localStorage.removeItem(cache_name); } } let cache = localStorage[cache_name] ? JSON.parse(localStorage[cache_name]) : {}; localStorage.setItem(cache_name + "_exp", now + expire); return { flush: function () { localStorage.setItem(cache_name, JSON.stringify(cache)); }, add: function (name, value) { cache[name] = value; this.flush(); }, del: function (name) { if (name) { delete cache[name]; this.flush; } else { localStorage.removeItem(cache_name); } }, get: function (name, def = null) { if (name) { return cache[name] ? cache[name] : def; } else { return cache; } } } } function clearExpiredCacheValue(force) { let StorageKey = []; for (let i = 0, len = localStorage.length; i < len; ++i) { // 先从里面取出所有的key StorageKey.push(localStorage.key(i)); } let CacheKey = StorageKey.filter(function (x) { return x && x.match(/(drdm_cache_.+)_exp/); }); // 再从中提取出本脚本缓存的键值 for (let i = 0,len = CacheKey.length ; i < len ; ++i) { let key_name = CacheKey[i]; let exp_at = localStorage.getItem(key_name); if (force || exp_at < Date.now()) { localStorage.removeItem(key_name); localStorage.removeItem(key_name.slice(0,-4)); // 移除 _exp 后缀 } } } let _version = GM_getValue("version", "轻量版"); let delete_site_prefix = "delete_site_"; if (typeof GM_registerMenuCommand !== "undefined") { function changeVersionConfirm() { if (confirm(`你当前版本是 ${_version},是否进行切换?`)) { GM_setValue("version", _version === "完整版" ? "轻量版" : "完整版"); } } GM_registerMenuCommand("脚本功能切换", changeVersionConfirm); function changeTagBColor() { let now_bcolor_list = [GM_getValue("tag_bcolor_exist", "#e3f1ed"), GM_getValue("tag_bcolor_not_exist", "#f4eac2"), GM_getValue("tag_bcolor_need_login", ""), GM_getValue("tag_bcolor_error", "")]; let name = prompt("请依次输入代表'资源存在','资源不存在','站点需要登陆','站点解析错误'颜色的Hex值,并用英文逗号分割。当前值为:", `${now_bcolor_list.join(',')}`); if (name != null && name !== "") { try { let bcolor_list = name.split(","); GM_setValue("tag_bcolor_exist", bcolor_list[0] || "#e3f1ed"); GM_setValue("tag_bcolor_not_exist", bcolor_list[1] || "#f4eac2"); GM_setValue("tag_bcolor_need_login", bcolor_list[2] || ""); GM_setValue("tag_bcolor_error", bcolor_list[3] || ""); } catch (e) { alert("解析输入出错"); } } } GM_registerMenuCommand("更改标签背景色", changeTagBColor); function changeTagFColor() { let now_fcolor_list = [GM_getValue("tag_fcolor_exist", "#3377aa"), GM_getValue("tag_fcolor_not_exist", "#3377aa"), GM_getValue("tag_fcolor_need_login", "#3377aa"), GM_getValue("tag_fcolor_error", "#3377aa")]; let name = prompt("请依次输入代表'资源存在','资源不存在','站点需要登陆','站点解析错误'颜色的Hex值,并用英文逗号分割。当前值为:", `${now_fcolor_list.join(',')}`); if (name != null && name !== "") { try { let fcolor_list = name.split(","); GM_setValue("tag_fcolor_exist", fcolor_list[0] || "#3377aa"); GM_setValue("tag_fcolor_not_exist", fcolor_list[1] || "#3377aa"); GM_setValue("tag_fcolor_need_login", fcolor_list[2] || "#3377aa"); GM_setValue("tag_fcolor_error", fcolor_list[3] || "#3377aa"); } catch (e) { alert("解析输入出错"); } } } GM_registerMenuCommand("更改标签文字色", changeTagFColor); function forceCacheClear() { if (confirm("清空所有缓存信息(包括资源存在情况、登陆情况等)")) { clearExpiredCacheValue(true); } } GM_registerMenuCommand("清空脚本缓存", forceCacheClear); } let fetch_anchor = function (anchor) { return anchor[0].nextSibling.nodeValue.trim(); }; function starBlock(source, source_link, _rating, _vote, max = 10) { let starValue = parseFloat(_rating) / 2; starValue = starValue % 1 > 0.5 ? Math.floor(starValue) + 0.5 : Math.floor(starValue); starValue *= (100 / max); return `
${parseFloat(_rating).toFixed(1)}
` } function parseLdJson (raw) { return JSON.parse(raw.replace(/\n/ig,'')); } $(document).ready(function () { let douban_link, douban_id; douban_link = 'https://' + location.href.match(/douban.com\/subject\/\d+\//); //豆瓣链接 douban_id = location.href.match(/(\d{7,8})/g); let site_map = []; /** label对象键值说明: * name: String 站点名称,请注意该站点名称在不同的site_map中也应该唯一,以免脚本后续判断出错 * method: String 搜索请求方式,默认值为 "GET" * link: String 构造好的请求页面链接,作为label的href属性填入,用户应该能直接点开这个页面。 * ajax: String 如果站点使用ajax的形式加载页面,则需要传入该值作为实际请求的链接,即优先级比link更高。 * type: String 返回结果类型,脚本默认按html页面解析;只有当传入值为"json"时,脚本按JSON格式解析 * selector: String 搜索成功判断结果,默认值为 "table.torrents:last > tbody > tr:gt(0)" (适用于国内多数NexusPHP构架的站点) * 如果type为"page"(默认)时,为一个(jQuery)CSS选择器, * 如果type为"json"或"jsonp"时,为一个具体的判断式。 * selector_need_login 搜索需要登录的选择器,仅在type为默认时有用,其余用法同Selector一致。 * data: String 作为请求的主体发送的内容,默认为空即可 * headers: Object 修改默认请求头,(防止某些站点有referrer等请求头检查 * rewrite_href: Boolean 如果站点最终搜索显示的页面与实际使用搜索页面(特别是使用post进行交互的站点)不一致, * 设置为true能让脚本存储最终url,并改写label使用的href属性 * csrf: Object 一个类似这样的字典 { name: "_csrf", update: "link"} * 其中key为站点csrf防护的名称,update为需要更新的字段(一般为link或data) * * 注意: 1. 如果某键有默认值,则传入值均会覆盖默认值 * 2. 关于请求方法请参考:https://github.com/scriptish/scriptish/wiki/GM_xmlhttpRequest * */ if (douban_id) { clearExpiredCacheValue(false); // 清理缓存 let cache = CacheStorage(douban_id, 86400 * 7 * 1e3); let need_login_cache = CacheStorage("need_login", 86400 * 1e3); $("#content div.aside").prepend(`
`); $("#drdm_req_status_hide").click(function () { $("#drdm_req_status").hide();}); $("#drdm_hide_fail").click(function () { $("#drdm_sites a[title!=\"资源存在\"]").hide(); $('#drdm_sites > div.c-aside.name-offline').each(function () {let that = $(this); if (that.find('> div > ul > a:visible').length == 0) {that.hide()}}); }); $("#drdm_show_all").click(function () { $("#drdm_sites a:hidden").show(); $('#drdm_sites > div.c-aside.name-offline').show(); }); let update_status_interval; function update_req_status() { let asking_length = $("#drdm_sites a[title=\"正在请求信息中\"]").length; $("#drdm_req_success").text($("#drdm_sites a[title=\"资源存在\"]").length); $("#drdm_req_asking").text(asking_length); $("#drdm_req_noexist").text($("#drdm_sites a[title=\"资源不存在\"]").length); $("#drdm_req_fail").text($("#drdm_sites a[title=\"站点需要登陆\"]").length + $("#drdm_sites a[title=\"遇到问题\"]").length); if (asking_length === 0) { clearInterval(update_status_interval); // 当所有请求完成后清除定时器 if (GM_getValue('enalbe_adv_auto_tip_hide', false)) { $("#drdm_req_status_hide").click(); } } } function _encodeToGb2312(str, opt) { let ret = ""; try { ret = encodeToGb2312(str, opt); } catch (e) { ret = Math.random() * 1e6; $("#drdm_dep_notice").show(); } return ret; } if (location.host === "movie.douban.com") { // 查看原图 if ($('#mainpic p.gact').length === 0) { // 在未登录的情况下添加空白元素以方便查看原图交互按钮的定位 $("#mainpic").append("

"); } let posterAnchor = document.querySelector('#mainpic > a > img'); let postersUrl, rawUrl; if (posterAnchor) { postersUrl = posterAnchor.getAttribute("src"); rawUrl = postersUrl.replace(/photo\/[sl](_ratio_poster|pic)\/public\/(p\d+).+$/, "photo/raw/public/$2.jpg"); $('#mainpic p.gact').after(`查看原图`); } // 调整底下剧情简介的位置 let interest_sectl_selector = $('#interest_sectl'); interest_sectl_selector.after($('div.grid-16-8 div.related-info')); interest_sectl_selector.attr('style', 'float:right'); $('div.related-info').attr('style', 'width:480px;float:left'); // Movieinfo信息生成相关 let this_title, trans_title, aka; let year, region, genre, language, playdate; let imdb_link, imdb_id, imdb_average_rating, imdb_votes, imdb_rating; let douban_average_rating, douban_votes, douban_rating; let episodes, duration; let director, writer, cast; let tags, introduction, awards; // 获得