您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
豆瓣随机漫步者脚本,为电影、读书、音乐的wish、do、collect添加了随机按钮和高亮显示,节省决策资源,拯救选择困难症!目前仅适配栅格视图,列表视图待适配。
// ==UserScript== // @name 豆瓣随机漫步者 - 手气不错 - 拯救选择困难症! // @version 0.1.5.4 // @namespace Black Rabbit // @author Black Rabbit // @description 豆瓣随机漫步者脚本,为电影、读书、音乐的wish、do、collect添加了随机按钮和高亮显示,节省决策资源,拯救选择困难症!目前仅适配栅格视图,列表视图待适配。 // @match http*://book.douban.com/* // @match http*://movie.douban.com/* // @match http*://music.douban.com/* // @match http*://*.douban.com/mine* // @match http*://*.douban.com/people/*/wish* // @match http*://*.douban.com/people/*/do* // @match http*://*.douban.com/people/*/collect* // @match http*://search.douban.com/book/* // @match http*://search.douban.com/movie/* // @match http*://search.douban.com/music/* // @icon https://img1.doubanio.com/favicon.ico // @original_icon https://www.google.com/s2/favicons?sz=64&domain=douban.com // @supportURL https://greasyfork.org/scripts/476110 // @grant GM_xmlhttpRequest // @grant GM_log // ==/UserScript== // Domain and Type Process var domain = window.location.hostname; var url = window.location.href; var hlcolor; //var imdbid = 2543698; var type; var cat; // Type Decide function judgetype(){ var bookkw = ["book.douban", "search.douban.com/book"]; var moviekw = ["movie.douban", "search.douban.com/movie"]; var musickw = ["music.douban", "search.douban.com/music"]; if (bookkw.some(function (substring) { return url.includes(substring); })) { return "book" } else if (moviekw.some(function (substring) { // includes keyword then run return url.includes(substring); })) { return "movie" } else if (musickw.some(function (substring) { // includes keyword then run return url.includes(substring); })) { return "music" } } // Handle type, cat, highlight color if (judgetype()=="book"){ type = "book" ; cat = "1001" ; hlcolor = "rgb(40,153,160)"; }//rgb(38,143,149) rgb(234,161,100) else if (judgetype()=="movie") { type = "movie" ; cat = "1002" ; hlcolor = "rgb(0,144,217)"; if(url.includes("typerank?type_name")){moviepick();}} //rgb(40,156,229) else if (judgetype()=="music"){ type = "music" ; cat = "1003" ; hlcolor = "rgb(249,92,68)";} //rgb(250,128,0) // Try get newest imdbid // (function() { // var imdburl = "https://www.imdb.com/pressroom/stats/"; // GM_xmlhttpRequest({ // method: "GET", // url: imdburl, // onload: function(response) { // // Parse the response text as HTML // var parser = new DOMParser(); // var doc = parser.parseFromString(response.responseText, "text/html"); // // Find the <li> element that contains the text "Titles w/ Primary Image:" // var li = doc.querySelector("li:contains('Titles w/ Primary Image:')"); // // Get the text content of the <li> element // var text = li.textContent; // // Extract the number from the text and remove the commas // var number = text.replace("Titles w/ Primary Image: ", "").replace(/,/g, ""); // // Convert the number to a numeric value // number = Number(number); // // Store the number in a variable for later use // imdbid = number; // } // }); // //console.log("imdbid = " + imdbid); // GM_log("imdbid = " + imdbid); // //console.log("imdbid = 111"); // GM_log("imdbid = 111"); // })(); // ADD Big Button (function () { $("div.inp-btn").css("display","inline-block"); var input = $("div.inp-btn"); var button = $('<button class="feelinglucky"></button>'); button.css({ "width": "83px", "height": "33px", "border": "none", "margin-left":"14px", "background-color": hlcolor, "border-radius": "4px", "font-size": "12px", "color": "white", "cursor":"pointer", "display": "inline-block", "vertical-align": "top" }); button.hover(function() { $( this ).css("opacity","0.88"); }, function() { $( this ).css("opacity","1"); }); button.text("🎲 随机漫步"); button.on("click", function () { //var roll = Math.floor(Math.random() * imdbid ) + 1; // roll a random imdb subject //var rdimdb = roll.toString().padStart(7, '0'); //window.open("https://" + domain + "/subject/" + randomsj + "/", "_self"); //window.open("https://search.douban.com/"+ type +"/subject_search?search_text=tt" + rdimdb + "&cat=" + cat , "_self"); var rdlink; if (judgetype()=="book"){ }//rgb(38,143,149) rgb(234,161,100) else if (judgetype()=="movie") { var list = { "纪录片": 1, "传记": 2, "犯罪": 3, "历史": 4, "动作": 5, "情色": 6, "歌舞": 7, "儿童": 8, "悬疑": 10, "剧情": 11, "灾难": 12, "爱情": 13, "音乐": 14, "冒险": 15, "奇幻": 16, "科幻": 17, "运动": 18, "惊悚": 19, "恐怖": 20, "战争": 22, "短片": 23, "喜剧": 24, "动画": 25, "同性": 26, "西部": 27, "家庭": 28, "武侠片": 29, "古装": 30, "黑色电影": 31 }; var index = Math.floor(Math.random () * 29); var keys = Object.keys(list); var key = keys[index]; var value = list[key]; var rdrange = (Math.floor(Math.random () * 19) + 2 )*5; //2~20 *5 rdlink = "https://movie.douban.com/typerank?type_name=" + key + "&type=" + value + "&interval_id="+ rdrange +":"+ (rdrange-10) + "&action=#rd"; } else if (judgetype()=="music"){ } //rgb(250,128,0) if (url.includes("typerank?type_name")){ window.open(rdlink, "_self"); } else if (judgetype()=="movie"){ window.open(rdlink); } return false; }); input.after(button); $("span.operator-count").after(button.clone(true).css({"vertical-align":"middle","height": "26px"}).text("🎲 再来一次")); })(); // Movie RANDOM Picking Process function moviepick(){ var hash = window.location.hash; // 如果有 # if (hash && hash.slice(1)==="rd") { //var span = $("span.operator-count"); //var spantxt = span.text(); // 创建一个 MutationObserver 对象,传入一个回调函数 var already = false; var span = $("span.operator-count").get(0); var mlp = $("div.movie-list-panel.pictext").get(0); var spantxt; var observer = new MutationObserver(function (mutations) { // 遍历 mutations 数组,检查每个变化记录 mutations.forEach(function (mutation) { // 如果变化类型是 characterData 或者 childList,说明 span 元素的文本发生了变化 if (!already && (mutation.type === "characterData" || mutation.type === "childList")) { already = true; // 获取 span 元素的文本,并赋值给变量 spantxt //spantxt = mutation.target.textContent; spantxt = span.textContent; // 在控制台中输出 spantxt 的值 var sjcount = Number(spantxt.replace("(", "").replace(")", "")); var div = $("div.movie-list-item").first(); var ranknum = Number(div.find("span.rank-num").text()); var roll = Math.floor(Math.random () * sjcount); var rdsj = ranknum + roll; console.log("spantxt= "+ spantxt); console.log("sjcount= "+ sjcount); console.log("roll= "+ roll); checkAndScroll("div.movie-list-panel.pictext","div.movie-list-item", roll); observer.disconnect(); } }); }); observer.observe(mlp, { characterData: true, childList: true }); //span //findTarget("div.movie-list-panel.pictext","div.movie-list-item", roll); } } function scrollToBottom () { // 使用 jQuery 的 animate 方法,把页面滚动到底部,时间为 100 毫秒 $("html, body").animate ( { scrollTop: $(document).height () }, 100); } // 定义一个函数,用来寻找目标元素 function findTarget (panel, item, num) { // 使用 jQuery 的选择器,找到 class 为 movie-list-panel pictext 的 div 元素,并赋值给变量 panel var p = $(panel); // 在 panel 元素中,找到 class 包含 movie-list-item 的 div 元素,并赋值给变量 items var items = p.find(item); // 判断 items 元素的长度是否大于等于 100,如果是,说明已经出现了第 100 个 movie-list-item 的元素 if (items.length >= num) { // 在 items 元素中,找到第 100 个 div 元素,并赋值给变量 target var target = items.eq(num); // 返回 true,表示找到了目标元素 console.log("Found: " + num); var element = target.get(0); element.classList.add("highlighted"); //element.style.border = "5px solid yellow"; // 添加一个 5px 的边框 element.style.setProperty("border", "5px solid "+ hlcolor, "important"); // 添加一个带有!important标记的5px边框 element.style.setProperty("border-radius", "8px"); element.scrollIntoView({ behavior: "smooth", // 平滑滚动 block: "center", // 垂直方向居中对齐 inline: "center" // 水平方向居中对齐 }); return true; } else { // 返回 false,表示没有找到目标元素 console.log("Not found"); return false; } } // 定义一个函数,用来检查是否找到目标元素,如果没有,就继续滚动 function checkAndScroll(panel, item, num) { // 调用 findTarget 函数,开始寻找目标元素,并把结果赋值给变量 found var found = findTarget(panel, item, num); // 如果 found 是 false,说明没有找到目标元素 if (!found) { // 调用 scrollToBottom 函数,滚动到页面底部 scrollToBottom (); // 使用 setTimeout 方法,在 2000 毫秒后再次调用 checkAndScroll 函数,继续检查和滚动 setTimeout ( (function(){checkAndScroll(panel, item, num);}), 800); } return false; } // TUNE the Annual position (function () { var anltarget = $("fieldset"); if (judgetype()=="book"){ $(".bookannual").appendTo(anltarget); $(".bookannual").attr("style","margin-left:200px !important; top:-11px;"); } else if (judgetype()=="movie") { $(".movieannual").appendTo(anltarget); $(".movieannual").attr("style","margin-left:200px !important; top:-11px;"); } else if (judgetype()=="music"){ $(".musicannual").appendTo(anltarget); $(".musicannual").attr("style","margin-left:270px !important; top:-11px;"); } })(); (function () { var type = $('.types span:last-child'); var txing = $('<span><a href="/typerank?type_name=同性&type=26&interval_id=100:90&action=">同性</a></span>'); type.after(txing); if (url.includes("type=26")) { $('#wrapper #content h1').text($("#wrapper #content h1").text() + " 同性"); } })(); // grid-view list-view Process var urlkw = ["/wish", "/do", "/collect", "/mine?"]; if (urlkw.some(function (substring) { // includes keyword then run return url.includes(substring); })) { // Get link reference var pageslc; var href; var range = 15; var paginator = document.getElementsByClassName("paginator"); var pexist = Array.from(paginator).find(function(element) { return element.className === "paginator"; }); if (pexist) { pageslc = pexist.getElementsByTagName("a")[0]; href = pageslc.href; } else { // paginator is not exist href = window.location.href.split("#")[0]; // use default url } // calculate max PAGE nums var sjnumspan = document.getElementsByClassName ("subject-num")[0]; var parts = sjnumspan.textContent.split ("/"); var total = Number(parts[1].trim()); if (total <= 15) { range = total; } var pagemax = Math.ceil (total / 15); //var pagemax = Number(document.getElementsByClassName("thispage")[0].getAttribute("data-total-page")) || sjnum; // Function: Add fixed RANDOM links in Grid mode (function() { 'use strict'; if (domain.includes("book.douban")){ $('div.opt-bar.clearfix').after('<div class="nicetry" style="width:675px; height:24px ;"><a id="random" href="#" style="float: right; margin-right: 0px;">🎲 手气不错! </a></div>'); } else { $('div.opt-bar.mb30.clearfix').css("margin-bottom","0px"); $('div.opt-bar.mb30.clearfix').after('<div class="nicetry" style="width:675px; height:24px ;"><a id="random" href="#" style="float: right; margin-right: 0px;">🎲 手气不错! </a></div>'); $('div.grid-view > div.item.comment-item:first-child').css({"padding-top":"20px","border-top-width":"1px","border-top-style":"dashed","border-top-color":"rgb(221,221,221)","margin-top":"5px"}); $('div.grid-view').css({"border-top-width":"0px","padding-top":"0px"}); } //$('div.mode').after('<div class="nicetry" style="width:200px; height:21px ;"><a id="random" href="#" style="float: right; margin-right: 0px;">🎲 手气不错! </a></div>'); $('#random').on({ click: function () { amble(); return false;//阻止默认行为 } }); // $('#random').after('<span class="gray-dot">·</span>'); })(); // Function: Locate to RANDOM subject then highlight it -- according the #num at the end of Url var hash = window.location.hash; // 如果有 # if (hash) { // 去掉 # 号并转换为数字 var index = Number(hash.slice(1)); // 如果是有效的数字 if (index >= 1 && index <= 15) { // 根据 CSS 选择器获取特定的元素 var element; if (domain.includes("book.douban")){ var interest = document.getElementsByClassName("interest-list")[0]; var icount = interest.children.length; if (icount<15) { index = index % icount + 1; } element = document.querySelector( "ul.interest-list > li.subject-item:nth-child(" + (index) + ")" ); } else { var grid = document.getElementsByClassName("grid-view")[0]; var count = grid.children.length; if (count<15) { index = index % count + 1; } // % 求余 element = document.querySelector( "div.grid-view > div.item.comment-item:nth-child(" + (index) + ")" ); } // 如果找到元素 if (element) { // 给元素添加一个样式类 element.classList.add("highlighted"); //element.style.border = "5px solid yellow"; // 添加一个 5px 的黄色边框 element.style.setProperty("border", "5px solid "+ hlcolor, "important"); // 添加一个带有!important标记的5px黄色边框 element.style.setProperty("border-radius", "8px"); if (domain.includes("book.douban")){ $('li.highlighted > div.info > div.short-note > div.opt-l > a.d_link').after('<a id="again" href="#" style="float: right; margin-right: 0px;">🎲 再来一次! </a>'); } else { $('div.highlighted > div.info > ul > li > span.date').after('<a id="again" href="#" style="float: right; margin-right: 10px;">🎲 再来一次! </a>'); } $('#again').on({ click: function () { amble(); return false; } }); // 让元素滚动到可视区域 element.scrollIntoView({ behavior: "smooth", // 平滑滚动 block: "center", // 垂直方向居中对齐 inline: "center" // 水平方向居中对齐 }); } } } // Function: wish do collect random method function amble(){ var randomsj = Math.floor(Math.random() * total ) + 1; // 根据 total 生成一个随机项目 1 ~ total var pg = Math.floor(randomsj / 15) * 15; // 随机项目位于第几页 0 ~ pagemax-1 var sj = randomsj % 15 + 1; // randomsj / 15 的余数,显示在 pg 的第 1 ~ 15 项 var oldHref = location.href.split("#")[0]; // storage opening href var newHref = href.replace(/start=\d+/, "start=" + pg); // 替换 start 参数 window.open(newHref + "#" + sj,"_self"); //location.replace(newHref + "#" + sj); if (total<=15 || newHref==oldHref){ location.reload(); } } } // Function: Add RANDOM links in List mode