不要なリンク、不要な広告をブロックできる！「そう、JavaScriptならね」 ScriptAutoRunner のご紹介（Google Chrome 拡張機能）

# 不要なリンク、不要な広告をブロックできる！「そう、JavaScriptならね」 ScriptAutoRunner のご紹介（Google Chrome 拡張機能）

# 誰得？ だれのための記事？🙄

まずは、この画像を見てもらって、左右の違いに「なるほど！」と思ったひと向けの記事です。

Google で「HTML CSS」で検索した結果。不要なリンクをブロック！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/a37c61d1-2f47-63ef-466c-2f31e839cf67.png)

とあるページで、不要な広告をブロック！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/d4062b0d-52cc-1924-cb5a-ac17a97ec0bc.png)

ブロック！とは言っても、実際には、表示されたあとで消しているので、データ自体は届いちゃうんですけど。まぁ、不要な情報が見えなくなるだけで、作業効率がかなりアップします。

# どんな機能なの？

入れておくと、特定のWebページを開いたときに、書いたコードを実行してくれる。
書いたコード次第で、不要なリンクや、不要な広告のブロックとか、たいていのことはできちゃう😁。

# おすすめポイント

・シンプルで、使いやすい
・おおよそ思いつくことや、やりたいことは、たいてい何でもできる。ただし、それなりの知識と時間は必要。
・いわゆる巷の広告ブロック系ツールだと、中でなにをしているのかわからないので、個人情報とか、漏れていないか不安があるが、このツールは起動しかしないので、安心感がある。

ちなみに、デメリットも感じていて、
・長いコードを編集しづらい
・保存とか、ダウンロードする機能がないので、ひたすらコードをコピペするしかない


# インストール

インストールはこちら👇から

https://chrome.google.com/webstore/detail/scriptautorunner/gpgjofmpmjjopcogjgdldidobhmjmdbm?hl=ja

# 使い方

詳しいのは、本家の GitHub 👇かな。英語だけど😋。

https://github.com/nakajmg/ScriptAutoRunner/

# HelloWorld 最速で試してみる 

### 1, インストールしたら、① と ② をクリックして設定ページを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/36961915-be29-1509-02d9-139de5e59f5f.png)

### 2, 「</>」をクリックして、Script を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/a32f8982-49c9-12a0-2e62-8e4f7d9aee05.png)

### 3, コードを書く

④ タイトルを `Hello` に変更
⑤ Scriptに `alert('HelloScriptAutoRunner' )` を入力
⑥ Scriptの実行を対象とするサイトにお試しで `qiita.com` を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/3010d728-2455-eccc-5b9e-5c4d4726e53d.png)

### 4, ON/OFF

プラグのアイコン部分「□」をクリックすることで、ON/OFF される。ちなみに ON だと、黄色になります。（って、説明するまでもないですね）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/af5b50af-ed59-28b8-3380-2c46b1590d33.png)

### 5, 動かしてみる

では、お試しで、Qiita のページにアクセスしてみましょう。
アクセスするとこんな感じ👇になり、書いたコードが動いていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/947620d9-4e1e-ccad-7d26-1bb325f1d0b2.png)

# 応用例

JavaScript が実行できるので、やりたいことはたいてい何でもできる（はず）。
ただし、それなりの知識と時間は必要（主に、HTML, JavaScriptの知識と、Chrome DevTool の使い方）。

たとえば、決まったページが開いたら、入力欄にあらかじめ決めたテキスト（例えば、ユーザーIDとか）を入れちゃうとか。

たとえば、RPA っぽいこと、、、、UI のテストとか、もできますよね。



## たとえば、検索結果の不要なリンクをブロック

設定するとこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/d03ca3c3-7fd7-3e3d-b42a-d2c7799eca88.png)

コードはこちら。

