DIY:使用扩展程序在Chrome下干掉各种恶心的广告

来源:互联网 发布:数据库原理视频教程 编辑:程序博客网 时间:2024/05/22 02:51

注:这是一篇简单的DIY记录,技术含量较低~

-----------------------我是分割线╮(╯▽╰)╭-----------------------

最近百度查东西的时候,经常会看到各种恶心的广告,以下面这货为代表:


这货不断变换的恶心造型真是醉了(已打马赛克),我实在忍不住要净化一下视线了。

首先想到的是有什么屏蔽掉图片的东西能干掉这种广告,去Chrome扩展商店一看,有很多这种类型的插件,例如下面这款:

.

这个工具看起来不错,所有较大的图片都会被简单纹理的纯色图片替换。装完以后发现若干问题:①所有图片都被替换了 ②对上面的恶心广告根本无效!

于是怒按F12 查看了百♂度推广元素。

<embed pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="opaque" quality="High" name="" src="http://ubmcmm.baidustatic.com/media/v1/0f000F_qSMbM-c5uLIlBzf.swf" width="120" height="270" scale="exactfit" allowfullscreen="" allowscriptaccess="" allownetworking="" flashvars="">
原来是个flash= =||
那么能不能对刚才那个插件修改一下达到阻止flash广告的目的呢?当然可以。

Chrome的扩展插件的组成非常简单:几个Html(绘制弹出窗口和设置界面等)、几个Js(具体工作代码都在这)、一个json(插件的说明文件,告诉Chrome扩展名字、版本、图标、主体是哪个js、设置界面是哪个html等)。

那么刚刚那个插件的屏蔽原理是什么呢?简单的说,就是插件向Chrome注册一些信息,然后当Chrome载入每个页面的DOM树之前,都执行一遍插件的指定js代码,然后在该代码中,插件再注册一些事件的监听器(例如window对象的DOMContentLoaded事件),当页面DOM载入之后,插件遍历一遍DOM树的每个元素,在每个元素上执行屏蔽逻辑,例如把IMG元素全都替换成上图中的纯色图片。

那么,我们修改Wizmage Image Blocker的思路基本上就有了:找到插件处理每个DOM元素的那部分代码,增加对于embed元素的屏蔽功能,由于除了这种广告,其他图片我并不想屏蔽,所以需要在屏蔽图片上增加一些限制,改成只屏蔽我们想屏蔽的,同理embed元素也是这样,插件的其他部分基本不用动。下面记录下修改过程:

-----------------------我是分割线╮(╯▽╰)╭-----------------------

先在Chrome中下载Wizmage Image Blocker 插件(版本2.5.3),然后进入:

     C:\Users\你的用户名\AppData\Local\Google\Chrome\User Data\Default\Extensions

中查看,会有很多乱码目录,这里每个目录是一个Chrome插件,通过每个目录里的图片找到Wizmage对应的目录,把整个目录拷贝到另一个地方,删除里面的_metadata目录。

显然可以看出各个文件的作用:

manifest.json 插件的说明文件,主要是修改一下插件名称、描述,删除“key”字段,其他部分不用动

options.htm 插件设置界面;

popup.htm 点击插件图标弹出窗口界面;

options.js 设置界面js;

jquery.min.js 一个小的jQuery(所以说安这种插件会小幅影响页面载入速度);

background.js 插件“后台页面”实现,主要用来保存读取设置;

js.js  插件的"内容脚本"(Content Scripts)实现,也就是上面说的每个页面载入的时候执行的代码,本次DIY的主要部分。

打开js.js文件:

1、首先看到@2-15行是各种变量定义,这里注意到有tagList,估计是插件处理的元素标签类型列表。

2、看到@18 : 

window.addEventListener('DOMContentLoaded', function () { contentLoaded = true; });
3、当DOM树载入后,将contentLoaded设为true,查下哪里用到了contentLoaded

chrome.runtime.sendMessage({ r: 'getSettings' }, function (s) {    settings = s;    //if is active - go    if (settings && !settings.isExcluded && !settings.isExcludedForTab && !settings.isPaused && !settings.isPausedForTab) {        //change icon        chrome.runtime.sendMessage({ r: 'setColorIcon', toggle: true });        //do main window        DoWin(window, contentLoaded);    }});
看到@28中有 DoWin(window, contentLoaded);,估计这段代码意思是和background.js通信,调用getSettings,当设置返回后,判断目前是否开启屏蔽功能,如果是的话,设置Icon,同时对window对象DoWin,可以推测DoWin是对window进行屏蔽操作,跟进。

4、@50 DoWin函数

function DoWin(win, winContentLoaded) {       .......    //start, or register start    if (winContentLoaded)        Start();    else        win.addEventListener('DOMContentLoaded', Start);       .......
哦?这里用到了contentLoaded,并且调用了Start()函数,跟到Start里

5、@103 Start()

    function Start() {           ........        DoElements(doc.body, false);           ........
同理DoWin,DoElements应该是对元素进行处理的,后面同理

@159  可以看到DoElements大概是通过上面的tagList查找了当前DOM元素下面每个子节点,然后对每个元素进行DoElement,这里使用了call,也就是DoElement中的this被替换成子节点all[i]。

    function DoElements(el, includeEl) {        if (includeEl)            DoElement.call(el);        var all = el.querySelectorAll(tagListCSS);        for (var i = 0, max = all.length; i < max; i++)            DoElement.call(all[i]);    }
跟进到DoElement @180:

    function DoElement() {          .......        if (this.tagName != 'IMG') {          .......                AddToList(this);          .......        } else {            AddToList(this);          .......        }    }
关键部分来了,这里具体负责屏蔽操作,大概结构如上,先判断当前元素的标签是不是IMG,是或不是,都将它加入一个list中,这个list是“当前页面中已被插件屏蔽的图片列表”,为什么要判断tag==IMG呢,没仔细看,大概是不同元素中出现的图片的处理方法不一样。

那么现在可以开始动手修改了:

js.js开头变量区域,增加两个变量:

myBlockList = ['kejet','baidu'],//src属性中含有这些字符串的flash将被屏蔽myImgBlockList = [ ];////src属性中含有这些字符串的img将被屏蔽

随便找个地方加个:

function IsSrcInList(src,list){for ( var i in list ){if ( src.indexOf(list[i]) >= 0 )return true;}return false;}
到DoElement函数中,把原先if ( this.tagName != "IMG" ) {  partA } else { partB }的结构改成下面的:

if ( this.tagName.toUpperCase()=="EMBED" ){if ( IsSrcInList(this.src,myBlockList)==true ){var p = this.parentNode;this.remove();}}else if (this.tagName == 'IMG' && IsSrcInList(this.src,myImgBlockList)==true){...[partB]...}
上面的修改增加了对embed标签的判断,如果是embed标签,并且src属性中含有禁止出现的关键字(例如“baidu”),那么就删除这个元素;如果是图片,并且图片的src属性中出现了禁止关键字,则执行原先插件的逻辑,屏蔽掉该图片。这样修改保证了不会屏蔽掉所有图片,同时加入了flash的屏蔽,并且可以自定义关键字~

-----------------------我是分割线╮(╯▽╰)╭-----------------------

ok,代码部分到此为止,把文件保存,在Chrome的扩展管理chrome://extensions/ 页面中,勾选“开发者模式”,点击“加载正在开发的扩展”,选择刚才拷贝出来的目录,安装运行。效果如下:

DIY完毕\(^o^)/

0 0
原创粉丝点击