新赚吧

 找回密码
 立即注册
查看: 508|回复: 1

[分享转发] 【油猴脚本】微博广告与推荐内容屏蔽工具--来自52PJ

[复制链接]
[OSE] 发表于 2026-1-5 08:54 | 显示全部楼层 |阅读模式
本帖最后由 OSE 于 2026-1-5 08:54 编辑



【油猴脚本】微博广告与推荐内容屏蔽工具
https://www.52pojie.cn/thread-2057844-1-1.html
(出处: 吾爱破解论坛)



  1. // ==UserScript==
  2. // @name 微博广告与推荐内容屏蔽工具(优化版)
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.0
  5. // @description 高性能屏蔽微博广告、推荐内容及侧栏推荐,支持配置和调试
  6. // @author Chief Programmer
  7. // @match https://weibo.com/*
  8. // @match https://*.weibo.com/*
  9. // [url=home.php?mod=space&uid=111117]@icon[/url] https://weibo.com/favicon.ico
  10. // @grant GM_addStyle
  11. // @grant GM_getValue
  12. // @grant GM_setValue
  13. // @grant GM_registerMenuCommand
  14. // @license MIT
  15. // ==/UserScript==

  16. (function() {
  17. \\\'use strict\\\';

  18. // ================== 配置管理 ==================
  19. const CONFIG = {
  20. // 功能开关
  21. blockAds: GM_getValue(\\\'blockAds\\\', true),
  22. blockSidebar: GM_getValue(\\\'blockSidebar\\\', true),
  23. blockImages: GM_getValue(\\\'blockImages\\\', true),
  24. debugMode: GM_getValue(\\\'debugMode\\\', false),

  25. // 屏蔽关键词(可扩展)
  26. blockKeywords: GM_getValue(\\\'blockKeywords\\\', [\\\'荐读\\\', \\\'推荐\\\', \\\'公益\\\', \\\'广告\\\']),

  27. // 性能配置
  28. observerDelay: 50, // MutationObserver 延迟(ms)
  29. scrollThrottle: 200, // 滚动节流时间(ms)
  30. batchSize: 10, // 批处理大小

  31. // 选择器配置(便于维护)
  32. selectors: {
  33. feedItem: \\\'article.Feed_wrap_3v9LH.Feed_normal_12A98\\\',
  34. tagContainer: \\\'.wbpro-tag-c2 div\\\',
  35. sidebarTitle: \\\'div.wbpro-side-tit .f16.fm.cla\\\',
  36. sidebarParent: \\\'.wbpro-side\\\'
  37. }
  38. };

  39. // ================== 工具函数 ==================

  40. /**
  41. * 节流函数
  42. */
  43. function throttle(func, limit) {
  44. let inThrottle;
  45. return function(...args) {
  46. if (!inThrottle) {
  47. func.apply(this, args);
  48. inThrottle = true;
  49. setTimeout(() => inThrottle = false, limit);
  50. }
  51. };
  52. }

  53. /**
  54. * 防抖函数
  55. */
  56. function debounce(func, delay) {
  57. let timeoutId;
  58. return function(...args) {
  59. clearTimeout(timeoutId);
  60. timeoutId = setTimeout(() => func.apply(this, args), delay);
  61. };
  62. }

  63. /**
  64. * 日志输出(支持调试模式)
  65. */
  66. function log(message, type = \\\'info\\\', data = null) {
  67. if (!CONFIG.debugMode && type !== \\\'error\\\') return;

  68. const prefix = \\\'【微博内容屏蔽 v2.0】\\\';
  69. const timestamp = new Date().toLocaleTimeString();

  70. switch(type) {
  71. case \\\'error\\\':
  72. console.error(`${prefix}[${timestamp}]`, message, data || \\\'\\\');
  73. break;
  74. case \\\'warn\\\':
  75. console.warn(`${prefix}[${timestamp}]`, message, data || \\\'\\\');
  76. break;
  77. case \\\'success\\\':
  78. console.log(`%c${prefix}[${timestamp}] ${message}`, \\\'color: green\\\', data || \\\'\\\');
  79. break;
  80. default:
  81. console.log(`${prefix}[${timestamp}]`, message, data || \\\'\\\');
  82. }
  83. }

  84. /**
  85. * 性能监控
  86. */
  87. const performanceMonitor = {
  88. stats: {
  89. blockedItems: 0,
  90. blockedImages: 0,
  91. blockedSidebars: 0,
  92. executionTime: 0
  93. },

  94. start() {
  95. return performance.now();
  96. },

  97. end(startTime, operation) {
  98. const duration = performance.now() - startTime;
  99. this.stats.executionTime += duration;
  100. if (CONFIG.debugMode) {
  101. log(`${operation} 耗时: ${duration.toFixed(2)}ms`, \\\'info\\\');
  102. }
  103. },

  104. report() {
  105. log(\\\'性能统计\\\', \\\'success\\\', this.stats);
  106. }
  107. };

  108. // ================== 核心功能 ==================

  109. /**
  110. * 注入优化的CSS样式
  111. */
  112. function injectStyles() {
  113. const styles = `
  114. /* 屏蔽推荐图片 - 使用更精确的选择器 */
  115. ${CONFIG.blockImages ? `
  116. img[src*=\\"shuakong.jpg\\"],
  117. img[src*=\\"upload/1014/739/2023/08/03/shuakong.jpg\\"] {
  118. display: none !important;
  119. visibility: hidden !important;
  120. opacity: 0 !important;
  121. width: 0 !important;
  122. height: 0 !important;
  123. }
  124. ` : \\\'\\\'}

  125. /* 隐藏标记的广告容器 - 添加平滑过渡 */
  126. .weibo-ad-blocked {
  127. display: none !important;
  128. opacity: 0 !important;
  129. transition: opacity 0.3s ease-out;
  130. pointer-events: none !important;
  131. }

  132. /* 调试模式高亮 */
  133. ${CONFIG.debugMode ? `
  134. .weibo-ad-blocked {
  135. display: block !important;
  136. opacity: 0.3 !important;
  137. border: 2px dashed red !important;
  138. background: rgba(255,0,0,0.1) !important;
  139. }
  140. ` : \\\'\\\'}
  141. `;

  142. GM_addStyle(styles);
  143. log(\\\'样式注入成功\\\', \\\'success\\\');
  144. }

  145. /**
  146. * 批量处理信息流广告
  147. */
  148. function processFeedItems() {
  149. if (!CONFIG.blockAds) return;

  150. const startTime = performanceMonitor.start();
  151. const feedItems = document.querySelectorAll(
  152. `${CONFIG.selectors.feedItem}:not([data-processed=\\"true\\"])`
  153. );

  154. let blockedCount = 0;
  155. const itemsToProcess = Array.from(feedItems).slice(0, CONFIG.batchSize);

  156. itemsToProcess.forEach(container => {
  157. try {
  158. // 标记为已处理
  159. container.setAttribute(\\\'data-processed\\\', \\\'true\\\');

  160. const tagElement = container.querySelector(CONFIG.selectors.tagContainer);
  161. if (!tagElement) return;

  162. const text = tagElement.textContent.trim();
  163. const shouldBlock = CONFIG.blockKeywords.some(keyword =>
  164. text.includes(keyword)
  165. );

  166. if (shouldBlock) {
  167. container.classList.add(\\\'weibo-ad-blocked\\\');
  168. blockedCount++;
  169. performanceMonitor.stats.blockedItems++;
  170. log(`屏蔽信息流: \\"${text}\\"`, \\\'success\\\');
  171. }
  172. } catch (error) {
  173. log(\\\'处理信息流条目时出错\\\', \\\'error\\\', error);
  174. }
  175. });

  176. if (blockedCount > 0) {
  177. log(`本次屏蔽 ${blockedCount} 条内容`, \\\'info\\\');
  178. }

  179. performanceMonitor.end(startTime, \\\'处理信息流\\\');

  180. // 如果还有未处理的元素,继续处理
  181. if (feedItems.length > CONFIG.batchSize) {
  182. setTimeout(() => processFeedItems(), 50);
  183. }
  184. }

  185. /**
  186. * 屏蔽侧栏推荐(优化版)
  187. */
  188. function hideSidebarRecommendations() {
  189. if (!CONFIG.blockSidebar) return;

  190. const startTime = performanceMonitor.start();

  191. try {
  192. // 使用更高效的查询方式
  193. const sidebars = document.querySelectorAll(
  194. `${CONFIG.selectors.sidebarParent}:not([data-sidebar-processed=\\"true\\"])`
  195. );

  196. sidebars.forEach(sidebar => {
  197. const title = sidebar.querySelector(CONFIG.selectors.sidebarTitle);
  198. if (title && title.textContent.trim() === \\\'你可能感兴趣的人\\\') {
  199. sidebar.style.display = \\\'none\\\';
  200. sidebar.setAttribute(\\\'data-sidebar-processed\\\', \\\'true\\\');
  201. performanceMonitor.stats.blockedSidebars++;
  202. log(\\\'屏蔽侧栏推荐\\\', \\\'success\\\');
  203. }
  204. });
  205. } catch (error) {
  206. log(\\\'处理侧栏推荐时出错\\\', \\\'error\\\', error);
  207. }

  208. performanceMonitor.end(startTime, \\\'处理侧栏\\\');
  209. }

  210. /**
  211. * 主处理函数(防抖优化)
  212. */
  213. const processContent = debounce(() => {
  214. processFeedItems();
  215. hideSidebarRecommendations();
  216. }, CONFIG.observerDelay);

  217. // ================== 初始化 ==================

  218. /**
  219. * 设置 MutationObserver(优化版)
  220. */
  221. function setupObserver() {
  222. let pendingMutations = [];
  223. let rafId = null;

  224. const processMutations = () => {
  225. if (pendingMutations.length > 0) {
  226. processContent();
  227. pendingMutations = [];
  228. }
  229. rafId = null;
  230. };

  231. const observer = new MutationObserver((mutations) => {
  232. // 过滤无关的变化
  233. const relevantMutations = mutations.filter(mutation => {
  234. // 忽略属性变化和我们自己的修改
  235. if (mutation.type === \\\'attributes\\\' &&
  236. mutation.attributeName === \\\'data-processed\\\') {
  237. return false;
  238. }
  239. // 忽略文本节点变化
  240. if (mutation.type === \\\'characterData\\\') {
  241. return false;
  242. }
  243. return true;
  244. });

  245. if (relevantMutations.length > 0) {
  246. pendingMutations.push(...relevantMutations);

  247. // 使用 requestAnimationFrame 优化
  248. if (!rafId) {
  249. rafId = requestAnimationFrame(processMutations);
  250. }
  251. }
  252. });

  253. observer.observe(document.body, {
  254. childList: true,
  255. subtree: true,
  256. attributes: false, // 减少不必要的属性监听
  257. characterData: false
  258. });

  259. log(\\\'DOM 监听器已启动\\\', \\\'success\\\');
  260. return observer;
  261. }

  262. /**
  263. * 设置滚动监听(节流优化)
  264. */
  265. function setupScrollListener() {
  266. const throttledProcess = throttle(() => {
  267. processContent();
  268. }, CONFIG.scrollThrottle);

  269. window.addEventListener(\\\'scroll\\\', throttledProcess, { passive: true });
  270. log(\\\'滚动监听器已启动\\\', \\\'success\\\');
  271. }

  272. /**
  273. * 注册用户菜单命令
  274. */
  275. function setupMenuCommands() {
  276. GM_registerMenuCommand(\\\'切换调试模式\\\', () => {
  277. CONFIG.debugMode = !CONFIG.debugMode;
  278. GM_setValue(\\\'debugMode\\\', CONFIG.debugMode);
  279. alert(`调试模式已${CONFIG.debugMode ? \\\'开启\\\' : \\\'关闭\\\'}`);
  280. location.reload();
  281. });

  282. GM_registerMenuCommand(\\\'查看统计信息\\\', () => {
  283. performanceMonitor.report();
  284. alert(`已屏蔽内容统计:\\\\n` +
  285. `- 信息流条目: ${performanceMonitor.stats.blockedItems}\\\\n` +
  286. `- 侧栏推荐: ${performanceMonitor.stats.blockedSidebars}\\\\n` +
  287. `- 总执行时间: ${performanceMonitor.stats.executionTime.toFixed(2)}ms`);
  288. });

  289. GM_registerMenuCommand(\\\'配置屏蔽关键词\\\', () => {
  290. const currentKeywords = CONFIG.blockKeywords.join(\\\',\\\');
  291. const newKeywords = prompt(\\\'请输入屏蔽关键词(逗号分隔):\\\', currentKeywords);
  292. if (newKeywords !== null) {
  293. CONFIG.blockKeywords = newKeywords.split(\\\',\\\').map(k => k.trim());
  294. GM_setValue(\\\'blockKeywords\\\', CONFIG.blockKeywords);
  295. alert(\\\'关键词已更新,页面将重新加载\\\');
  296. location.reload();
  297. }
  298. });
  299. }

  300. /**
  301. * 初始化函数
  302. */
  303. function init() {
  304. try {
  305. log(\\\'开始初始化...\\\', \\\'info\\\');

  306. // 1. 注入样式
  307. injectStyles();

  308. // 2. 初始处理
  309. setTimeout(() => {
  310. processContent();
  311. }, 500);

  312. // 3. 设置监听器
  313. setupObserver();
  314. setupScrollListener();

  315. // 4. 注册菜单
  316. setupMenuCommands();

  317. // 5. 页面可见性变化时处理
  318. document.addEventListener(\\\'visibilitychange\\\', () => {
  319. if (!document.hidden) {
  320. processContent();
  321. }
  322. });

  323. log(\\\'初始化完成!\\\', \\\'success\\\');

  324. // 定期报告(调试模式)
  325. if (CONFIG.debugMode) {
  326. setInterval(() => {
  327. performanceMonitor.report();
  328. }, 30000);
  329. }

  330. } catch (error) {
  331. log(\\\'初始化失败\\\', \\\'error\\\', error);
  332. }
  333. }

  334. // ================== 启动脚本 ==================
  335. if (document.readyState === \\\'loading\\\') {
  336. document.addEventListener(\\\'DOMContentLoaded\\\', init);
  337. } else {
  338. init();
  339. }

  340. })();
复制代码
回复

使用道具 举报

 楼主| [OSE] 发表于 2026-1-5 08:56 | 显示全部楼层
其实药方脚本好用,不知为啥 这几天失效了
回复 支持 反对

使用道具 举报

温馨提示:如果需要上传图片,可以点击右边的高级模式试一下!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

联系站长|小黑屋|新赚吧 ( 粤ICP备12087818号 )

GMT+8, 2026-1-27 21:01 , Processed in 0.108470 second(s), 11 queries , Redis On.

Powered by Discuz!

Copyright © 2021-2023 见闻鹿科技 .

快速回复 返回顶部 返回列表