🔇

最強になりたくない人向けのZennでのキーワード/ユーザ非表示方法、またはAdblock入門

2022/11/02に公開

はじめに

近頃「最強」のような魅力的な言葉を用いたタイトルが、技術記事で流行っているように見受けられます。

もちろん数多くの人が最強になったり、作業効率を瞬時に上げたりしたいと願うものですので、そういう人々にわかりやすく伝わるタイトルにすることは、良いことだと考えています。

しかしながら、私は既に\overset{\scriptsize \text{アルティメットパワーエンジニア}}{\small \bold{究極強技術者}}であり、これ以上最強や急激な作業効率を手に入れてしまうと、誰にも止められなくなる恐れが出てきました。

よって悲しいことながらそのような言葉をなるべく回避する必要がありますが、Zennを含め数多くのサイトで、通常ではキーワードでの非表示機能がありません(ご承知の通り究極強技術者はスーパースペシャルレアなので、致し方のないことです)。

そこで、今回はそういった普通のWebサイトにて、キーワード/ユーザ非表示をAdblocker(Webブラウザのブロッカー/コンテンツブロッカー)[1]で行う方法をご紹介いたします。

人類よりも上位の存在にならないよう、自己の\overset{\scriptsize \text{インテリジェンス}}{\small \bold{力}}を恐れている方々に対し、この\overset{\scriptsize \text{うた}}{\small \bold{記事}}を捧げます。

記事名での非表示手順

今回はキーワード/ユーザ非表示をAdblocker、具体的にはおそらく最も一般的な構成であるChrome上のuBlock Origin(uBO)を用いて非表示を行っていきたいと思います。

フィルタ文自体は一般的なもので、また互換性のために各Adblockerで似た機能は同じ文で動くようになったりしているため、他Adblockerでもそのまま動くと思われます(AdGuard for iOSを用いて、iPhone上のSafariでいくつか動作することを確認できました)。

以下、手順内の雑にいじったZennトップページにある記事/ユーザ名等は適当につけたもので、実際の記事/ユーザ名等とは一切関係ありません。

次の画像のような記事一覧で、user2さんが上げているような魅力的な記事名を非表示にするとしましょう。

まず、非表示にしたいキーワードが含まれる対象である、記事タイトルを右クリックして検証を選択し、デベロッパーツールを開きます。

h2要素に記事タイトルテキストが存在していますね。

デベロッパーツール内の要素の上でカーソルを動かしながら見ると、classがArticleList_itemContainer__foobarなdivの中に各記事のタイトルやユーザ名が含まれているようです。

これをまるまる非表示できれば目標達成です。ただし、class名の最後の文字列はランダム生成されたように見えるので、それ以外を前方一致するようにしましょう。

というわけで、記事名のみを対象とする場合は、「非表示としたい文字列の含まれたh2要素を含む、classがArticleList_itemContainerで始まるdiv要素」でよさそうです。

これをフィルタにすると次のようになります。

zenn.dev##div[class^="ArticleList_itemContainer"]:has(h2:has-text(非表示としたい文字列))

頭から一つずつ、説明を次に記述します。

フィルタの一部 説明
zenn.dev 非表示対象とするドメインを設定しています
## Static extended filteringであることを表現しています
ここではAdblockで一般的な特定ドメインへのXHRをブロックするのではなく、ページ内の一部を非表示にするルールの書き方、という理解で大丈夫かと思います
div[class^="ArticleList_itemContainer"] classがArticleList_itemContainerで始まるdiv要素を、属性セレクターを用いて指定しています
:has() 対象要素内に、引数の要素が含まれているもののみを:has(arg)で選択しています
よって引数である非表示としたい文字列の含まれたh2要素を含む要素であることを表現しています
h2:has-text(非表示としたい文字列) 引数のテキストが、対象と配下に存在するもののみを選択する:has-text(needle)を用いて、非表示としたい文字列がテキストとして含まれたh2要素を表現しています

他にも構文を詳しく知りたい方は、次のドキュメントなどを参考にしてみてください。
https://github.com/gorhill/uBlock/wiki/Static-filter-syntax

記事タイトルに限らず、ユーザ名X日前も含めて良い場合は、単に

zenn.dev##div[class^="ArticleList_itemContainer"]:has-text(非表示としたい文字列)

というフィルタでも機能します。

uBOのダッシュボード内のマイフィルターに、例として非表示としたい文字列をウルトラスーパーデラックスとしたフィルタを追加してページを更新すると、次のように非表示にされていることが確認できます。

ユーザでの非表示手順

Zennではユーザ名は変更可能ですが、ユーザIDは現時点では変更不可で、かつユーザのURLにも含まれており他ユーザと重複しなさそうですので、こちらを判別対象としていきましょう。

記事名と同じようにユーザ名上で検証すると、次のようにa要素で/ユーザIDにhrefでリンクされていますね。

つまり、「非表示としたい/ユーザIDをhref属性にしたa要素を含む、classがArticleList_itemContainerで始まるdiv要素」を対象とすればよいわけです。

よって、次のようなフィルタで非表示にすることができます。

zenn.dev##div[class^="ArticleList_itemContainer"]:has(a[href="/ユーザID"])

記事名での構文が理解できればそのままだと思うので、説明は割愛させていただきます。

例として対象ユーザIDをuser2としてフィルタを追加して更新すると、以下のように該当ユーザの投稿を非表示に出来ていることが確認できます。

本手法の問題点

