// ==UserScript== // @name 知乎增强 // @name:zh-CN 知乎增强 // @name:zh-TW 知乎增強 // @name:en Zhihu enhancement // @version 2.3.9 // @author X.I.U // @description 屏蔽指定类别(视频、盐选、文章、想法、关注[赞同了XX/关注了XX]等等)、屏蔽用户、屏蔽关键词、默认收起回答、快捷收起回答/评论(左键两侧)、快捷回到顶部(右键两侧)、区分问题文章、移除高亮链接、净化搜索热门、净化标题消息、展开问题描述、显示问题作者、默认高清原图(无水印)、置顶显示时间、完整问题时间、直达问题按钮、默认站外直链... // @description:zh-TW 屏蔽指定類別(視頻、鹽選、文章、想法、關注[贊同了XX/關注了XX]等等)、屏蔽用戶、屏蔽關鍵詞、默認收起回答、快捷收起回答/評論、快捷回到頂部、區分問題文章、移除高亮鏈接、默認高清原圖(無水印)、默認站外直鏈... // @description:en A more personalized Zhihu experience~ // @match *://www.zhihu.com/* // @match *://zhuanlan.zhihu.com/* // @exclude https://www.zhihu.com/signin* // @icon data:image/png;base64,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 // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_openInTab // @grant GM_getValue // @grant GM_setValue // @grant GM_notification // @grant GM_info // @grant window.onurlchange // @sandbox JavaScript // @license GPL-3.0 License // @run-at document-end // @namespace https://greasyfork.org/scripts/4122051 // @supportURL https://github.com/XIU2/UserScript // @homepageURL https://github.com/XIU2/UserScript // @downloadURL none // ==/UserScript== 'use strict'; var menu_ALL = [ ['menu_defaultCollapsedAnswer', '默认收起回答', '默认收起回答', true], ['menu_collapsedAnswer', '一键收起回答/评论', '一键收起回答/评论', true], ['menu_collapsedNowAnswer', '快捷收起回答/评论 (点击两侧空白处)', '快捷收起回答/评论', true], ['menu_backToTop', '快捷回到顶部 (右键两侧空白处)', '快捷回到顶部', true], ['menu_blockUsers', '屏蔽指定用户', '屏蔽指定用户', true], ['menu_customBlockUsers', '自定义屏蔽用户', '自定义屏蔽用户', ['故事档案局', '盐选推荐', '盐选科普', '盐选成长计划', '知乎盐选会员', '知乎盐选创作者', '盐选心理', '盐选健康必修课', '盐选奇妙物语', '盐选生活馆', '盐选职场', '盐选文学甄选', '盐选作者小管家', '盐选博物馆', '盐选点金', '盐选测评室', '盐选科技前沿', '盐选会员精品']], ['menu_blockKeywords', '屏蔽指定关键词', '屏蔽指定关键词', true], ['menu_blockKeywordsComment', '屏蔽关键词 - 评论区', '屏蔽关键词 - 评论区', true], ['menu_customBlockKeywords', '自定义屏蔽关键词', '自定义屏蔽关键词', []], ['menu_blockType', '屏蔽指定类别 (视频/文章等)', '勾选 = 屏蔽该类别的信息流', ''], ['menu_blockTypeVideo', '视频 [首页、搜索页、问题页、关注页]', '视频(首页、搜索页、问题页、关注页)', true], ['menu_blockTypeArticle', '文章 [首页、搜索页、关注页]', '文章(首页、搜索页、关注页)', false], ['menu_blockTypePin', '想法 [首页、关注页]', '想法(首页、关注页)', false], ['menu_blockTypeFollowAgree', '赞同了XX [关注页]', '赞同了XX(关注页)', false], ['menu_blockTypeFollowQuestion', '关注了XX [关注页]', '关注了XX(关注页)', false], ['menu_blockTypeTopic', '话题 [搜索页]', '话题(搜索页)', false], ['menu_blockTypeSearch', '杂志文章、盐选专栏、相关搜索等 [搜索页]', '相关搜索、杂志、盐选等(搜索页)', false], ['menu_blockYanXuan', '盐选内容 [问题页]', '盐选内容(问题页)', false], ['menu_blockTypeLiveHot', '热榜文章、直播、广告等 [热榜]', '热榜文章、直播、广告等 [热榜]', true], ['menu_cleanSearch', '净化搜索热门 (默认搜索词及热门搜索)', '净化搜索热门', false], ['menu_cleanTitles', '净化标题消息 (标题中的私信/消息)', '净化标题提醒', false], ['menu_questionRichTextMore', '展开问题描述', '展开问题描述', false], ['menu_publishTop', '置顶显示时间', '置顶显示时间', true], ['menu_typeTips', '区分问题文章', '区分问题文章', true], ['menu_toQuestion', '直达问题按钮', '直达问题按钮', true] ], menu_ID = []; for (let i=0;i menu_ALL.length){ // 如果菜单ID数组多于菜单数组,说明不是首次添加菜单,需要卸载所有脚本菜单 for (let i=0;i.zhihuE_SettingRoot {position: absolute;top: 50%;left: 50%;-webkit-transform: translate(-50%, -50%);-moz-transform: translate(-50%, -50%);-ms-transform: translate(-50%, -50%);-o-transform: translate(-50%, -50%);transform: translate(-50%, -50%);width: auto;min-width: 400px;max-width: 600px;height: auto;min-height: 150px;max-height: 400px;color: #535353;background-color: #fff;border-radius: 3px;} .zhihuE_SettingBackdrop_1 {position: fixed;top: 0;right: 0;bottom: 0;left: 0;z-index: 203;display: -webkit-box;display: -ms-flexbox;display: flex;-webkit-box-orient: vertical;-webkit-box-direction: normal;-ms-flex-direction: column;flex-direction: column;-webkit-box-pack: center;-ms-flex-pack: center;justify-content: center;overflow-x: hidden;overflow-y: auto;-webkit-transition: opacity .3s ease-out;transition: opacity .3s ease-out;} .zhihuE_SettingBackdrop_2 {position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 0;background-color: rgba(18,18,18,.65);-webkit-transition: background-color .3s ease-out;transition: background-color .3s ease-out;} .zhihuE_SettingRoot .zhihuE_SettingHeader {padding: 10px 20px;color: #fff;font-weight: bold;background-color: #3994ff;border-radius: 3px 3px 0 0;} .zhihuE_SettingRoot .zhihuE_SettingMain {padding: 10px 20px;border-radius: 0 0 3px 3px;} .zhihuE_SettingHeader span {float: right;cursor: pointer;} .zhihuE_SettingMain input {margin: 10px 6px 10px 0;cursor: pointer;vertical-align:middle} .zhihuE_SettingMain label {margin-right: 20px;user-select: none;cursor: pointer;vertical-align:middle} .zhihuE_SettingMain hr {border: 0.5px solid #f4f4f4;} [data-theme="dark"] .zhihuE_SettingRoot {color: #adbac7;background-color: #343A44;} [data-theme="dark"] .zhihuE_SettingHeader {color: #d0d0d0;background-color: #2D333B;} [data-theme="dark"] .zhihuE_SettingMain hr {border: 0.5px solid #2d333b;}
${title}

