Greasy Fork

Greasy Fork is available in English.

匹配关键字=>屏蔽图片

按照个人喜好,在【数据】中填写关键字,用中文或者英文逗号隔开,就可以根据这些关键字,把对应的图片,替换成 replacement 的火,或者自行填写 replacement 的内容

当前为 2022-09-12 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        匹配关键字=>屏蔽图片
// @namespace   leizingyiu.net
// @version     2022.09.13
// @description 按照个人喜好,在【数据】中填写关键字,用中文或者英文逗号隔开,就可以根据这些关键字,把对应的图片,替换成 replacement 的火,或者自行填写 replacement 的内容
// @icon        https://www.leizingyiu.net/animated_favicon.gif
// @author      Leizingyiu
// @include     *://*.taobao.com/*
// @include     *://*.jd.com/*
// @include     *://*.weibo.com/*
// @include     *://weibo.com/*
// @include     *://*.smzdm.com/*
// @include     *://*.bing.com/*
// @grant       GM_setValue
// @grant       GM_getValue
// @license     GNU AGPLv3 
// ==/UserScript==
// source file name: match_and_block_by_mutation.js

/** readme.md: 

按照个人喜好,在【数据】中填写关键字,用中文或者英文逗号隔开,就可以根据这些关键字,把对应的图片视频内容,替换成 replacement 的🔥,或者自行填写 replacement 的内容  

---

请在 “ 代码 | 设置 | 数据 ” 的 “数据” 中填写关键字,前后保留英文双引号,中间用中文或者英文逗号隔开, 譬如:  
```
"牛奶,刀具,消毒液,口香糖,咖啡,巧克力,自热米饭,速溶,麦片,扫地机"
```

---

如您了解 CSS 选择器,可在 “ 代码 | 设置 | 数据 ” 的 “数据” 中,修改 选择器 ,结构如下:  
```JSON
'需要识别的域名,如 www.baidu.com 可填写 baidu.com;填写后请根据通配符规则,在 @include 新增一行添加': {
    '需要检查的包含一个图一个文的容器,填写 CSS 选择器': {
        'detect': '需要检测innerHTML的子节点,填写 CSS 选择器,需为上述容器的子节点',
        'hide': '需要屏蔽的图或者视频,填写 CSS 选择器'
    },
    '可以添加多个选择器,这个是第二个选择器': {
        'detect': '检测选择器2',
        'hide': '屏蔽选择器2'
    }
}
```  

请务必符合 JSON 规范,如使用双引号、最后一项后不可带有逗号等  

---

*/

const replacement = '🔥',
  fireSize = 1.08,
  delayTime = 1000;

function checkAndSetLocalValue(key, value, stringSplitter) {
  const checking_local_reagent = "___";
  if (GM_getValue(key, checking_local_reagent) == checking_local_reagent) {
    GM_setValue(key, value);
  } else {
    const currentValue = GM_getValue(key), backupValue = GM_getValue("备份_" + key, checking_local_reagent);
    if ((typeof stringSplitter == 'undefined') || backupValue == checking_local_reagent || typeof currentValue != 'string') {
      GM_setValue("备份_" + key, GM_getValue(key));
    } else if (typeof currentValue == 'object' && typeof backupValue == 'object') {
      const newValue = Object.assign(backupValue, currentValue);
      GM_setValue("备份_" + key, newValue);
    } else {
      let splitter = currentValue.match(stringSplitter);
      if (splitter) { splitter = splitter[0]; } else { splitter = ' '; }
      const newValueGroup = ((currentValue + splitter + backupValue).split(stringSplitter));
      const newValue = [...new Set(newValueGroup)].join(splitter);
      GM_setValue("备份_" + key, newValue);
    }
  }
}

const keywords_spliter = /[\s,,]{1,}/;

const checking_local_reagent = "___",

  local_wait_time_key = '请填写等待时间',
  default_wait_time = 5,

  local_keywords_key = "请填写需要屏蔽的关键字",
  default_block_keywords = "牛奶,刀具,消毒液,口香糖,咖啡,巧克力,自热米饭,速溶,麦片,扫地机",

  local_selectors_key = '请填写自定义选择器',
  default_web_selectors = {

    '需要识别的域名,填写后请添加 @include ': {
      '需要检查的包含一个图一个文的容器,填写 CSS selector': {
        'detect': '需要检测innerHTML的子节点,填写 CSS selector',
        'hide': '需要屏蔽的图或者视频,填写 CSS selector'
      },
      '可以添加多个选择器,这个是第二个选择器': {
        'detect': '检测选择器2',
        'hide': '屏蔽选择器2'
      },
    },

    'taobao.com': {
      '.item': { //淘宝搜索列表
        'detect': '.ctx-box',
        'hide': '.pic-box'
      },
      'li[class^=c2018],li.oneline': {
        // 淘宝搜索页右侧,以及搜索页下方
        'detect': 'a[class$=red],div[class$=line2]',
        'hide': 'div[class$=imgwrap]'
      },

      '.tb-recommend-content-item': { //淘宝首页推荐内容
        'detect': '.info-wrapper',
        'hide': '.img-wrapper'
      },
      'a.item': { //淘宝 
        'detect': 'div.item-title',
        'hide': 'div.item-image-wrap'
      },

      'ul.ald-switchable-content>li': {//天猫详情页右侧 看了又看
        'detect': 'div.img',
        'hide': 'div.img'
      },
      '.tuijian-bd-window li': { //淘宝详情页右侧 看了又看
        'detect': '.tuijian-img',
        'hide': '.tuijian-img'
      }
    },

    'jd.com': {
      '.gl-i-wrap': { //京东搜索列表
        'detect': '.p-name',
        'hide': '.p-img'
      },
      'div.mc li[id^=ad]': { //京东搜索列表 左侧推荐
        'detect': '.p-name',
        'hide': '.p-img'
      }
    },

    'weibo.com': {
      '.vue-recycle-scroller__item-view': {//微博 全部关注 
        'detect': 'article',
        'hide': 'div[class*=content_row]'
      },
      ".card-feed": { // 微博 搜索页下方信息流的卡片
        "detect": ".content",
        "hide": "div[node-type=feed_list_media_prev]"
      },
      ".WB_feed_detail": {
        "detect": ".WB_detail",
        "hide": ".WB_media_wrap"
      }
    },

    'smzdm.com': { // 什么值得买
      '.feed-row-wide': {
        'detect': '.feed-block',
        'hide': '.z-feed-img'
      }
    },

    'bing.com': {//必应图片搜索
      'ul li[data-idx]>div ': {
        'detect': '.infopt',
        'hide': '.imgpt'
      }
    }

  };