“誤爆”が発生する可能性がある

非表示対象としたいもの以外を非表示としてしまったり、またサイトの変更によって全く機能しなくなる可能性があります。

自分では制御できない人様のサイトを勝手にいじくるわけですので、Adblockは常にどこかで壊れている可能性があると言っても過言ではないでしょう。

今回のようなケースで、非表示の誤爆を許容できない場合には、非表示にするのではなく見えづらくするという対処もあります。

subject:style(arg)を用いてCSSを変更することが可能なので、これを末尾に追加して次のようなフィルタを適用することで、

zenn.dev##div[class^="ArticleList_itemContainer"]:has(h2:has-text(非表示としたい文字列)):style(background-color: #505050)

以下のように、背景色を変更して見えづらくするのみにすることができます。

これによりうっかり別の要素を変更してしまった場合でもわかりやすくなり、また読もうと思えば読める表示にすることも可能となります。

誤爆を覚悟でとにかく非表示にしたいのか、あるいはお試しで見えづらくする程度に済ませたいのか、はたまた”絶対NGキーワード”と”疑わしいキーワード”をそれぞれ非表示と見えづらくを適用したいか、などユースケースによって最適なものが異なりますので、色々試してみることをおすすめします。

非表示対象の変更がしづらい

例えば記事名非表示対象の文字列が複数あった場合、次のフィルタのように正規表現のORで繋げていくか

zenn.dev##div[class^="ArticleList_itemContainer"]:has(h2:has-text(/文字列1|文字列2/))

あるいは次のように、単に複数行にずらずら書くしかないです。

zenn.dev##div[class^="ArticleList_itemContainer"]:has(h2:has-text(文字列1))
zenn.dev##div[class^="ArticleList_itemContainer"]:has(h2:has-text(文字列2))

個人的には正規表現で横にずらずら並んでいくのは見づらいですし、かといって複数行でコピペして書いていくのはちょっとイケてない感じがします。

緩和策としては、例えば一行毎に対象文字列を書いたテキストファイルを、上記のようなAdblockerフィルタに変換するプログラムを書いて、GitHubとかに上げてCIで出力し、各Adblockerで購読するというのが考えられます。この方法では複数ブラウザ/端末間でフィルタを同期できる、という利点もあります。

非表示対象の切り替え/カウントがしづらい

uBOの場合、非表示とするフィルタはCosmetic filteringに含まれますので、ChromeのツールバーにあるuBOアイコンをクリックすると表示されるポップアップ内から表示/非表示のトグル、(他の広告等の非表示対象を含めた)非表示数の確認を行うことが可能です。

参照: Per site switches · gorhill/uBlock Wiki

しかしちょっと深い階層の位置にありますので、常時非表示数の確認を行いたい場合はかなり手間になると思います。

CSS変更で無理やりどこかにカウント表示を行うことも可能かもしれませんが、ここまでいくとAdblockerではなくUserscriptや別途機能拡張(アドオン)で行ったほうが良いかと思われます。

例えばGoogle検索結果のフィルタリングであれば、uBlacklistのような機能拡張がありますので、これを利用することによって表示/非表示のトグル、カウント確認が極めてしやすくなり、また非表示対象の追加・削除も設定から簡単に行うことが出来るようになります。

uBlacklistはサポートされているサイトを対象とする場合は大変便利ですが、現時点では検索サイトに限定されているので、他サイトを追加したい場合は機能拡張を変更する必要がありそうです。

今後の展望

もっと"良い"フィルタにすることは可能でしょうか?

  • わかりやすい、パフォーマンスの良い、誤爆の少ないフィルタを書くにはどうすれば良いのでしょうか
  • それぞれを評価するためには、何を指標としたらいいのでしょうか

もっと簡単にフィルタを作成することはできないでしょうか?

  • uBOの要素選択モードはインタラクティブに対象を指定できて便利なので、ぜひ試してみてください
  • 私含めChromeのデベロッパーツールの方が使い慣れている人が多いかと思い、本記事ではそうしてあります

uBlacklistのような機能拡張を、容易に他サイトを追加できるようにするにはどうすればいいのでしょうか?

  • 例えば一部の”自動ページ送り継ぎ足し表示”系機能拡張と、 AutoPagerizeデータベースの関係のように、機能拡張は単に非表示処理エンジンのみを保持し、非表示対象文字列/トグル・カウント表示の方法が記載されたconfigファイルは分離することにより、個人やコミュニティが対応サイトを追加できるようにすることは可能でしょうか

自分の管理するサイトにNGワード機能を追加したい場合、どうするのが望ましいでしょうか?

  • バックエンドで、ログインしたユーザが一覧取得APIを叩いたら、フィルタされた結果を返すようにするのがよいでしょうか
  • フロントエンドで、Adblockerが行うようにブラウザ上でフィルタ処理を行う方がよいでしょうか
  • これらを比較する場合、APIのキャッシュ効率、それぞれの実装コスト等、どのような点が挙げられるでしょうか

おわりに

zenn.dev##p:has-text(いかがだったでしょうか)

で「いかがだったでしょうか」を含む段落を、非表示に出来ると思います。

Happy adblocking!

脚注
  1. 非表示対象は広告ではないのでAdblockというのは全く正しくないのですが、Webブラウザのブロッカーというとちょっとしっくりこないので、個人的に一番普及していると考えているAdblock(-er)という呼称を本記事ではいたします。 ↩︎

Discussion