${tips}


` if (line) _br = '
' for (let i=0; i${menu[i][1]}${_br}` } else { _html += `${_br}` } } _html += `
` document.body.insertAdjacentHTML('beforeend', _html); // 插入网页末尾 setTimeout(function() { // 延迟 100 毫秒,避免太快 // 关闭按钮 点击事件 document.querySelector('.zhihuE_SettingClose').onclick = function(){this.parentElement.parentElement.parentElement.remove();document.querySelector('.zhihuE_SettingStyle').remove();} // 点击周围空白处 = 点击关闭按钮 document.querySelector('.zhihuE_SettingBackdrop_2').onclick = function(event){if (event.target == this) {document.querySelector('.zhihuE_SettingClose').click();};} // 复选框 点击事件 document.getElementsByName('zhihuE_Setting').forEach(function (checkBox) { checkBox.addEventListener('click', function(){if (this.checked) {GM_setValue(this.value, true);} else {GM_setValue(this.value, false);}}); }) }, 100) } // 添加收起回答观察器 function getCollapsedAnswerObserver() { if (!window._collapsedAnswerObserver) { const observer = new MutationObserver(mutations => { for (const mutation of mutations) { if (mutation.target.hasAttribute('script-collapsed')) return // 短的回答 if (mutation.target.classList.contains('RichContent')) { for (const addedNode of mutation.addedNodes) { if (addedNode.nodeType != Node.ELEMENT_NODE) continue if (addedNode.className != 'RichContent-inner') continue if (addedNode.offsetHeight < 400) break //console.log('111',addedNode, addedNode.classList, addedNode.classList.contains('RichContent-inner'), addedNode.offsetHeight, addedNode.textContent.length) const button = mutation.target.querySelector('.ContentItem-actions.Sticky [data-zop-retract-question]'); if (button) { mutation.target.setAttribute('script-collapsed', ''); button.click(); return } } // 长的回答 } else if (mutation.target.tagName === 'DIV' && !mutation.target.style.cssText && !mutation.target.className) { if (mutation.target.parentElement.hasAttribute('script-collapsed')) return //console.log('222',mutation.target, mutation.target.querySelector('.ContentItem-actions.Sticky [data-zop-retract-question]')) const button = mutation.target.querySelector('.ContentItem-actions.Sticky [data-zop-retract-question]'); if (button) { mutation.target.parentElement.setAttribute('script-collapsed', ''); button.click(); return } } } }) observer.start = function() { if (!this._active) { this.observe(document, { childList: true, subtree: true }); this._active = true; } } observer.end = function() { if (this._active) { this.disconnect(); } } window.addEventListener('urlchange', function() { observer[location.href.indexOf('/answer/') === -1 ? 'start' : 'end'](); }) window._collapsedAnswerObserver = observer; } return window._collapsedAnswerObserver } // 默认收起回答 function defaultCollapsedAnswer() { if (!menu_value('menu_defaultCollapsedAnswer')) return const observer = getCollapsedAnswerObserver(); if (location.href.indexOf('/answer/') === -1) { observer.start(); } } // 一键收起回答+评论(全部) function collapsedAnswer() { if (!menu_value('menu_collapsedAnswer')) return //console.log('1111', document.querySelector('.CornerAnimayedFlex')) if (document.querySelector('.CornerAnimayedFlex') && !document.getElementById('collapsed-button')) { // 向网页中插入收起全部回答按钮+样式+绑定点击事件 document.head.appendChild(document.createElement('style')).textContent = '.CornerButton{margin-bottom:8px !important;}.CornerButtons{bottom:45px !important;}'; document.querySelector('.CornerAnimayedFlex').insertAdjacentHTML('afterBegin', ''); document.getElementById('collapsed-button').onclick = function () { // 收起所有评论(悬浮的 [收起评论]) document.querySelectorAll('.Comments-container').forEach(function (el) { let commentCollapseButton = getXpath('//button[text()="收起评论"]', el) if (commentCollapseButton) commentCollapseButton.click(); }); // 收起所有评论(固定的 [收起评论]) document.querySelectorAll('.RichContent >.ContentItem-actions>button:first-of-type').forEach(function (el) { if (el.textContent.indexOf('收起评论') > -1) el.click() }); if (location.pathname === '/' || location.pathname === '/hot' || location.pathname === '/follow') {// 对于首页的关注、推荐、热榜 document.querySelectorAll('.ContentItem-rightButton').forEach(function (el) {if (el.hasAttribute('data-zop-retract-question')) {el.click();};}); } else { // 被 getCollapsedAnswerObserver 函数收起过的,固定 [收起] 按钮 document.querySelectorAll('[script-collapsed]').forEach(function(scriptCollapsed) {scriptCollapsed.querySelectorAll('.ContentItem-actions [data-zop-retract-question], .ContentItem-actions.Sticky [data-zop-retract-question]').forEach(function(button) {button.click();});}) // 被 getCollapsedAnswerObserver 函数收起过的,悬浮 [收起] 按钮(悬浮底部的横栏) document.querySelectorAll('.RichContent:not([script-collapsed]) .ContentItem-actions.Sticky [data-zop-retract-question]').forEach(function(button) { let el = button.parentElement; while (!el.classList.contains('RichContent')) {el = el.parentElement;} if (el) el.setAttribute('script-collapsed', ''); button.click(); }) const observer = getCollapsedAnswerObserver(); observer.start(); if (!menu_value('menu_defaultCollapsedAnswer') && !observer._disconnectListener) { window.addEventListener('urlchange', function() { observer.end(); window._collapsedAnswerObserver = null; }) observer._disconnectListener = true; } } } } } // 收起当前回答、评论(监听点击事件,点击网页两侧空白处) function collapsedNowAnswer(selectors) { backToTop(selectors) // 快捷回到顶部 if (!menu_value('menu_collapsedNowAnswer')) return document.querySelector(selectors).onclick = function(event){ if (event.target == this) { // 下面这段主要是 [收起回答],顺便 [收起评论](如果展开了的话) let rightButton = document.querySelector('.ContentItem-actions.Sticky.RichContent-actions.is-fixed.is-bottom') if (rightButton) { // 悬浮在底部的 [收起回答](此时正在浏览回答内容 [中间区域]) // 固定的 [收起评论](先看看是否展开评论) let commentCollapseButton = rightButton.querySelector('button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type') //console.log('111') if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) commentCollapseButton.click(); // 再去收起回答 rightButton = rightButton.querySelector('.ContentItem-rightButton[data-zop-retract-question]') //console.log('222') if (rightButton) rightButton.click(); } else { // 固定在回答底部的 [收起回答](此时正在浏览回答内容 [尾部区域]) // 悬浮的 [收起评论](此时正在浏览评论内容 [中间区域]) //if (getXpath('//button[text()="收起评论"]',document.querySelector('.Comments-container'))) {getXpath('//button[text()="收起评论"]',document.querySelector('.Comments-container')).click();console.log('asfaf')} let answerCollapseButton_ = false; for (let el of document.querySelectorAll('.ContentItem-rightButton[data-zop-retract-question]')) { // 遍历所有回答底部的 [收起] 按钮 if (isElementInViewport(el)) { // 判断该 [收起] 按钮是否在可视区域内 // 固定的 [收起评论](先看看是否展开评论,即存在 [收起评论] 按钮) let commentCollapseButton = el.parentNode.querySelector('button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type') // 如果展开了评论,就收起评论 //console.log('333') //if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) commentCollapseButton.click(); if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) { commentCollapseButton.click(); if (!isElementInViewport(commentCollapseButton)) scrollTo(0,el.offsetTop+50) } //console.log('444') el.click() // 再去收起回答 answerCollapseButton_ = true; // 如果找到并点击收起了,就没必要执行下面的代码了(可视区域中没有 [收起回答] 时) break } } // 针对完全看不到 [收起回答] 按钮时(如 [头部区域],以及部分明明很长却不显示悬浮横条的回答) if (!answerCollapseButton_) { for (let el of document.querySelectorAll('.List-item, .Card.AnswerCard, .Card.TopstoryItem')) { // 遍历所有回答主体元素 if (isElementInViewport_(el)) { // 判断该回答是否在可视区域内 // 固定的 [收起评论](先看看是否展开评论,即存在 [收起评论] 按钮) let commentCollapseButton = el.querySelector('button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type') // 如果展开了评论,就收起评论 //console.log('555',commentCollapseButton) if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) { commentCollapseButton.click(); if (!isElementInViewport(commentCollapseButton)) scrollTo(0,el.offsetTop+50) } let answerCollapseButton__ = el.querySelector('.ContentItem-rightButton[data-zop-retract-question]'); //console.log('666') if (answerCollapseButton__) answerCollapseButton__.click() // 再去收起回答 break } } } } // 下面这段只针对 [收起评论](如果展开了的话) let commentCollapseButton_ = false, commentCollapseButton__ = false; // 悬浮的 [收起评论](此时正在浏览评论内容 [中间区域]) let commentCollapseButton = getXpath('//button[text()="收起评论"]',document.querySelector('.Comments-container')) if (commentCollapseButton) { //console.log('777', commentCollapseButton) commentCollapseButton.click(); } else { // 固定的 [收起评论](此时正在浏览评论内容 [头部区域]) let commentCollapseButton_1 = document.querySelectorAll('.ContentItem-actions > button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type, .ContentItem-action > button.Button.Button--plain.Button--withIcon.Button--withLabel:first-of-type') if (commentCollapseButton_1.length > 0) { for (let el of commentCollapseButton_1) { if (el.textContent.indexOf('收起评论') > -1) { if (isElementInViewport(el)) { //console.log('888') el.click() commentCollapseButton_ = true // 如果找到并点击了,就没必要执行下面的代码了(可视区域中没有 [收起评论] 时) break } } } } if (commentCollapseButton_ == false) { // 可视区域中没有 [收起评论] 时(此时正在浏览评论内容 [头部区域] + [尾部区域](不上不下的,既看不到固定的 [收起评论] 又看不到悬浮的 [收起评论])),需要判断可视区域中是否存在评论元素 let commentCollapseButton_1 = document.querySelectorAll('.Comments-container') if (commentCollapseButton_1.length > 0) { for (let el of commentCollapseButton_1) { if (isElementInViewport(el)) { let parentElement = findParentElement(el, 'List-item') || findParentElement(el, 'Card '), commentCollapseButton = parentElement.querySelector('.ContentItem-actions > button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type') if (commentCollapseButton.textContent.indexOf('收起评论') > -1) { //console.log('999') commentCollapseButton.click() if (!isElementInViewport(commentCollapseButton)) {console.log(parentElement,parentElement.offsetTop,parentElement.offsetHeight);scrollTo(0,parentElement.offsetTop+parentElement.offsetHeight-50)} commentCollapseButton__ = true // 如果找到并点击了,就没必要执行下面的代码了(可视区域中没有 评论元素 时) break } } } } if (commentCollapseButton__ == false) { // 如果上面的都没找到,那么就尝试寻找评论末尾的 [评论回复框] let commentCollapseButton_2 = document.querySelectorAll('.Editable-content') if (commentCollapseButton_2.length > 0) { for (let el of commentCollapseButton_2) { if (isElementInViewport(el)) { let parentElement = findParentElement(el, 'List-item') || findParentElement(el, 'Card '), commentCollapseButton = parentElement.querySelector('.ContentItem-actions > button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type') //console.log(commentCollapseButton) if (commentCollapseButton.textContent.indexOf('收起评论') > -1) { //console.log('101010') commentCollapseButton.click() if (!isElementInViewport(commentCollapseButton)) {console.log(parentElement,parentElement.offsetTop,parentElement.offsetHeight);scrollTo(0,parentElement.offsetTop+parentElement.offsetHeight-50)} break } } } } } } } } } } // 回到顶部(监听点击事件,鼠标右键点击网页两侧空白处) function backToTop(selectors) { if (!menu_value('menu_backToTop')) return document.querySelector(selectors).oncontextmenu = function(event){ if (event.target == this) { event.preventDefault(); window.scrollTo(0,0) } } } //获取元素是否在可视区域(完全可见) function isElementInViewport(el) { let rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } //获取元素是否在可视区域(部分可见) function isElementInViewport_(el) { let rect = el.getBoundingClientRect(); return ( rect.top < (window.innerHeight || document.documentElement.clientHeight) && rect.bottom > 0 ); } // 自定义屏蔽用户 function customBlockUsers() { let nowBlockUsers = ''; menu_value('menu_customBlockUsers').forEach(function(item){nowBlockUsers += '|' + item}) //console.log(nowBlockUsers.replace('|','')) let newBlockUsers = prompt('编辑 [自定义屏蔽用户]\n(不同用户名之间使用 "|" 分隔,例如:用户A|用户B|用户C )', nowBlockUsers.replace('|','')); if (newBlockUsers === '') { GM_setValue('menu_customBlockUsers', []); registerMenuCommand(); // 重新注册脚本菜单 } else if (newBlockUsers != null) { GM_setValue('menu_customBlockUsers', newBlockUsers.split('|')); registerMenuCommand(); // 重新注册脚本菜单 } }; // 屏蔽指定用户 function blockUsers(type) { if (!menu_value('menu_blockUsers')) return if (!menu_value('menu_customBlockUsers') || menu_value('menu_customBlockUsers').length < 1) return switch(type) { case 'index': blockUsers_('.Card.TopstoryItem.TopstoryItem-isRecommend', 'Card TopstoryItem TopstoryItem-isRecommend'); break; case 'question': blockUsers_question(); break; case 'search': blockUsers_search(); break; case 'topic': blockUsers_('.List-item.TopicFeedItem', 'List-item TopicFeedItem'); break; case 'people': blockUsers_button_people(); // 添加屏蔽用户按钮(用户主页) break; } blockUsers_comment(); // 评论区 blockUsers_button(); // 加入黑名单按钮(用户信息悬浮框中) function blockUsers_(className1, className2) { // 前几条因为是直接加载的,而不是动态插入网页的,所以需要单独判断 function blockKeywords_now() { document.querySelectorAll(className1).forEach(function(item1){ let item = item1.querySelector('.ContentItem.AnswerItem, .ContentItem.ArticleItem'); // 用户名所在元素 if (item) { for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单 if (keyword != '' && item.dataset.zop.indexOf('authorName":"' + keyword + '",') > -1) { // 找到就删除该信息流 console.log('已屏蔽:' + item.dataset.zop); item1.hidden = true; break; } } } }) } blockKeywords_now(); window.addEventListener('urlchange', function(){ setTimeout(blockKeywords_now, 1000); // 网页 URL 变化后再次执行 }) // 这个是监听网页插入事件,用来判断后续网页动态插入的元素 const callback = (mutationsList, observer) => { for (const mutation of mutationsList) { for (const target of mutation.addedNodes) { if (target.nodeType != 1) return if (target.className === className2) { let item = target.querySelector('.ContentItem.AnswerItem, .ContentItem.ArticleItem'); // 用户名所在元素 if (item) { for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单 if (keyword != '' && item.dataset.zop.indexOf('authorName":"' + keyword + '",') > -1) { // 找到就删除该信息流 console.log('已屏蔽:' + item.dataset.zop); target.hidden = true; break; } } } } } } }; const observer = new MutationObserver(callback); observer.observe(document, { childList: true, subtree: true }); } function blockUsers_question() { const blockUsers_question_ = (mutationsList, observer) => { for (const mutation of mutationsList) { for (const target of mutation.addedNodes) { if (target.nodeType != 1) return if (target.className === 'List-item' || target.className === 'Card AnswerCard') { let item1 = target.querySelector('.ContentItem.AnswerItem'); if (item1) { menu_value('menu_customBlockUsers').forEach(function(item2){ // 遍历用户黑名单 if (item1.dataset.zop.indexOf('authorName":"' + item2 + '",') > -1) { // 找到就删除该回答 console.log('已屏蔽:' + item1.dataset.zop) target.hidden = true; } }) } } } } }; const blockUsers_question_answer_ = (mutationsList, observer) => { for (const mutation of mutationsList) { for (const target of mutation.addedNodes) { if (target.nodeType != 1) return target.querySelectorAll('.List-item, .Card.AnswerCard').forEach(function(item){ let item1 = item.querySelector('.ContentItem.AnswerItem'); if (item1) { menu_value('menu_customBlockUsers').forEach(function(item2){ // 遍历用户黑名单 if (item1.dataset.zop.indexOf('authorName":"' + item2 + '",') > -1) { // 找到就删除该回答 console.log('已屏蔽:' + item1.dataset.zop) item.hidden = true; } }) } }) } } }; if (location.pathname.indexOf('/answer/') > -1) { // 回答页(就是只有三个回答的页面) const observer = new MutationObserver(blockUsers_question_answer_); observer.observe(document, { childList: true, subtree: true }); } else { // 问题页(可以显示所有回答的页面) const observer = new MutationObserver(blockUsers_question_); observer.observe(document, { childList: true, subtree: true }); } // 针对的是打开网页后直接加载的前面几个回答(上面哪些是针对动态加载的回答) document.querySelectorAll('.List-item, .Card.AnswerCard').forEach(function(item){ let item1 = item.querySelector('.ContentItem.AnswerItem'); if (item1) { menu_value('menu_customBlockUsers').forEach(function(item2){ // 遍历用户黑名单 if (item1.dataset.zop.indexOf('authorName":"' + item2 + '",') > -1) { // 找到就删除该回答 console.log('已屏蔽:' + item1.dataset.zop) item.hidden = true; } }) } }) } function blockUsers_search() { function blockUsers_now() { if (location.search.indexOf('type=content') === -1) return // 目前只支持搜索页的 [综合] document.querySelectorAll('.Card.SearchResult-Card[data-za-detail-view-path-module="AnswerItem"], .Card.SearchResult-Card[data-za-detail-view-path-module="PostItem"]').forEach(function(item1){ let item = item1.querySelector('.RichText.ztext.CopyrightRichText-richText b'); // 用户名所在元素 if (item) { for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单 if (keyword != '' && item.textContent === keyword) { // 找到就删除该信息流 console.log('已屏蔽:' + item.textContent); item1.hidden = true; break; } } } }) } setTimeout(blockUsers_now, 2000); window.addEventListener('urlchange', function(){ setTimeout(blockUsers_now, 1000); // 网页 URL 变化后再次执行 }) const callback = (mutationsList, observer) => { if (location.search.indexOf('type=content') === -1) return // 目前只支持搜索页的 [综合] for (const mutation of mutationsList) { for (const target of mutation.addedNodes) { if (target.nodeType != 1) return let item = target.querySelector('.Card.SearchResult-Card[data-za-detail-view-path-module="AnswerItem"] .RichText.ztext.CopyrightRichText-richText b, .Card.SearchResult-Card[data-za-detail-view-path-module="PostItem"] .RichText.ztext.CopyrightRichText-richText b'); if (item) { for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单 if (keyword != '' && item.textContent === keyword) { // 找到就删除该信息流 console.log('已屏蔽:' + item.textContent); target.hidden = true; break; } } } } } }; const observer = new MutationObserver(callback); observer.observe(document, { childList: true, subtree: true }); } function blockUsers_comment() { const callback = (mutationsList, observer) => { for (const mutation of mutationsList) { for (const target of mutation.addedNodes) { if (target.nodeType != 1) return //console.log(target) if (target.tagName == 'DIV' && target.className.indexOf('css-') == 0 && target.dataset.id == undefined) { let item = target.querySelector('a[href^="https://www.zhihu.com/people/"]>img.Avatar[alt][loading]') if (item) { //console.log(item) menu_value('menu_customBlockUsers').forEach(function(item1){ // 遍历用户黑名单 if (item.alt === item1) { // 找到就删除该搜索结果 //console.log(item.alt,item1) item.parentElement.parentElement.parentElement.parentElement.style.display = "none"; } }) // 添加屏蔽用户按钮(点赞、回复等按钮后面) /*if (item) { let footer = findParentElement(item, 'CommentItemV2-meta', true).parentElement.querySelector('.CommentItemV2-metaSibling > .CommentItemV2-footer'), userid = item.parentElement; if (userid && footer && !footer.lastElementChild.dataset.name) { userid = userid.href.split('/')[4]; footer.insertAdjacentHTML('beforeend',``); footer.lastElementChild.onclick = function(){blockUsers_button_add(this.dataset.name, this.dataset.userid, false)} } }*/ } } } } }; const observer = new MutationObserver(callback); observer.observe(document, { childList: true, subtree: true }); } // 添加屏蔽用户按钮(用户信息悬浮框中) function blockUsers_button() { const callback = (mutationsList, observer) => { for (const mutation of mutationsList) { for (const target of mutation.addedNodes) { if (target.nodeType != 1) return //console.log(target, target.className) if (target.tagName == 'DIV' && target.className && (target.className.indexOf('css-') == 0 || target.style == 'opacity: 1;')) { const item = target.querySelector('.MemberButtonGroup.ProfileButtonGroup.HoverCard-buttons'), item1 = target.querySelector('img.Avatar+div span.UserLink>a.UserLink-link[data-za-detail-view-element_name=User]'); if (item1) { const name = item1.textContent, userid = item1.href.split('/')[4], users = menu_value('menu_customBlockUsers'); for (let num = 0;num