コンテンツブロッカーをつくってみよう

iOS

コンテンツブロッカーとは

コンテンツブロッカーとはiOS9で実装されたデフォルトブラウザであるSafariで広告などをブロックする公式の仕組みのこと。

コンテンツブロッカーにはおそらく三種類あり「デフォルト方式」「VPN方式」「DNS方式」があります。

コンテンツブロッカーの機能を有するアプリのつくりかたですが、下記サイトが非常に参考になりました。ありがとうございます。

[iOS9]広告ブロック(Content Blocking Safari Extensions)の作り方 - Qiita
まず、「広告ブロック」とは言ってもコンテンツ制御のうちの一つの呼び名(みんながそう言ってる)であるだけで、単純に広告をブロック出来るわけではない点を理解しておいたほうがいいです。 Content Blocking Safari Ex...

デフォルト方式

blockerList.jsonでブロックするルールを書いていきます。

ブロックの種類はblockでドメイン自体のアクセスをブロックするものと、css-display-noneでkンテンツを非表示にするものがあります。

blockであればドメイン自体にアクセスしないので無駄なJavascriptなどのロードがなくなり、表示の高速化が期待できます。

それに対してcss-display-noneは通信自体は行なうがコンテンツを見えないようにするだけなので、これを使うだけでは高速化はできません。ただ、ブロックしたコンテンツの表示領域に無意味な空白が残ってしまうことがあるので、これをブロックするために使うと良いかもしれません。

VPN方式

自分自身をVPNサーバとして中継し、中継時のルールとして独自のHostsをかませることで広告サーバへのアクセスをブロックする方法です。

Safariだけでなく一部のアプリのアプリ内広告もブロックできますが、柔軟なフィルタが書けないのが難点かもしれません。

DNS方式

よくわかっていないが、基本の考え方はVPN方式と同じはず。

毎回サーバへのアクセスを必要とせず、キャッシュとして持っているためにバッテリー持ちはいいかもしれない。

最近のコンテンツブロッカーはこの機能を搭載しているものも多い。

今回はデフォルト方式でやってみた

今回はまあ「初めてましての方はこっちからやればいいか」ということでデフォルトのSafari内の広告だけをブロックする方法を試しました。

で、Safari内の広告ブロックは非常に単純で、 blockerList.jsonにフィルタリングのルールを書いていくだけです、簡単ですね。

Introduction to WebKit Content Blockers
Describing content blocking rules in a structured format ahead-of-time, rather than running extension-provided code.

ルールの書き方については英文ですが、上の参考サイトが非常にわかりやすいです。

全部試すのはまあめんどくさくて、個人的には基本的な広告だけブロックできたらいいやと思ったのでとりあえず書いてみることにしました。

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にしました。

tkgstrator/NyamoBlocker
Contribute to tkgstrator/NyamoBlocker development by creating an account on GitHub.

記事は以上。

コメント

タイトルとURLをコピーしました