Hide YouTube homepage videos by blacklisted words in title or channel name
当前为
// ==UserScript==
// @name YouTube Keyword Blocker (Whole‑Word Mode)
// @description Hide YouTube homepage videos by blacklisted words in title or channel name
// @match https://www.youtube.com/*
// @run-at document-end
// @version 0.0.1.20250522140812
// @namespace https://greasyfork.org/users/1435046
// ==/UserScript==
(function () {
'use strict';
// skip “results” and “@channel” pages
if (location.pathname.startsWith('/results') || location.pathname.startsWith('/@')) return;
// 1) List words
const terms = [
];
// 2) Convert to RegExp objects with \b boundaries, case‑insensitive
const blacklist = terms.map(term => {
const esc = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
return new RegExp(`\\b${esc}\\b`, 'i');
});
const ITEM_SELECTOR = 'ytd-rich-item-renderer'; /*, ytd-rich-grid-media, ytd-video-renderer*/
const TITLE_SELECTOR = '#video-title';
const CHANNEL_SELECTOR = 'ytd-channel-name a';
function filterItem(item) {
// skip “results” and “@channel” pages on dynamic loads
if (location.pathname.startsWith('/results') ||
location.pathname.startsWith('/@')) return;
// skip if we've already seen this node
if (item.dataset.keywordBlocked) return;
item.dataset.keywordBlocked = '1';
const linkEl = item.querySelector('a#video-title-link');
const title = linkEl
? linkEl.getAttribute('aria-label').trim()
: '‹no title›';
console.log('› filterItem saw:', item.tagName, title);
const channelEl = item.querySelector(CHANNEL_SELECTOR);
const channel = channelEl ? channelEl.textContent.trim() : '';
for (const re of blacklist) {
if (re.test(title) || re.test(channel)) {
console.log(
`Blocking video:\n` +
` title: "${title}"\n` +
` channel: "${channel}"\n` +
` matched: ${re}`
);
item.style.display = 'none';
return;
}
}
}
function scanPage() {
// skip “results” and “@channel” pages on every scan
if (location.pathname.startsWith('/results') ||
location.pathname.startsWith('/@')) return;
document.querySelectorAll(ITEM_SELECTOR).forEach(filterItem);
}
new MutationObserver(mutations => {
for (const { addedNodes } of mutations) {
for (const node of addedNodes) {
if (!(node instanceof HTMLElement)) continue;
if (node.matches(ITEM_SELECTOR)) filterItem(node);
else node.querySelectorAll && node.querySelectorAll(ITEM_SELECTOR).forEach(filterItem);
}
}
}).observe(document.body, { childList: true, subtree: true });
scanPage();
window.addEventListener('yt-navigate-finish', scanPage);
})();