过滤知乎推荐中包含特定关键词的内容,支持黑白名单和模式切换
// ==UserScript==
// @name 知乎关键词过滤助手
// @namespace http://tampermonkey.net/
// @version 0.9
// @description 过滤知乎推荐中包含特定关键词的内容,支持黑白名单和模式切换
// @author You
// @match https://www.zhihu.com/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @license AGPLv3
// ==/UserScript==
(function() {
'use strict';
// 默认黑名单关键词 不区分大小写
const defaultBlacklist = ["洗地机", "GOOVIS"];
// 默认白名单关键词 不区分大小写
const defaultWhitelist = ["AI", "Gemini", "Anthropic"];
// 获取已保存的黑白名单,如果没有则使用默认值, 并转换为 Set
let blacklist = new Set(GM_getValue("blacklist", defaultBlacklist));
let whitelist = new Set(GM_getValue("whitelist", defaultWhitelist));
// 获取当前的过滤模式,默认为黑名单模式
let filterMode = GM_getValue("filterMode", "blacklist");
let whitelistRegex = null;
let blacklistRegex = null;
// 构建正则表达式
function buildRegex() {
whitelistRegex = new RegExp(Array.from(whitelist).join("|"), "i"); // "i" 表示忽略大小写
blacklistRegex = new RegExp(Array.from(blacklist).join("|"), "i");
}
buildRegex(); // 初始构建
// 过滤函数,只针对单个元素进行过滤
function filterElement(element) {
const textContent = element.textContent; // 缓存 textContent
let shouldHide = false;
if (filterMode === "blacklist") {
// 黑名单模式:使用正则表达式匹配
shouldHide = blacklistRegex.test(textContent);
} else if (filterMode === "whitelist") {
// 白名单模式:先用白名单正则匹配,再用黑名单正则排除
shouldHide = !whitelistRegex.test(textContent);
if (!shouldHide && blacklistRegex.test(textContent)) {
shouldHide = true;
}
}
if (shouldHide && element.style.display !== "none") {
element.style.display = "none";
console.log("Blacklisted: " + textContent);
} else if (!shouldHide && element.style.display === "none") {
element.style.display = "";
}
}
// 过滤函数,用于过滤整个页面
function filterContent() {
const elements = document.querySelectorAll("div.TopstoryItem-isRecommend.TopstoryItem.Card");
elements.forEach(filterElement);
}
// 使用 MutationObserver 监听动态加载的内容
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
// 只处理元素节点,并且是目标元素
if (node.nodeType === Node.ELEMENT_NODE && node.matches('div.TopstoryItem-isRecommend.TopstoryItem.Card')) {
filterElement(node); // 对新添加的单个节点进行过滤
}
});
});
});
const config = { childList: true, subtree: true };
observer.observe(document.body, config);
// 初始过滤
filterContent();
// 添加设置菜单
function addMenuCommands() {
GM_registerMenuCommand("设置黑名单", () => {
let newBlacklist = prompt("请输入黑名单关键词,用逗号分隔", Array.from(blacklist).join(","));
if (newBlacklist !== null) {
// 将中文逗号替换为英文逗号
newBlacklist = newBlacklist.replace(/,/g, ",");
blacklist = new Set(newBlacklist.split(",").map(s => s.trim()));
GM_setValue("blacklist", Array.from(blacklist)); // 存储时还需要转为数组
buildRegex();
filterContent();
}
});
GM_registerMenuCommand("设置白名单", () => {
let newWhitelist = prompt("请输入白名单关键词,用逗号分隔", Array.from(whitelist).join(","));
if (newWhitelist !== null) {
// 将中文逗号替换为英文逗号
newWhitelist = newWhitelist.replace(/,/g, ",");
whitelist = new Set(newWhitelist.split(",").map(s => s.trim()));
GM_setValue("whitelist", Array.from(whitelist)); // 存储时还需要转为数组
buildRegex();
filterContent();
}
});
GM_registerMenuCommand("切换到黑名单模式", () => {
filterMode = "blacklist";
GM_setValue("filterMode", filterMode);
// buildRegex(); // 切换模式不需要重新构建正则
filterContent();
});
GM_registerMenuCommand("切换到白名单模式", () => {
filterMode = "whitelist";
GM_setValue("filterMode", filterMode);
// buildRegex(); // 切换模式不需要重新构建正则
filterContent();
});
}
addMenuCommands();
})();