您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
模拟点击实现内容屏蔽
// ==UserScript== // @name 知乎屏蔽 // @namespace https://github.com/mygith/monkey // @match https://www.zhihu.com/ // @grant none // @version 0.3 // @author mygith // @license GPL License // @description 模拟点击实现内容屏蔽 // ==/UserScript== (function () { 'use strict'; // 配置区==================================================== const titleStopWords = ['NPD', 'INTP', '北大', '清华', '00元', '小说', '基建狂魔', '出国', '出了国', '中国学生', '留学', '韩流', '小米', '华为', '尊界', '长城', '比亚迪', '鸿蒙', '问界', '品牌', '明星', 'NAS', '环保', '健康', '618', '护肤', '敏感肌', '面膜', '新品', '跨境电商', '副业', '赚钱', '海外', '富贵', '适合普通人', '赚麻了', '神器', '脱毛', '爱美', '少儿编程', '颜值', '暧昧', '异性', '舔狗', '彩礼', '抑郁', '疯狂', '恋', '植发', '分享', '生理性', '婚姻', '男', '女', '虐文', '肉体', '沉迷', '为什么我', '只能', '其实', '真的', '听过', '洗白', '焦虑', '劝退', '人生', '底层', '匿名', '路子', '陌生人', '电视剧', '中年危机', '亲戚', '夫妻', '内向', '玄', '修炼', ]; const badgeTextStopWords = ['全网', '同名', '家居', '家电', '优质', '文案', '好物', '推荐', '合作', '简介']; const targetSelector = '.Topstory-content, .QuestionPage-main'; const cardSelector = '.Card:not([data-zf-processed])'; const titleSelector = '.ContentItem-title, [data-za-detail-view-element_name="Title"], .QuestionHeader-title'; const badgeTextSelector = '.AuthorInfo-badgeText'; const menuSelector = '.Menu-item'; const menuText = '不感兴趣'; const menuTimeout = 2000; // 菜单等待超时时间 // 逻辑区 ==================================================== let observer; // 智能点击操作(带重试机制) const performBlock = async (card) => { try { // 第一阶段:点击更多按钮 const moreBtn = card.querySelector('.ContentItem-action button[aria-label="更多"]'); if (!moreBtn) { console.warn('⚠️ 未找到更多按钮', card); return false; } moreBtn.click(); // 等待菜单渲染 const menuItem = await waitForElement(); if (!menuItem) { console.error('⌛ 菜单项加载超时'); return false; } // 第二阶段:点击屏蔽项 menuItem.click(); console.log('✅ 已屏蔽内容'); return true; } catch (e) { console.error('❌ 屏蔽流程异常:', e); return false; } function waitForElement() { return new Promise((resolve, reject) => { const start = Date.now(); const check = () => { const nodeList = document.querySelectorAll(menuSelector); const el = Array.from(nodeList).find(el => el.textContent.trim().includes(menuText) ); if (el) return resolve(el); if (Date.now() - start > menuTimeout) return reject('Timeout'); requestAnimationFrame(check); }; check(); }); } }; // 卡片处理器(带状态追踪) const processCard = async (card) => { if (card.dataset.zfStatus) return; // 防止重复处理 const title = card.querySelector(titleSelector)?.textContent.trim(); if (!title) { card.dataset.zfStatus = 'no-title'; return; } if (titleStopWords.some(w => title.includes(w))) { card.dataset.zfStatus = 'processing'; performBlock(card); } else { const badgeText = card.querySelector(badgeTextSelector)?.textContent.trim(); if (badgeTextStopWords.some(w => badgeText.includes(w))) { card.dataset.zfStatus = 'processing'; performBlock(card); } else { card.dataset.zfStatus = 'passed'; } } }; // 批量处理器(带节流控制) const processCards = (() => { let processing = false; return (root) => { if (processing) return; processing = true; const cards = Array.from(root.querySelectorAll(cardSelector)); cards.forEach(card => processCard(card)); requestAnimationFrame(() => processing = false); }; })(); // 观察器管理(动态容器感知) const initObserver = () => { if (observer) observer.disconnect(); const target = document.querySelector(targetSelector) || document.documentElement; processCards(target); observer = new MutationObserver(mutations => { const needsCheck = mutations.some(m => m.addedNodes.length > 0 || m.attributeName === 'class' ); if (needsCheck) processCards(target); }); observer.observe(target, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] }); // SPA路由检测 let lastPath = location.pathname; const checkRoute = () => { if (location.pathname !== lastPath) { lastPath = location.pathname; initObserver(); // 重新初始化 } requestAnimationFrame(checkRoute); }; checkRoute(); }; // 启动控制器 const init = () => { if (document.readyState === 'complete') initObserver(); else window.addEventListener('load', initObserver, { once: true }); }; // 兼容性启动 document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', init) : init(); })();