```JS
{ // google.com 特定のURLは飛んで行っても後悔するだけなので表示を置き換える
const URL_BLOCK_LIST = [
'://techacademy.jp/',
'://udemy.benesse.co.jp',
'udemy.com/',
'://dev.classmethod.jp/',
'://www.sejuku.net/',
'://blog.codecamp.jp/',
'://digitalidentity.co.jp/',
'://proengineer.internous.co.jp/',
'://techplay.jp/',
'://webukatu.com/',
]

const replacement = (el, s) => {
    console.error( '☕ URL BLOCK! 🍰', s, el )
    el.insertAdjacentHTML('beforebegin', '<div style="text-align: center;">☕ '+s+' 🍰</div>')
    el.remove()
}

for ( const a_tag of document.querySelectorAll('div#search > div > div > div.g > div > div > div > a') )
for ( const str of URL_BLOCK_LIST )
if ( a_tag.href.includes( str ) )
replacement( a_tag.parentElement.parentElement.parentElement.parentElement, str )

} // グローバルを汚さない目的のスコープ
```
（2021-07-19 いつのまにか div 階層が変わっていたので追従した。↑）

冒頭でも紹介しましたが、
この状態で、Google のページで「HTML CSS」で検索しすると、不要なリンクを（コード内のURL_BLOCK_LIST にある文字列にヒットすると）ブロック！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/a37c61d1-2f47-63ef-466c-2f31e839cf67.png)

## たとえば、広告をブロック！

コードの解説としては、`document.querySelectorAll('div')`で、すべての div tag の中から、id に 'google_ads_iframe_' という文字列の入っているタグを探してきて、中身を差し替える軽量化（ `div.innerHTML = '☕ google ads 🍰'` ）をしています。

☕ や 🍰 を表示しているのは「ブロックしたことがわかるように」という配慮と、「やさしい気持ちになれるように」という配慮からです。

console.error() にログを出しているのは、この機能が効いているかどうか、把握しやすいように。ログ内で目立つように、error として出しています。他のコードでは推奨しない書き方です。

setTimeout() や setInterval() を使って何度も実行しているのは、最初から表示されていることもあるし、あとから、時間差で表示されることもあるので、その対応のためです。

```JS
{ const f = e => { // div google_ads_iframe_ BLOCK!
for ( const div of document.querySelectorAll('div') ) {
  if ( ! ( 'id' in div ) ) continue // id で判断する
  if ( div.id.includes( 'google_ads_iframe_' ) ) {
    console.error( '☕ google_ads BLOCK! 🍰', e )
    div.id = ''
    div.style = 'text-align: center;'
    div.innerHTML = '☕ google ads 🍰'
} } }
for(let i=0;i<30;i++)
  setTimeout(e=>f(`★${i*2}`), 1000*i*2) // i*2 秒後に実行 60 秒まで
} // グローバルを汚さない目的のスコープ
```


あとは、iframe を見つけたらすべてブロックしまくるとか。こちらは、iframe の src を確認して、広告ふうの URL だったらブロックするコードになります。

