QiitaのLGTM率をGASとQiita APIで計算してみた

こんにちは、株式会社Diverseでフロントエンドエンジニアをやっている[mu-suke](https://twitter.com/chelsea08ym)です。
この記事は[株式会社Diverse Advent Calendar2021](https://qiita.com/advent-calendar/2021/diverse) 、17日目の記事です。

## これはなに？
Qiita APIを使って自分の記事のLGTM率を調べてみました。

LGTM率とは、勝手に僕が造った言葉ですが、View数/LGTM数を割合で表したものです。

数式っぽく表すとこんな形になります。

```math
LGTM率 = \frac{View数}{LGTM数} \times 100
```


## この記事のゴール
以下の理解を得ることをゴールとします。

- Qiitaに投稿している自分の記事のLGTM率を知れること
- 読者がLGTM率を調べられるようになること

## 話の始まり
10月あたりから毎週記事投稿を個人目標に掲げて、毎週頑張って記事を書いていたのですが
@MinoDriven さんの記事を読んでふと、「自分が書いた記事は誰かの役に立っているのか？」と考えるようになりました

https://qiita.com/MinoDriven/items/6718b5e70e3fb321ff9b

じゃあそれって具体的になんなんだろうと思った時に以下のように考えました。

伝えたい人（読んだ人）に対してしっかり伝わったかどうか（LGTMした人）

数値的に言い換えるとview数のうちにどれだけの人がLGTMしたかという結論になりました。

どうやろうって考えた時に自分はGASが割と得意な方だったのでGAS→スプシで保存するという上で述べたような方法になりました。

## 実現方法
以下実現方法になります。

1. GASからQiita APIを叩く
2. 取得したデータを基にスプレッドシートに保存する
3. 得られた値からLGTM率を算出


↓イメージはこんな形です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/642c22e6-5fe1-152d-0849-3c82cf2b162c.jpeg" width=600 />

上記を実現するうえで今回使う技術はこちら

- Qiita API v2
- GAS
- TypeScript
- Clasp

前までGASを書くときはweb上のエディタ, jsで書いていたのですが、最近はもっぱらTypeScriptなのでClaspに挑戦してみました

## ソースコード

https://github.com/mu-suke/Qiita_LGTM_rate


## 0. 開発環境のセットアップ

~~この記事の本質では無いのでリンクを貼るだけとします。~~

Zennのスクラップでまとめたのでそちらを参考にしてみてください。

https://zenn.dev/musuke/scraps/1dc62f457522c8


## 1. スプレッドシートの準備
シートの方は以下のようにしました
保存する要素
- タイトル
- view数
- LGTM数
- 作成日時
- URL

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/0b528307-6169-7434-6f25-c8e9d0ddf4d2.png" width=800 />


## 2. Qiita API用アクセストークンの取得

1. Qiita > 設定 > アプリケーションを選択
2. `新しくトークンを発行する`を選択
3. `read_qiita`にチェックをつけて`発行する`を選択

これでQiita APIで自分の記事を取得する準備が整いました。

発行されたアクセストークンはどこかに保管しておいてください。


## 3. Qiita APIから記事を取得
さてこれで、準備が整ったので実際にコードを書いていきます。

ますはGASからQiita APIを叩く部分になります。

```ts
const main = () => {
  // アクセストークンをGASのプロパティストアに保存
  // 参照: https://tonari-it.com/gas-property-store/
  const ACCESS_TOKEN =
    PropertiesService.getScriptProperties().getProperty('QIITA_ACCESS_TOKEN')

  const resp = UrlFetchApp.fetch(
    'https://qiita.com/api/v2/users/{Write your user ID}/items',
    {
      headers: {
        Authorization: `Bearer ${ACCESS_TOKEN}`,
      },
    }
  )
}
```

アクセストークンをコード上に記載するのはセキュリティ上よろしくないのでGASのプロパティストアに保存します。

プロパティストアへの保存方法は`setProperty()`を実行する方法がありますが、コードを書くのが面倒な場合は以下の方法でもできます

1. GASのエディタを開く
1. 画面右上にある`以前のエディタを使用`をクリック
1. フォームやらポップアップが出るので閉じる
1. 画面左上にある `ファイル` > `プロジェクトのプロパティ`を選択
1. スクリプトのプロパティを選択
1. プロパティ名を`QIITA_ACCESS_TOKEN`、値に先ほど保存したアクセストークンを貼り付けて保存

### 補足画像

step2 | step4 | step6
:-: | :-: | :-: 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/986bed5a-ced0-f40e-0738-a6b116d2ef4d.png" width=360/> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/b07f0c0d-e9dc-e4ae-f469-f7e5c9f7d040.png" width=360/> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/f7491441-fade-7a50-0034-8bacebffa076.png" width=360/>

## 4. スプレッドシートに保存
次にAPIで取得してきたデータをスプレッドシートに保存する処理を書いていきます。

```ts
const main = () => {
  // シートIDとシート名を指定
  // 参照: https://qiita.com/chihiro/items/3e1d17b78676c6a39d24
  const spreadsheet = SpreadsheetApp.openById('Write your sheet ID')
  const sheet = spreadsheet.getSheetByName('Write your sheet name')

  ~~API取得部分は省略~~

  // APIで取得したデータ
  const json = JSON.parse(resp.toString())

  // 上のAPIだとpage_views_countがnullになるため記事ごとにAPIを叩く必要がある
  json.map((data: any) => {
    // スプレッドシート上に保存
    sheet?.appendRow([
      data['title'],
      data['page_views_count'],
      data['likes_count'],
      data['created_at'],
      data['url'],
    ])
  })
}
```

処理の流れとしては以下になります

1. シートのIDを指定
1. シート名を指定
1. 取得した記事を指定したシートの最終行に保存

シートのIDというのはアドレスバーに表示されている赤文字で囲った部分になります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/8b4db32a-33ad-5abd-fdf4-1e3777a5aa1a.png" width=700 />



シート名は画面下部に書かれている文字通りシートの名前を記載すればokです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/efa06351-9a1a-96ca-5f4b-f86f709fc67e.png" width=700 />


## 5. 全体像(結果だけ見たい方はこちら)
コードの全体像になります

```ts
const main = () => {
  // シートIDとシート名を指定
  // 参照: https://qiita.com/chihiro/items/3e1d17b78676c6a39d24
  const spreadsheet = SpreadsheetApp.openById('Write your sheet ID')
  const sheet = spreadsheet.getSheetByName('Write your sheet name')

  // アクセストークンをGASのプロパティストアに保存
  // 参照: https://tonari-it.com/gas-property-store/
  const ACCESS_TOKEN =
    PropertiesService.getScriptProperties().getProperty('QIITA_ACCESS_TOKEN')

  // 1つ目のAPIコール
  const resp = UrlFetchApp.fetch(
    'https://qiita.com/api/v2/users/{Write your user ID}/items',
    {
      headers: {
        Authorization: `Bearer ${ACCESS_TOKEN}`,
      },
    }
  )
  const json = JSON.parse(resp.toString())

  // 上のAPIだとpage_views_countがnullになるため記事ごとにAPIを叩く必要がある
  json.map((data: any) => {
    // 2つ目のAPIコール
    const pageViewRespRaw = UrlFetchApp.fetch(
      `https://qiita.com/api/v2/items/${data['id']}`,
      {
        headers: {
          Authorization: `Bearer ${ACCESS_TOKEN}`,
        },
      }
    )
    const pageViewResp = JSON.parse(pageViewRespRaw.toString())

    // スプレッドシート上に保存
    sheet?.appendRow([
      data['title'],
      pageViewResp['page_views_count'],
      data['likes_count'],
      data['created_at'],
      data['url'],
    ])
  })
}

