// ==UserScript== // @name Pixiv小说屏蔽关键词/作者/标签(三重过滤)+设置面板+导入导出 // @namespace http://tampermonkey.net/ // @version 2025-05-31 // @description 屏蔽含有指定关键词、作者名或标签的 Pixiv 项目,支持自定义关键词和导入导出设置。 // @author 灌注雾莉静子喵 // @match https://www.pixiv.net/tags* // @icon https://www.google.com/s2/favicons?sz=64&domain=pixiv.net // @grant GM_addStyle // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/537840/Pixiv%E5%B0%8F%E8%AF%B4%E5%B1%8F%E8%94%BD%E5%85%B3%E9%94%AE%E8%AF%8D%E4%BD%9C%E8%80%85%E6%A0%87%E7%AD%BE%EF%BC%88%E4%B8%89%E9%87%8D%E8%BF%87%E6%BB%A4%EF%BC%89%2B%E8%AE%BE%E7%BD%AE%E9%9D%A2%E6%9D%BF%2B%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA.user.js // @updateURL https://update.greasyfork.icu/scripts/537840/Pixiv%E5%B0%8F%E8%AF%B4%E5%B1%8F%E8%94%BD%E5%85%B3%E9%94%AE%E8%AF%8D%E4%BD%9C%E8%80%85%E6%A0%87%E7%AD%BE%EF%BC%88%E4%B8%89%E9%87%8D%E8%BF%87%E6%BB%A4%EF%BC%89%2B%E8%AE%BE%E7%BD%AE%E9%9D%A2%E6%9D%BF%2B%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA.meta.js // ==/UserScript== (function() { 'use strict'; const defaultConfig = { contentKeywords: ['无限制ai', 'ai风月'], authorKeywords: ['(', '('], tagKeywords: ['语c', '男同'] }; function getConfig() { const saved = localStorage.getItem('pixivFilterConfig'); if (saved) { try { return JSON.parse(saved); } catch (e) { console.warn('配置解析失败,使用默认值'); } } return { ...defaultConfig }; } function saveConfig(config) { localStorage.setItem('pixivFilterConfig', JSON.stringify(config)); } let config = getConfig(); GM_addStyle(` #pixivFilterBtn, #pixivConfigBtn { position: fixed; left: 10px; z-index: 9999; padding: 8px 12px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; box-shadow: 0 2px 5px rgba(0,0,0,0.2); } #pixivFilterBtn { top: 50%; } #pixivConfigBtn { top: 60%; background: #2196F3; } .hidden-by-ai-toggle { display: none !important; } #pixivConfigPanel { position: fixed; top: 120px; left: 120px; width: 400px; background: #fff; color: #333; padding: 16px; border-radius: 10px; box-shadow: 0 0 15px rgba(0,0,0,0.3); z-index: 10000; display: none; font-size: 14px; } #pixivConfigPanel textarea { width: 100%; height: 60px; margin-bottom: 20px; } #pixivConfigPanel button { margin-right: 8px; } `); // 插入设置面板 const configPanel = document.createElement('div'); configPanel.id = 'pixivConfigPanel'; configPanel.innerHTML = `
内容关键词:
作者关键词:
标签关键词:
`; document.body.appendChild(configPanel); // 插入按钮 const toggleButton = document.createElement('button'); toggleButton.id = 'pixivFilterBtn'; toggleButton.textContent = 'Hide AI'; document.body.appendChild(toggleButton); const configButton = document.createElement('button'); configButton.id = 'pixivConfigBtn'; configButton.textContent = '关键词设置'; document.body.appendChild(configButton); let isHidden = false; let configPanelVisible = false; let observedElements = []; function containsKeyword(text, keywords) { const lower = text.toLowerCase(); return keywords.some(k => lower.includes(k.toLowerCase())); } function getTagTexts(li) { const tags = []; const tagLinks = li.querySelectorAll('div > div:nth-child(2) > div > div:nth-child(3) ul a, ul span span'); tagLinks.forEach(tag => { const text = tag.textContent?.trim(); if (text) tags.push(text); }); return tags; } function findTargetElements() { return document.querySelectorAll('#__next ul li'); } function toggleElements() { observedElements.forEach(li => { const authorElem = li.querySelector('div > div:nth-child(2) > div > div:nth-child(2) > a'); const authorName = authorElem ? authorElem.textContent.trim() : ''; const contentElem = li.querySelector('div > div:nth-child(2) > div > div:nth-child(3) > div > div > div'); const contentText = contentElem ? contentElem.textContent.trim() : ''; const tags = getTagTexts(li); const matchTags = tags.some(tag => containsKeyword(tag, config.tagKeywords)); const matchAuthor = containsKeyword(authorName, config.authorKeywords); const matchContent = containsKeyword(contentText, config.contentKeywords); li.classList.toggle('hidden-by-ai-toggle', isHidden && (matchAuthor || matchContent || matchTags)); }); } function init() { observedElements = Array.from(findTargetElements()); toggleElements(); } toggleButton.addEventListener('click', function () { isHidden = !isHidden; toggleButton.textContent = isHidden ? 'Show AI' : 'Hide AI'; toggleElements(); }); configButton.addEventListener('click', function () { configPanelVisible = !configPanelVisible; configPanel.style.display = configPanelVisible ? 'block' : 'none'; }); configPanel.querySelector('#saveBtn').addEventListener('click', () => { config.contentKeywords = configPanel.querySelector('#contentInput').value.split('\n').map(s => s.trim()).filter(Boolean); config.authorKeywords = configPanel.querySelector('#authorInput').value.split('\n').map(s => s.trim()).filter(Boolean); config.tagKeywords = configPanel.querySelector('#tagInput').value.split('\n').map(s => s.trim()).filter(Boolean); saveConfig(config); init(); alert('已保存设置'); }); configPanel.querySelector('#exportBtn').addEventListener('click', () => { const exportData = JSON.stringify(config, null, 2); navigator.clipboard.writeText(exportData).then(() => alert('配置已复制到剪贴板')); }); configPanel.querySelector('#importBtn').addEventListener('click', () => { const input = prompt('请粘贴你导出的配置JSON:'); if (input) { try { const imported = JSON.parse(input); config = imported; saveConfig(config); location.reload(); } catch (e) { alert('导入失败,JSON 格式有误。'); } } }); configPanel.querySelector('#closeBtn').addEventListener('click', () => { configPanel.style.display = 'none'; configPanelVisible = false; }); const observer = new MutationObserver(() => { init(); }); observer.observe(document.body, { childList: true, subtree: true }); init(); })();