checkAndSetLocalValue(local_wait_time_key, default_wait_time);

checkAndSetLocalValue(local_keywords_key, default_block_keywords, keywords_spliter);

checkAndSetLocalValue(local_selectors_key, default_web_selectors, keywords_spliter);

const block_keywords = GM_getValue(local_keywords_key, default_block_keywords).split(keywords_spliter).filter(a => Boolean(a)),
  wordsReg = new RegExp('(' + (block_keywords.map(word => `(${word})`).join('|') + ')'), 'i'),
  webSelectors = GM_getValue(local_selectors_key, default_web_selectors),
  waitTime = GM_getValue(local_wait_time_key, default_wait_time);



let web = Object.keys(webSelectors).filter(k => window.location.host.indexOf(k) != -1);
const fireRandomClass = `fire_${String(Math.random()).replace('.', '')}`;

if (!document.querySelector(`#${fireRandomClass}`)) {
  let fireStyle = document.createElement('style');
  fireStyle.setAttribute('id', fireRandomClass);
  fireStyle.innerHTML = `
  .${fireRandomClass}{
    overflow:hidden!important;
    position:absolute!important;
    width:100%!important; height:100%!important;
    left:50%!important;top:0!important;
    transform:translate(-50%,0)!important;
    line-height:1em!important;
    display: flex;
    flex-direction: row;
    place-content: center;
    opacity:1;
  }

  .${fireRandomClass}_parent *{
    opacity:0;
    transition:opacity 0.5s ease;
  }
  .${fireRandomClass}_parent:hover *{
    opacity:1;
    transition:opacity ${waitTime}s ease;
  }

  .${fireRandomClass}_parent  .${fireRandomClass}{
    opacity:1;
    transition:opacity 0.5s ease;
  }
  .${fireRandomClass}_parent:hover .${fireRandomClass}{
    pointer-events: none;
    opacity:0;
    transition:opacity ${waitTime}s ease;
  }

  `;
  document.body.appendChild(fireStyle);
}

if (Boolean(web.length)) {
  web = web[0];

  const selectors = webSelectors[web];


  const style = document.createElement('style');
  style.innerHTML = `
  `;
  document.body.appendChild(style);


  const blockThem = function (target) {
    if (!Boolean(target)) { return }
    if (!target.querySelector(Object.keys(selectors).join(' , '))) { return }



    let checker = 'block-checked';
    let fireChecker = '__fire__'


    Object.keys(selectors).map(selector => {

      [...target.querySelectorAll(selector)].filter(dom => !dom.querySelector(`[${fireChecker}]`)).map(dom => {
        dom.setAttribute(checker, true);
        let detectDom = dom.querySelector(selectors[selector]['detect']),
          hideDom = dom.querySelector(selectors[selector]['hide']);

        if (detectDom && detectDom.innerHTML.match(wordsReg)) {

          if (hideDom) {

            let fire = document.createElement('i');
            fire.innerText = replacement;
            fire.classList.add(fireRandomClass);
            fire.style.fontSize = Number(hideDom.clientHeight) * fireSize + 'px';
            fire.style.lineHeight = '1em';
            fire.setAttribute(fireChecker, true);

            hideDom.classList.add(`${fireRandomClass}_parent`);
            hideDom.style.overflow = 'hidden';
            hideDom.style.position = 'relative';
            hideDom.appendChild(fire);

          }
        }
      });
    });
  }

  const promiseIt = function (fn) {
    return new Promise((resolve, reject) => {
      fn();
      resolve();
    })
  };

  var timer = null;

  const targetNode = document.querySelector('body'),
    config = { attributes: true, childList: true, subtree: true },
    callback = function (mutationsList, observer) {
      observer.disconnect();

      for (let mutation of mutationsList) {

        promiseIt(() => {
          blockThem(mutation.target);
        });
      }

      timer = timer ? null : setTimeout(
        () => {
          observer.disconnect();
          promiseIt(() => {
            blockThem(document.querySelector('body'));
          });
          timer = null;
          observer.observe(targetNode, config);
        }, delayTime);

    },
    observer = new MutationObserver(callback);

  observer.observe(targetNode, config);


} else { throw ('匹配关键字=>屏蔽图片: 没有此网站的设置,请检查数据') }