LoginSignup
1
1

広告にモザイクを付けるChromeの拡張機能を作ってみた

Posted at

不快な広告に悩まされてませんか?

 最近、ネットを見ていると「不快な広告」を散見します。筆者はちょっとHなアプリの紹介くらいなら許容範囲なのですが、暴力的な内容のモノは本当にNGなんですよね。あと脳破壊を示唆する漫画とか。
 最初こそ「この広告を表示しない」とオプトアウト設定していたのですが、そういう措置をとれない広告もありますし、なんなら似たような別の広告が表示されることはあり得ます。

「AdBlockでも入れるか? いやでも、それは申し訳ないし……。まあ、我慢しよう」

 そう思っていたのですが、ある時、筆者の堪忍袋の緒が切れる出来事が起きました。それは防虫剤の広告だったと思うのですが、寝ている人の周りにリアルなGが無数に集まっているデザインだったんです。もうね、思わず「うぎゃ!」と叫んでしまいました。なんでこんな広告を世に出してしまったのか理解に苦しみます。

「決めた、AdBlockerを入れよう! ……でもなあ、AdBlockerを入れたらサイト主に検知されるって聞くし……」

 悩んだ末に私は「広告をブロックはせず、モザイクをかけるだけ」という拡張機能を作ることに決めました!

拡張機能の作り方

 拡張機能を作るのは簡単です! まずフォルダを作ります。その中にmanifest.jsonとcontent.jsというファイルを作ります。manifest.jsonに以下のように記述します。

{
  "name": "AdMosaic",
  "version": "1.0.0",
  "manifest_version": 3,
  "description": "Add mosaic to ads",
  "content_scripts": [{
    "matches": ["*://*/*"],
    "js": [
      "content.js"
    ]
  }]
}

name:拡張機能の名前
version:バージョン
manifest_version:3にする
description:拡張機能の説明
content_scripts:拡張機能の設定。配列。
matches:拡張機能が有効になるURL。今回は全サイトで有効化するから*://*/*としている。
js:プログラムファイル名。今回はcontent.js

あとはchrome://extensions/にアクセス、デベロッパー モードをオンにして「パッケージ化されていない拡張機能を読み込む」をクリックしたら追加できます。

 もはや、メモ帳だけでも作れてしまうレベルで簡単ですね!!

広告の検出

 広告は画像、もしくはiframeで実装されていることが多いみたいです。(たぶん)
 そこでまずはiframe要素をすべて取得するコードを書きます。

const iframes = document.getElementsByTagName("iframe");
for(const iframe of iframes){
	//広告か判断するコード
}

 もちろん、広告以外にモザイクをかけてしまってはいけないので、広告かどうかを検知できるようにします。今回はtitleが存在するなら、それがadvertisementかadかad contentである物にモザイクをかけてみようと思います。

let title = iframe.getAttribute("title");
if(title !== null){
	title = title.toLowerCase(); //すべて小文字にする
	if(title == "advertisement" || title == "ad" || title == "ad content"){
		hide(iframe); //広告にモザイクをかける
	}
}

 あとは広告にモザイクをかける「hide関数」を実装するだけです。

モザイクをかける

 cssでモザイク(正確にはブラー)をかけるには以下のように書きます。

iframe.ad{
    filter:blur(8px);
}

 これをjsから設定すればいいわけですね!
 コードは以下の通り。

function hide(ad){
	ad.style.setProperty("opacity", "0.15", "important");
	ad.style.setProperty("filter", "blur(8px)", "important");
}

 広告を薄くして(opacityを0.15に設定)、ブラーフィルタをかけます(filterをblur(8px)に設定)。
 なお、ad.style.opacity="0.15"だと消えないことがあるので、このようにimportant属性を付与して確実に半透明処理が行われるようにします。

以上機処理を0.1秒ごとに行う

 広告の中には、ページ読み込み完了時点ではまだ読み込まれておらず、時間差で表示されるものがあります。そこで、「広告を検出したらブラーをかける」という処理を一定時間ごとに行う必要があります。ある関数を一定時間ごとに行うにはsetIntervalを使います。

function hideAds(){...中略...}
setInterval(hideAds, 100);//100msごとに関数を呼び出す。

全ソースコード

function hide(ad){
	ad.style.setProperty("opacity", "0.15", "important");
	ad.style.setProperty("filter", "blur(8px)", "important");
}

function hideAds(){
	const imgs = document.getElementsByTagName("img");
	for(const img of imgs){
		if(img.alt == "Advertisement" || img.classList.contains("img_ad")){
			hide(img);
		}
	}
	const iframes = document.getElementsByTagName("iframe");
	for(const iframe of iframes){
		let id = iframe.getAttribute("id");
		if(id !== null){
			id = id.toLowerCase();
			if(id.startsWith("aswift")){
				hide(iframe);
				continue;
			}
		}
		let title = iframe.getAttribute("title");
		if(title !== null){
			title = title.toLowerCase();
			if(title == "advertisement" || title == "ad" || title == "ad content"){
				hide(iframe);
				continue;
			}
		}
		let aria_label = iframe.getAttribute("aria-label");
		if(aria_label !== null){
			aria_label = aria_label.toLowerCase();
			if(aria_label == "advertisement" || aria_label == "ad" || aria_label == "ad content"){
				hide(iframe);
				continue;
			}
		}
	}
}
hideAds();
setInterval(hideAds, 100);
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1