```JS
{ const f = e => { // iframe BLOCK!

const d = (el, s) => {
  console.error( '☕ iframe BLOCK! 🍰', e, s )
  el.insertAdjacentHTML('beforebegin', '<div style="text-align: center;">☕ '+s+' 🍰</div>')
  el.remove()
}

for ( const iframe of document.querySelectorAll( 'iframe' ) )
{
  if ( ! iframe.src ) continue
  if      ( iframe.src.includes('https://googleads.')    ) d( iframe, 'iframe google ad' )
  else if ( iframe.src.includes('.amazon-adsystem.com/') ) d( iframe, 'iframe amazon ad' )
  else if ( iframe.src.includes('https://s.yimg.com/')   ) d( iframe, 'iframe ad' )
}
}
for(let i=0;i<30;i++)
  setTimeout(e=>f(`★${i*2}`), 1000*i*2) // i*2 秒後に実行 60 秒まで
} // グローバルを汚さない目的のスコープ
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/d4062b0d-52cc-1924-cb5a-ac17a97ec0bc.png)


## investing.com 内の div tag を減らして軽量化

個人的に、頻繁に使うページが、investing.com。なので、ピンポイントなコードになってます。

```JS
{ const f = e => { // investing.com 内の div tag を軽量化
const ft = document.querySelector( 'footer#footerWrapper' ) // フッターが重いので
if ( ft != null ) {
  console.error( `ScriptAutoRunner 'footer#footerWrapper' 軽量化!` )
  ft.remove()
}

const side = document.querySelector('div.sidebarCommentaryHeader' ) // side も重い
if ( side != null ) {
  console.error( 'ScriptAutoRunner div.sidebarCommentaryHeader 軽量化!' )
  side.parentElement.remove()
}
const you = document.querySelector('div#outbrain_widget_0' ) // YouMayAlsoLike も重い
if ( you != null ) {
  console.error( 'ScriptAutoRunner div.YouMayAlsoLike 軽量化!' )
  you.remove()
}
}
f()    // すぐ実行
setTimeout(f,100)  // 0.1 秒後に実行
setTimeout(f,1000) // 1.0 秒後に実行
setInterval(f,3000) // 3.0 秒間隔でずっと実行

const close = document.querySelector('span.dfpCloseBtn') // 閉じるボタン
if ( close != null ) {
  console.error( 'ScriptAutoRunner span.dfpCloseBtn 押下!' )
  close.click()
}
}
```
OFF ← ScriptAutoRunner → ON

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/82491fbb-1750-97ea-b6b7-c839460f043a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107592/76495b6d-aae8-3c56-087f-9b3dd8a5e15f.png)

# コードの書き方

じゃぁ、どうやって、このコードを書くのかというと、基本的に、DevTool を開いて、ページの構造を読むところからはじめます。
その HTML タグの特徴を見て、軽量化するコードを書くというアプローチです。
まぁ、面倒ですけどｗ

実は、Yahoo Finance US のページも軽量化したいのですが、、、、なかなか手強い。

# 追記：2021-08-23

iframe をブロックするコードがだいぶ進化したので、メモを残します。詳細の説明に関しては、別ページであらためて書けるといいなぁ。（なぜか、このページは人気が無いので、、、、）

```JS
// iframe は無条件にBLOCK!する

if ( ! window.location.href.includes('.microsoft.com/') ) // Microsoft は除く
if ( ! window.location.href.includes('https://codepen.io/') ) // codepen は除く
if ( ! window.location.href.includes('https://developer.mozilla.org/') ) // mozilla は除く
if ( ! window.location.href.includes('https://docs.google.com/') ) // docs.google は除く
{
const f = e => {
const d = (el, s) => {
if ( s.includes( 'https://codepen.io/') ) return // codepen は除く
if ( s.includes( 'mdn.mozilla.net/' ) ) return // mozilla も除く
if ( s.includes( 'https://www.youtube.com/' ) ) return // youtube も除く
console.error( '☕ iframe BLOCK! 🍰', e, s )
el.insertAdjacentHTML('beforebegin', '<div style="text-align: center;">☕ '+s+' 🍰</div>')
el.remove()
} // end d()

for ( const iframe of document.querySelectorAll( 'iframe' ) )
{
let str = 'iframe: '
if ( iframe.src )
for ( const s of iframe.src.split('?')[0].split('#')[0].split('/') )
{
str += s + '/'
if ( str.length > 40 ) break // 40 文字くらいにまとめる
}
d( iframe, str )
}

} // end f()

// HTMLの内容が変化したら呼ばれる（新機能）これを使えば、リアルタイムに置き換えられる
const observer = new window.MutationObserver( ev => f('★Observer') )
observer.observe( document.body,{
attributes: false,
childList: true,
characterData: true,
subtree: true,
})

f('★init') // 最初の一回

} // グローバルを汚さない目的のスコープ
```

では、この記事が、みなさまのプログラミングライフに役立つことを祈りつつ。