// ==UserScript== // @name QQ空间精准广告拦截(保留好友视频) // @namespace http://tampermonkey.net/ // @version 1.0 // @description 仅隐藏QQ空间中的广告动态,不误伤好友发布的视频内容 // @author You // @match https://user.qzone.qq.com/* // @match https://qzone.qq.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // 广告特征选择器(组合多个特征,提高准确性) const AD_SELECTORS = [ 'i[name="feed_data"][data-uin="0"]', // 广告的data-uin固定为0 '[data-advfeed-click-url]', // 广告特有的点击追踪属性 '[data-advfeed-pv-url]', // 广告曝光追踪属性 'div.f-vqz-ad:has(span:contains("广告"))' // 含有“广告”标签的广告容器(:contains非标准,但可后续用js检查) ]; // 由于:contains不是标准选择器,这里用函数实现包含文本检查 function hasAdSpan(element) { return element.querySelector('span')?.textContent.includes('广告'); } // 判断一个元素是否为广告(或其子元素包含广告特征) function isAdElement(element) { // 直接匹配选择器 for (const selector of AD_SELECTORS) { if (selector.includes(':contains')) { // 特殊处理:contains,手动检查 if (element.matches && element.matches('div.f-vqz-ad') && hasAdSpan(element)) { return true; } if (element.querySelector('div.f-vqz-ad') && hasAdSpan(element.querySelector('div.f-vqz-ad'))) { return true; } } else { if (element.matches && element.matches(selector)) return true; if (element.querySelector(selector)) return true; } } return false; } // 从广告特征元素向上查找整个feed项(通常是最接近的li元素) function findFeedItem(element) { // QQ空间每条动态通常是
  • ,带有data-uin或feed-item类 return element.closest('li[data-uin], li.feed-item, li.f-single, li'); } // 隐藏广告项(标记已处理,避免重复操作) function hideAdIfNeeded(node) { if (!node || node.nodeType !== Node.ELEMENT_NODE) return; // 如果节点本身或子节点包含广告特征 if (isAdElement(node)) { const feedItem = findFeedItem(node); if (feedItem && feedItem.style.display !== 'none') { feedItem.style.display = 'none'; // 可选:添加一个自定义属性标记已隐藏 feedItem.setAttribute('data-ad-hidden', 'true'); console.log('隐藏广告:', feedItem); } } else { // 如果节点是容器,检查其内部是否有广告特征元素 const adElements = node.querySelectorAll(AD_SELECTORS.join(',')); adElements.forEach(el => { // 排除已经隐藏的 const feedItem = findFeedItem(el); if (feedItem && feedItem.style.display !== 'none') { feedItem.style.display = 'none'; feedItem.setAttribute('data-ad-hidden', 'true'); console.log('隐藏广告:', feedItem); } }); } } // 初始隐藏已有的广告 function hideExistingAds() { // 组合所有可能的选择器,一次性查找 const allAdCandidates = document.querySelectorAll(AD_SELECTORS.join(',')); allAdCandidates.forEach(el => { const feedItem = findFeedItem(el); if (feedItem && feedItem.style.display !== 'none') { feedItem.style.display = 'none'; feedItem.setAttribute('data-ad-hidden', 'true'); } }); // 额外处理包含“广告”文本的f-vqz-ad(因为:contains无法在querySelector中使用) document.querySelectorAll('div.f-vqz-ad').forEach(div => { if (hasAdSpan(div)) { const feedItem = findFeedItem(div); if (feedItem && feedItem.style.display !== 'none') { feedItem.style.display = 'none'; feedItem.setAttribute('data-ad-hidden', 'true'); } } }); } // 监听动态加载的新feed function observeNewFeeds() { // QQ空间的feed列表容器通常是 id="feed_friend" 的