Contents
コンテンツブロッカーとは
コンテンツブロッカーとはiOS9で実装されたデフォルトブラウザであるSafariで広告などをブロックする公式の仕組みのこと。
コンテンツブロッカーにはおそらく三種類あり「デフォルト方式」「VPN方式」「DNS方式」があります。
コンテンツブロッカーの機能を有するアプリのつくりかたですが、下記サイトが非常に参考になりました。ありがとうございます。

デフォルト方式
blockerList.jsonでブロックするルールを書いていきます。
ブロックの種類はblockでドメイン自体のアクセスをブロックするものと、css-display-noneでkンテンツを非表示にするものがあります。
blockであればドメイン自体にアクセスしないので無駄なJavascriptなどのロードがなくなり、表示の高速化が期待できます。
それに対してcss-display-noneは通信自体は行なうがコンテンツを見えないようにするだけなので、これを使うだけでは高速化はできません。ただ、ブロックしたコンテンツの表示領域に無意味な空白が残ってしまうことがあるので、これをブロックするために使うと良いかもしれません。
VPN方式
自分自身をVPNサーバとして中継し、中継時のルールとして独自のHostsをかませることで広告サーバへのアクセスをブロックする方法です。
Safariだけでなく一部のアプリのアプリ内広告もブロックできますが、柔軟なフィルタが書けないのが難点かもしれません。
DNS方式
よくわかっていないが、基本の考え方はVPN方式と同じはず。
毎回サーバへのアクセスを必要とせず、キャッシュとして持っているためにバッテリー持ちはいいかもしれない。
最近のコンテンツブロッカーはこの機能を搭載しているものも多い。
今回はデフォルト方式でやってみた
今回はまあ「初めてましての方はこっちからやればいいか」ということでデフォルトのSafari内の広告だけをブロックする方法を試しました。
で、Safari内の広告ブロックは非常に単純で、 blockerList.jsonにフィルタリングのルールを書いていくだけです、簡単ですね。
ルールの書き方については英文ですが、上の参考サイトが非常にわかりやすいです。
全部試すのはまあめんどくさくて、個人的には基本的な広告だけブロックできたらいいやと思ったのでとりあえず書いてみることにしました。
Google AdSenseをブロックしよう
Google AdSenseを配信しているサーバ名はtpc.googlesyndication.comなのでここをブロックするように書けばOKです。
[ { "action": { "type": "block" }, "trigger": { "url-filter": "tpc\\.googlesyndication\\.com" } } ]
このように書くことでドメイン自体(サブドメイン含む?)へのアクセスをブロックすることができます。
スポンサードリンクを非表示にしよう
ドメインブロックで広告のロードは防ぐことができますが、ウェブサイト自体は広告を読めたという前提で「ここに広告がありますよ」という感じでサイトを表示しているわけです。
なので、なにもないのに「スポンサードリンク」などと表示されてちょっと気持ち悪いわけですね。
{ "action": { "type": "css-display-none", "selector": "[class^='ad-'], [class^='ad_']" }, "trigger": { "url-filter": "\\.*" } },
そんなときは上のコードでCSSを非表示にしてしまいましょう。
CSSのセレクタは正規表現が使えないのですが、擬似的に似たような書き方をすることができます。
例えば、上のコードは全てのドメインにおいて「クラス名がad-またはad_から始まる要素を非表示にする」を意味しています。
めったにないとは思いますが、広告ではないのにこれらのフィルタリングにマッチしてしまう場合があります。
そういうときはunless-domainなどでフィルタリング対象外であることを明記するなどして対応してください。
blockerList.jsonの作成方法
import json blockerList = [] with open("hosts.txt", mode="r") as f: for host in f: if "//" not in host and host != "\n": domain = host.strip().replace(".", "\\.") blockerList.append({"action": {"type": "block"}, "trigger" : {"url-filter": domain}}) with open("selector.txt", mode="r") as f: selectors = [] for css in f: if "//" in css: # Domain Name domain = css.replace("//", "").strip().replace(".", "\\.") else: if css != "\n": selectors.append(css.strip()) if css == "\n": selector = ", ".join(selectors) blockerList.append({"action": {"type": "css-display-none", "selector": selector}, "trigger" : {"url-filter": domain}}) selectors = [] selector = ", ".join(selectors) blockerList.append({"action": {"type": "css-display-none", "selector": selector}, "trigger" : {"url-filter": domain}}) with open("blockerList.json", mode="w") as w: w.write(json.dumps(blockerList, indent=4))
ちまちまやっていると無限に時間があっても足りないので、自動作成用のプログラムを書きました。
あとはXCodeでビルドした際にこのパッチを自動実行してくれるようにすればいいわけですね。
# Type a script or drag a script file from your workspace to insert its path. cd ${SRCROOT}/blockerList python3 ${SRCROOT}/blockerList/genPatch.py
各ファイルについて
// hosts.txt www.googletagservices.com tpc.googlesyndication.com adservice.google.com adservice.google.co.jp
hosts.txtにはブロックしたいドメインをズラズラと書いていくだけです。
// selector.txt // .* [class^='ad-'] [class^='ad_']
selector.txtには非表示にしたい要素とドメイン名を書いていきます。
今は適当にダブルスラッシュのあとにドメイン名を書くようにしていますが、この書き方はちょっとダサくてわかりにくいかもしれませんね。
今後の展望
多くのアプリでは小さいアップデートに関してはアプリのアップデートなしに更新ファイルをダウンロードすることで対応しています。
それを実装しようとしたのですが、シミュレータではうまくいくのに実機ではちゃんと動作しなかったのでここを対応しようと思います。
ちなみに、開発中のNyamo Blockerは以下のサイトでなんとオープンソースソフトウェアとして公開しています。よくわからなかったので適当にGPLv3にしました。
記事は以上。
自身を天才と信じて疑わないマッドサイエンティスト。二つ上の姉は大英図書館特殊工作部勤務、額の十字架の疵は彼女につけられた。
コメント