Chrome デベロッパーツールの Console を使いこなす

技術書典5 で本記事をさらにパワーアップさせた本を書いたのでよかったらどうぞ
[Chromeデベロッパーツールを使いこなそう Console編](https://techthetoaster.booth.pm/items/1054598)

---

Chrome デベロッパーツールの Console には Web 画面を解析するための便利な機能が備わっています。
この便利機能を覚えておくと **Web 画面からの情報抽出** や、 **Chrome Extension 開発** がとても捗ります。
※ 筆者はこの機能を利用して、 ウェブスクレイピング時のDOMセレクタを調べたり、 [Q Accelerator](https://qiita.com/howdy39/items/e6136b8454099ebfef29) などの Chrome 拡張機能を開発しています。

本記事では、次の３つを解説します。
1. **Console の便利機能**
2. **実際に Qiita の画面を解析する手順**
3. リアルタイムで評価結果を返す **Eager Evaluation** （Google IO 2018 で発表されました）



## 便利機能（コマンドライン API）
`コマンドライン API` は デベロッパーツール の Console 内で使える便利関数のことです。
リファレンスにはたくさんの関数がありますが、本記事では筆者がよく使うものを抜粋して解説します。

参考:[コマンドライン API リファレンス  |  Tools for Web Developers  |  Google Developers](https://developers.google.com/web/tools/chrome-devtools/console/command-line-reference)

### $$(selector)
`document.querySelectorAll` と似ていますが、 `NodeList` ではなく `配列` を返すのがポイントです。

```javascript:$$は配列を返す
$$('img')  // Array

document.querySelectorAll('img') // NodeList
```

$$ を使うことで配列に変換する手間が省けます。
※ NodeList ではなく配列が必要なのは、 [Array#splice](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/splice), [Array#map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map), [Array#filter](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) などを使用するためです。

参考: [配列 · JavaScriptの入門書 #jsprimer](https://asciidwango.github.io/js-primer/basic/array/)

```javascript:$$を使用する場合としない場合
// ＄＄を使用すると短くかける
$$().map

// ＄＄を使用しないと次のような配列変換が必要になり面倒
Array.from(document.querySelectorAll()).map 
[...document.querySelectorAll()].map
```


### $(selector)
`document.querySelector` と使い勝手は同じですが、短く書くために使用します。

```javascript:同じ結果だけど短く書ける
// $を利用すると短く書ける
$('title')  

// ＄＄を使用しないとちょっと面倒
document.querySelector('title')
```

`$` は Web サイトに設置された `jQuery` で既に定義されていることが多いです。
その場合は、`$$()[0]` で代用すると良いでしょう。

```javascript:$$()[0]で代用した例
$$('title')[0] // <title>Chrome デベロッパーツールの Console を使いこなす - Qiita​</title>​

document.querySelector('title') // <title>​Chrome デベロッパーツールの Console を使いこなす - Qiita​</title>​
```


### $_
**直前の実行結果** が格納されています。

```javascript:$_は直前の実行結果が格納されている
$$('title')[0]  // <title>Chrome デベロッパーツールの Console を使いこなす - Qiita​</title>​

console.log($_) // <title>Chrome デベロッパーツールの Console を使いこなす - Qiita​</title>​
```

`$_` が既に定義されているサイトがたまにあります。
その場合、`$_` を使わずに1行で書いてしまうか、`var` で退避させると良いでしょう。


### copy(object)
**とても便利な関数です、必ず覚えましょう。**
クリップボードに実行結果をコピーする事ができます。

```javascript:クリップボードにコピー
copy($$('title')[0]) // copy自体は値を返さないが、実行するとクリップボードにコピーされている
// 貼り付けると次の値が表示される
// <title>Chrome デベロッパーツールの Console を使いこなす - Qiita​</title>​
```


### clear()
Console をクリアすることができますが、ショートカットキーの方が便利です。
macOS だと `Ctrl + L` または `Cmd + K` で消せます。


### table(data[, columns])
console.tableのエイリアスです、配列をテーブル表示します。
また、第二引数の `columns` で絞り込みが可能です。

次の画像はとあるオブジェクトを `table` で表示した例です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/16f8ccea-8798-adfc-aba3-9a59e5b624ac.png)


### inspect(object/function)
Elements パネルの当該要素を選択状態にします。

次の画像は `inspect` で Qiita の `title 要素` を選択状態にした例です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/8fd60176-9f45-4a12-e558-990f370150c1.png)


### dir(object)
オブジェクトのプロパティを表示します。

次の画像は `dir` で Qiita の `title 要素` のプロパティを表示した例です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/8162d853-abdf-f89d-b3ae-add9eb35f2a1.png)


## Qiita のトレンド記事一覧のタイトルと URL を取得する手順
`コマンドライン API` についていくつか解説しましたが、ここでは実際にそれらを使い、 Qiita のトレンドページから 人気記事の `タイトル` と `URL` を抽出する手順を解説します。


### 1. 取得したい画面要素を Web インスペクタで選択 
インスペクタを使って、取得したい画面要素を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/95c2a784-fbe0-9fa6-7133-180d301f6b75.png)


### 2. クラス名やタグ名でセレクタのあたりをつける
クラス名やタグ名などでセレクタを推測します。
今回はクラス名を使い `$$('.tr-Item_title')` で取れないかを試します。

```javascript:要素を抽出
$$('.tr-Item_title')
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/57adcded-fd0d-4793-4b16-0ffd11a9d00e.png)


### 3. 選択要素を確認する
展開して、マウスカーソルを合わせることで自動で `inspect` が動くような動作をします。
これを利用して選択要素が合っているかを確認します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/75dcc318-6a86-d8f0-709e-f24068f13cd2.png)


### 4. 選択要素のプロパティを確認する
要素を展開して必要なプロパティを探します。
今回は、`textContent` と `href` を使うこととします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/bc153f57-df7e-9e8a-cf92-75c92c2628a1.png)


### 5. Array#map でプロパティを絞った結果を確認
このままではプロパティが多すぎるので `Array#map` で必要なプロパティ(`textContent`, `href`)だけを返すようにします。

```javascript:プロパティを絞る
$$('.tr-Item_title')
.map(e => ({textContent: e.textContent, href: e.href}))
```

`textContent` と `href` だけになっていることが確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/8e0ed8f3-0fd1-4ce6-91bb-233d81d6d262.png)