```

## 7. 実行してみる
実行してみた結果がこちらになります。
きれいに表示されてますね！

![スクリーンショット 2021-12-16 20.54.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/307a2f3b-be1b-3307-fec2-ff85aa5e2383.png)

## 8. LGTM率を算出
LGTM率に関しては取得してきたデータをもとにシート上で計算しています。


```math
LGTM率 = \frac{View数}{LGTM数} \times 100
```


冒頭で出た式を当てたものが上の画像のLGTM率になります。

これで無事LGTM率を率を見ることが出来ました！🎉 🎉


## 注意点
お気づきかもしれないのですが実はQiita APIには複数回アクセスしています。
1つ目は認証ユーザーの記事一覧取得API
2つ目は記事IDを使用した記事取得API
です。

なぜこんなことをしたかというと、1つ目のAPIでは`page_views_count`がnullになってしまうからです。

どうやら2つ目のAPIでview数は取れるのでその方法で取得し直したという流れです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/888e7740-d4ad-f280-c9b1-67227fd0abbc.jpeg" width=600 />

ただ以下に記載したようにQiita APIには利用制限があるのでこれを超えない程度に利用することをおすすめします。

>利用制限
認証している状態ではユーザごとに1時間に1000回まで、認証していない状態ではIPアドレスごとに1時間に60回までリクエストを受け付けます。
出典：Qiita API v2 documentation

https://qiita.com/api/v2/docs#%E5%88%A9%E7%94%A8%E5%88%B6%E9%99%90

## 余談

今回やってみて、GASはやっぱり便利だなというのを改めて感じましてた。
非エンジニアが業務効率化目的でプログラミング学ぶなら間違いなくGASをおすすめします。


ではまた！🎅