GASでQiita APIを使ってView・いいね・ストック数の一覧を取得する

## 自分の投稿のView・いいね・ストック数を一覧で知りたい
1つ1つ開いてみないとViewはわからないし、ストック数はどこにも表示されない。
どうしたものかということで、~~承認欲求を満たす~~世の中にどのぐらい貢献できているか知るために[Qiita API](https://qiita.com/api/v2/docs)を触ってみました。

## 準備
Chrome拡張「[Restlet Client](https://chrome.google.com/webstore/detail/restlet-client-rest-api-t/aejoelaoggembcahagimdiliamlcdmfm)」で適当に叩いてみるなどして確認。
どうやらユーザー認証していないと、`page_views_count`は取れない模様。

### アクセストークン発行
[設定->アプリケーション](https://qiita.com/settings/applications)から発行できます。

## 実践
### 1.GASの準備
毎日情報を更新できたらいいなと、GASを利用します。
スプレッドシートに一覧を出力することにします。

また、更新日時出してみようかということで、ライブラリ`Moment.js`を利用することにします。
[日付＆時刻の便利ライブラリ「Moment.js」をGoogle Apps Scriptで使う方法](https://tonari-it.com/gas-moment-js-moment/)

初めにスプレッドシートにフォーマットをつくります。

```javascript:.gs
  //カラム番号
  const COL_TITLE  = 1;
  const COL_LATEST = 2;
  const COL_PV     = 3;
  const COL_LIKE   = 4;
  const COL_STOCK  = 5;
  const COL_UPDATE = 7;

  var sheet = SpreadsheetApp.getActiveSheet();
  //シート初期化
  sheet.clear();
  sheet.getRange(1, COL_TITLE).setValue("タイトル");
  sheet.getRange(1, COL_LATEST).setValue("最終更新");
  sheet.getRange(1, COL_PV).setValue("ビュー");
  sheet.getRange(1, COL_LIKE).setValue("いいね");
  sheet.getRange(1, COL_STOCK).setValue("ストック");
  var now = Moment.moment();
  sheet.getRange(1, COL_UPDATE).setValue("【確認日時】" + now.format('YYYY/MM/DD HH:mm:ss'));
```

イメージ
![qiitawk.png](https://qiita-image-store.s3.amazonaws.com/0/86958/837c0963-0d28-2be1-0bfa-5f9d1afd0c4a.png)

### 2.自分の投稿一覧
まずは自分の投稿一覧を取得します。
[GET /api/v2/authenticated_user/items](https://qiita.com/api/v2/docs#get-apiv2authenticated_useritems)
リクエストヘッダでアクセストークンを渡します。

```javascript:.gs
  //定義
  const QIITA_TOKEN  = 'XXXXXXXX';
  const API_ENDPOINT = 'https://qiita.com/api/v2';
  const API_MY_ITEMS = '/authenticated_user/items';

...
  
  //APIヘッダ
  var headers = {'Authorization' : 'Bearer ' + QIITA_TOKEN};
  var params = {'headers' : headers};

  //投稿一覧取得API
  var paramstr = "?per_page=100&page=1"; //★投稿が100件を超えたらページネーションしないといけない
  var res = UrlFetchApp.fetch(API_ENDPOINT + API_MY_ITEMS + paramstr, params);
  var json = JSON.parse(res.getContentText());
  json.forEach(function(item, i){
    sheet.getRange(i + 2, COL_TITLE).setValue(item["title"]);
    var latest = Moment.moment(item["updated_at"]);
    sheet.getRange(i + 2, COL_LATEST).setValue(now.diff(latest, 'd') + "日前").setHorizontalAlignment("right");
  });
```

こんな感じで取得できました。
タイトルと更新日をスプレッドシートに書き込みます。
（更新日は「○日前」と日付計算）

なお、一度に取得できるのが最大100件（デフォルトは20件）なので、それを超える場合は再帰的にAPIを実行する必要があります。
とりあえず今回は省略。

### 3.ページビュー
投稿一覧からは`page_views_count`が返ってこない（null）ので、投稿1件1件に対して詳細を取得しないといけません。
[GET /api/v2/items/:item_id](https://qiita.com/api/v2/docs#get-apiv2itemsitem_id)
また、認証されていないとやはりnullで返ってくるので、リクエストヘッダでアクセストークンを渡す必要があります。

```javascript:.gs
  //定義
...
  const API_ITEM_DTL = '/items';

...
  
  json.forEach(function(item, i){
...
    //投稿ごと詳細取得API
    var resdtl = UrlFetchApp.fetch(API_ENDPOINT + API_ITEM_DTL + "/" + item["id"], params);
    var jsondtl = JSON.parse(resdtl.getContentText());
    
    sheet.getRange(i + 2, COL_PV).setValue(jsondtl["page_views_count"]);
    sheet.getRange(i + 2, COL_LIKE).setValue(jsondtl["likes_count"]);
  });
```

`likes_count`は投稿一覧のレスポンスでも取れるのでどちらでも。

### 4.ストック数
ストック数は、投稿をストックしているユーザー一覧から件数を取ります。
[GET /api/v2/items/:item_id/stockers](https://qiita.com/api/v2/docs#get-apiv2itemsitem_idstockers)

```javascript:.gs
  //定義
...
  const API_ITEM_DTL = '/items';
  const API_STOCKER  = '/stockers';

...
  
  json.forEach(function(item, i){
...
    //投稿ごとのストックユーザー取得API
    var resdtl = UrlFetchApp.fetch(API_ENDPOINT + API_ITEM_DTL + "/" + item["id"] + API_STOCKER, params);
    var count = resdtl.getAllHeaders()['total-count'];
    
    sheet.getRange(i + 2, COL_STOCK).setValue(count);
  });
```

レスポンスヘッダの`total-count`に件数が入ります。
（ページネーションのときもここを取ればトータル件数が分かる）

### 5.GASの定期実行
できあがったらトリガーに登録して完了。
GAS便利だなー。

## 参考
[Qiita API v2 を使って自身の全投稿をエクスポートする Python スクリプトを書いた](https://qiita.com/sta/items/5074df5fcb81d890897b)
[GASで外部APIと連携（１／３）](https://qiita.com/yukihisa-karako@github/items/30747232987c154a01be)
[GoogleスプレッドシートでGET/POST通信を行いコンテンツを取得する](http://shinsuke789.hatenablog.jp/entry/2015/01/03/164203)
[Google Apps Script UrlFetchApp で Http Header を設定する](https://www.monotalk.xyz/blog/google-apps-script-urlfetchapp-%E3%81%A7-http-header-%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B/)
[GASでMoment.jsライブラリを使って超スマートに日時の差をとる方法](https://tonari-it.com/gas-moment-diff/)
[Qiitaでストックされた記事の傾向と対策](https://qiita.com/cognitom/items/8f702e33903f9f890451)