#### tableでも確認可能
`table` を利用することで縦が揃うので見やすいです。
たくさんのプロパティを取得するときは使うと便利です。

```javascript:テーブル表示で確認
table(
  $$('.tr-Item_title')
  .map(e => ({textContent: e.textContent, href: e.href}))
)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/249b7dd5-a32f-e254-c527-2c1cdb61dfc0.png)


### 6. JSONでコピーする
`copy` を利用して抽出結果をコピーしましょう。
JSON でコピーをしたいときはそのまま `copy` で囲うだけです。

```javascript:JSONでコピー
copy(
  $$('.tr-Item_title')
  .map(e => ({textContent :e.textContent, href: e.href}))
)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/eb51b6fa-20f1-19c7-69f0-c87357588a16.png)



### 7. TSVでコピーする
TSV で `copy`をするときは、次のような変換処理を入れます。

```javascript:TSVでコピー
copy(
  $$('.tr-Item_title')
  .map(e => [e.textContent, e.href].join('\t'))
  .join('\n')
)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/58a55c75-5f77-79f4-41c7-70e35e1f27e9.png)

TSV なので**そのままスプレッドシートなどに貼ることが可能**です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/849f3e80-9c4e-a9e8-e8c6-af93baef04e2.png)



## おまけ
Google IO 2018 で `Eager evaluation` という新機能が Console に追加されることが発表されました。
これを利用するとかなり便利になるので覚えておきましょう。

参考: Google IO の Eager Evaluation の動画
https://www.youtube.com/watch?v=Ay-mdLMDtbs&feature=youtu.be&t=953


### Eager evaluation
リアルタイムで結果を下部に表示する機能です。
`Chrome Canary` で既に利用できます。
※ `Eager evaluation` の設定を ON にする必要があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/116b260f-1fb5-fc3e-6496-230190fbf984.png)


## あとがき
フロントエンド勉強会でこのネタについて話したところ、評判が良かったので記事にしてみました。