広告削除方法模索(CSSで攻める)
追記以下のエントリーはこれを知らなかった。。
GM_addStyle(<><![CDATA[ #sub {display:none !important;} td[class~="turnup"]:hover {background:pink !important;} ]]></>);
これまで個別のページごとに広告を削除するスクリプトは数多くあったが、
ここではテンプレート化して汎用性を高めたものを考える。
脱マシンガン方式
効率よく広告を消すgreasemonkeyスクリプトを考える (cherenkov.vox.com)
今までは削除したいやつをdocument.evaluateで大まかに拾ってきて、
一個一個リスト照会して削除をしていた。
今回は気持ちを切り替えてCSSで攻めてみた。
どういうもの?
最近のブログはタイトルと記事の間に広告が挟まれたりして、ユーザにとって不愉快なスクロールを強いることに疑問を感じた。近頃の広告はid要素やclass要素で丁寧にマーキングされている。そこで、そのマーキングを利用して効率よく広告を削除できるのではないかと考えた。
ユーザは消したい広告にマークされているid要素、class要素、name要素のいずれかをリストに追加すればいい。
Adblockよりも優れている点
- Adblockは付属のブロック要素一覧が使いにくい。
→うちの方法ではユーザがfirebugを使いながらリストに加える情報を集める。
→うちの方法ではテキストベースの広告などもidかclassかname要素が設定されていれば簡単に削除対象になる。
usercontent.cssよりも優れている点
さっそくデモ
ブックマークレットを用意しました。
gigazineで試してみてください トップページでも個別の記事でも広告を削除します。
今回のデモで消したい広告は以下の三種類。
- id属性が 'af8b0702'
- class属性が 'jobboard_blog_parts'
- name属性が 'google_ads_frame'
javascript:(function(){function stringList(idList,classList,nameList){for(var i=0;i<idList.length;i++){idList[i]='#'+idList[i]+'{display:none!important;}';}for(var i=0;i<classList.length;i++){classList[i]='.'+classList[i]+'{display:none!important;}';}for(var i=0;i<nameList.length;i++){nameList[i]='[name="'+nameList[i]+'"]{display:none!important;}';}var removeList=idList.concat(classList,nameList).join('').toString();return removeList;}function addGlobalStyle(css){var head=document.getElementsByTagName('head')[0];if(!head){return;}var style=document.createElement('style');style.type='text/css';style.innerHTML=css;head.appendChild(style);}var idList=['af8b0702'];var classList=['jobboard_blog_parts'];var nameList=['google_ads_frame'];var removeList=stringList(idList,classList,nameList);addGlobalStyle(removeList);})();
主なソースコード(ここはまだ見るだけ)
(function(){ function stringList(idList,classList,nameList){ for(var i=0;i<idList.length;i++){ idList[i] = '#'+idList[i]+'{display:none!important;}'; } for(var i=0;i<classList.length;i++){ classList[i] = '.'+classList[i]+'{display:none!important;}'; } for(var i=0;i<nameList.length;i++){ nameList[i] = '[name="'+nameList[i]+'"]{display:none!important;}'; } var removeList = idList.concat(classList,nameList).join('').toString(); return removeList; } function addGlobalStyle(css){ var head, style; head = document.getElementsByTagName('head')[0]; if(!head){ return; } style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); } var idList = ['af8b0702']; var classList = ['jobboard_blog_parts']; var nameList = ['google_ads_frame']; var removeList = stringList(idList,classList,nameList); addGlobalStyle(removeList); })();
仕組み
注意
var idList = ['ad_01','ad_02']; var classList = ['']; ← var nameList = ['google_ads_frame']; var removeList = stringList(idList,classList,nameList); addGlobalStyle(removeList);
リストに入れるものがなくても上記のように、空でも記述しておかないといけない仕様。
日々の管理
- たまに広告のマーキングが変ってないかチェック。リストのものが存在してなくても問題ない。
- リストは以下のように空になっていても、空のCSSを設定し空振りするだけなのであまり気にしなくてもいい。(リスト追加するときにコンマ打つのがめんどうで書き溜めてもよい)
var idList = new Array('','','','','resources','bp4');
ついでに広めたいこと(メイン)
greasemonkeyユーザなら知っていて当然かもしれないけど、一応紹介したいことがある。
便利なスクリプトをどんどん追加していって数が多くなり、
管理が面倒になってないだろうか。
数行のコードのためにわざわざ新規追加するのに疑問を感じたはず。
それを是非まとめてほしい。というかまとめてスッキリした。
どうやってまとめるの?
// @include http://japanese.engadget.com/* // @include http://www.nicovideo.jp/watch/* // @include http://dictionary.goo.ne.jp/
のようにドメインでフィルターをして
if (location.href.match(/japanese.engadget.com/)) {url = 'engadget'} else if (location.href.match(/nicovideo.jp\/watch/)) {url = 'nicovideo'} else if (location.href.match(/dictionary.goo.ne.jp/)) {url = 'goo_dictionary'} switch (url){ case 'engadget': break;
のようにswitchして、ページごとに管理する。
注意点
@includeに http://* とか https://*を設定しないのは、セキュリティ面と管理しやすさを考えた。
ページを追加するときは、毎回ユーザスクリプトの管理画面で実行させたいページを追加する必要がある。
スクリプト中の@includeに書き忘れても、動作に影響はないが忘れずに追加することを勧める。
お試しインストール
なにこれ?
greasemonkeyスクリプト。
個人的によくつかうページで実際に使っているサンプルを用意した。
上の方で作った広告削除機能を盛り込みつつ、入門者のテンプレートにもなるようにしたつもり。
見やすくインデントしたつもり。
公開しても恥ずかしくないようにしたつもり。
で結局どう使うの?
お試しインストールのソースコードを参考に説明します。
- firefox+greasemonkeyを導入しお試しインストールを済ます。
- スクリプト(例えば広告を削除したい)を実行したいページを見つける。
- firefoxの右下にある猿のアイコンを右クリックなりしてメニューを表示してユーザスクリプトの管理画面を開き、このスクリプトを選択しユーザスクリプトを実行するページに対象のURLを登録する。
- スクリプト上の// @includeにも登録しておく。
- 対象のURLに含まれるユニークな文字列を以下の部分に登録する。
else if (location.href.match(/ココ/)) {url = 'ココ'}
主な効果を列挙
はて?
どんどんつっこんでください。いまはこれが正しいと思い込んでるから。
caseごと無名関数で包んでるけど効果あんの?
Stylishでやったら? 導入めんどい><