【Qiita API】いいね！閲覧数の自動集計

# 概要

Qiita APIを叩き、`いいね数`・`閲覧数`を取得する。
Pythonで、出力結果をCSVファイルに保存する方法を実装しました。
GASで、集計結果のレコードを、スプレッドシートに追記する方法を実装しました。

# cURL

cURLでAPIを叩いてみる。

1 . [ユーザの管理画面](https://qiita.com/settings/applications)より、アクセストークンを取得する。
スコープは、`read_qiita`と`write_qiita`にする。

2 . [公式ドキュメント](https://qiita.com/api/v2/docs)より、`認証中のユーザの記事の一覧`を取得する。

```shell:cURL
curl -H 'Authorization: Bearer [アクセストークン]'\
         https://qiita.com/api/v2/authenticated_user/items
```

```json:出力例
[
  {
    "rendered_body": "<h1>Example</h1>",
    "body": "# Example",
    "coediting": false,
    "comments_count": 100,
    "created_at": "2000-01-01T00:00:00+00:00",
    "group": {
      "created_at": "2000-01-01T00:00:00+00:00",
      "id": 1,
      "name": "Dev",
      "private": false,
      "updated_at": "2000-01-01T00:00:00+00:00",
      "url_name": "dev"
    },
    "id": "4bd431809afb1bb99e4f",
    "likes_count": 100,
    "private": false,
    "reactions_count": 100,
    "tags": [
      {
        "name": "Ruby",
        "versions": [
          "0.0.1"
        ]
      }
    ],
    "title": "Example title",
    "updated_at": "2000-01-01T00:00:00+00:00",
    "url": "https://qiita.com/yaotti/items/4bd431809afb1bb99e4f",
    "user": {
      "description": "Hello, world.",
      "facebook_id": "yaotti",
      "followees_count": 100,
      "followers_count": 200,
      "github_login_name": "yaotti",
      "id": "yaotti",
      "items_count": 300,
      "linkedin_id": "yaotti",
      "location": "Tokyo, Japan",
      "name": "Hiroshige Umino",
      "organization": "Increments Inc",
      "permanent_id": 1,
      "profile_image_url": "https://si0.twimg.com/profile_images/2309761038/1ijg13pfs0dg84sk2y0h_normal.jpeg",
      "team_only": false,
      "twitter_screen_name": "yaotti",
      "website_url": "http://yaotti.hatenablog.com"
    },
    "page_views_count": 100
  }
]
```

`likes_count`と`page_views_count `より、`「いいね！」の数`と`閲覧数`を取得できる。
しかし、実際にcURLを叩いてみると、`"page_views_count": null`が返ってくる。

3 . `閲覧数`を取得するため、記事を取得するAPIを叩く。

```shell:cURL
curl -H 'Authorization: Bearer [アクセストークン]'\
         https://qiita.com/api/v2/items/[記事のID]
```

```json:出力例
{
  "rendered_body": "<h1>Example</h1>",
  "body": "# Example",
  "coediting": false,
  "comments_count": 100,
  "created_at": "2000-01-01T00:00:00+00:00",
  "group": {
    "created_at": "2000-01-01T00:00:00+00:00",
    "id": 1,
    "name": "Dev",
    "private": false,
    "updated_at": "2000-01-01T00:00:00+00:00",
    "url_name": "dev"
  },
  "id": "4bd431809afb1bb99e4f",
  "likes_count": 100,
  "private": false,
  "reactions_count": 100,
  "tags": [
    {
      "name": "Ruby",
      "versions": [
        "0.0.1"
      ]
    }
  ],
  "title": "Example title",
  "updated_at": "2000-01-01T00:00:00+00:00",
  "url": "https://qiita.com/yaotti/items/4bd431809afb1bb99e4f",
  "user": {
    "description": "Hello, world.",
    "facebook_id": "yaotti",
    "followees_count": 100,
    "followers_count": 200,
    "github_login_name": "yaotti",
    "id": "yaotti",
    "items_count": 300,
    "linkedin_id": "yaotti",
    "location": "Tokyo, Japan",
    "name": "Hiroshige Umino",
    "organization": "Increments Inc",
    "permanent_id": 1,
    "profile_image_url": "https://si0.twimg.com/profile_images/2309761038/1ijg13pfs0dg84sk2y0h_normal.jpeg",
    "team_only": false,
    "twitter_screen_name": "yaotti",
    "website_url": "http://yaotti.hatenablog.com"
  },
  "page_views_count": 100
}
```

アクセストークンを設定しない場合、`page_views_count`が`null`になる。

# Pythonで実装

1 . `認証中のユーザの記事の一覧`を取得し、`閲覧数`を取得するため、記事を取得するAPIを叩く。

```python:いいね！閲覧数の取得
import requests
import json

url = 'https://qiita.com/api/v2/authenticated_user/items'
headers = {"content-type": "application/json",
           "Authorization": "Bearer [アクセストークン]"}

res = requests.get(url, headers=headers)
list = res.json()

for item in list:
  item_id = item['id']
  title = item['title']
  likes_count = item['likes_count']

  url = 'https://qiita.com/api/v2/items/' + item_id
  res = requests.get(url, headers=headers)
  json = res.json()
  page_views_count = json['page_views_count']

  print(title, page_views_count, likes_count)
```

```none:出力結果
【Django】Hello World 110 0
【JWT】 入門 187 3
【JS】setTimeoutを用いた、非同期処理入門 385 3
```

2 . 出力結果をCSVファイルに書き込む。

```py:CSVファイルに書き込み
import requests
import json
import csv

url = 'https://qiita.com/api/v2/authenticated_user/items'
headers = {"content-type": "application/json",
           "Authorization": "Bearer [アクセストークン]"}

res = requests.get(url, headers=headers)
list = res.json()


with open('qiita.csv', 'w') as f:
  for item in list:
    item_id = item['id']
    title = item['title']
    likes_count = item['likes_count']

    url = 'https://qiita.com/api/v2/items/' + item_id
    res = requests.get(url, headers=headers)
    json = res.json()
    page_views_count = json['page_views_count']

    print([title, page_views_count, likes_count])

    writer = csv.writer(f, lineterminator='\n')
    writer.writerow([title, page_views_count, likes_count])
```

```none:qiita.csv
【Django】Hello World,110,0
【JWT】 入門,187,3
【JS】setTimeoutを用いた、非同期処理入門,385,3
```

# GASで実装

定期実行するため、GASで実装する。

1 . `認証中のユーザの記事の一覧`を取得し、`閲覧数`を取得するため、記事を取得するAPIを叩く。

```js:いいね！閲覧数の取得
function myFunction() {
  var url = 'https://qiita.com/api/v2/authenticated_user/items'
  var option = {
    headers : {
      'Authorization' : 'Bearer [アクセストークン]'
    },
    method : 'get'
  }
  var res = UrlFetchApp.fetch(url, option)
  var list = JSON.parse(res.getContentText())
  
  for(var i=0; i<list.length; i++) {
    var item = list[i]
    
    var item_id = item['id']
    var title = item['title']
    var likes_count = item['likes_count']
    
    url = 'https://qiita.com/api/v2/items/' + item_id
    res = UrlFetchApp.fetch(url, option)
    var json = JSON.parse(res.getContentText())
    var page_views_count = json['page_views_count']
    
    Logger.log(title)
    Logger.log(likes_count)
    Logger.log(page_views_count)
  }
}
```

```none:出力結果
【Django】Hello World
0.0
110.0
【JWT】 入門
3.0
187.0
【JS】setTimeoutを用いた、非同期処理入門
3.0
385.0
```

2 . 出力結果を集計したレコードを、スプレッドシートに追加する。

```js:集計したレコードをスプレッドシートに追加
function myFunction() {
  var url = 'https://qiita.com/api/v2/authenticated_user/items'
  var option = {
    headers : {
      'Authorization' : 'Bearer [アクセストークン]'
    },
    method : 'get'
  }
  var res = UrlFetchApp.fetch(url, option)
  var list = JSON.parse(res.getContentText())
  
  var page_views_count = 0
  var likes_count = 0
  
  for(var i=0; i<list.length; i++) {
    var item = list[i]
    
    var item_id = item['id']
    likes_count += item['likes_count']
    
    url = 'https://qiita.com/api/v2/items/' + item_id
    res = UrlFetchApp.fetch(url, option)
    var json = JSON.parse(res.getContentText())
    page_views_count += json['page_views_count']
  }
      
  var spreadsheet = SpreadsheetApp.openById('[キー]')
  var sheet = spreadsheet.getSheetByName('[シート名]')
  sheet.appendRow([new Date(), list.length, likes_count, page_views_count])

}
```

実行結果は、以下のようになる。

<img width="581" alt="スクリーンショット 2019-02-07 3.45.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/320365/b9741dee-dd84-c6af-8477-88fbc116ce3c.png">

3 . 1日1回集計するトリガーを作成する。

<img width="479" alt="スクリーンショット 2019-02-07 4.01.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/320365/1fad983e-c2ce-cb3f-26e4-e598e2e5812f.png">

<img width="661" alt="スクリーンショット 2019-02-07 4.02.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/320365/494b8c3b-d8b9-2532-5ff9-70f69dfe0ac2.png">

4 . 各記事の`いいね数`・`閲覧数`もまた、集計する。

```js:記事毎の集計をスプレッドシートに追加
function myFunction() {  
  var url = 'https://qiita.com/api/v2/authenticated_user/items'
  var option = {
    headers : {
      'Authorization' : 'Bearer [アクセストークン]'
    },
    method : 'get'
  }
  var res = UrlFetchApp.fetch(url, option)
  var list = JSON.parse(res.getContentText())
  lest = list.reverse()  // 降順から昇順に変更
  
  var sum_likes_count = 0
  var sum_page_views_count = 0
  
  var now = new Date()
  var record_title = ['日付']
  var record_likes_count = [now]
  var record_page_views_count = [now]
  
  for(var i=0; i<list.length; i++) {
    var item = list[i]
    var item_id = item['id']
    var title = item['title']
    var likes_count = item['likes_count']
  
    url = 'https://qiita.com/api/v2/items/' + item_id
    res = UrlFetchApp.fetch(url, option)
    var json = JSON.parse(res.getContentText())
    var page_views_count = json['page_views_count']
    
    sum_likes_count += likes_count
    sum_page_views_count += page_views_count
    
    record_title.push(title)
    record_likes_count.push(likes_count)
    record_page_views_count.push(page_views_count)
  }
  var spreadsheet = SpreadsheetApp.openById('[キー]')
  var sheet = spreadsheet.getSheetByName('sum')
  sheet.appendRow([new Date(), list.length, sum_likes_count, sum_page_views_count])
  sheet = spreadsheet.getSheetByName('likes_count')
  sheet.getRange('1:1').clear()
  sheet.getRange(1,1,1,record_title.length).setValues([record_title])
  sheet.appendRow(record_likes_count)
  sheet = spreadsheet.getSheetByName('page_views_count')
  sheet.getRange('1:1').clear()
  sheet.getRange(1,1,1,record_title.length).setValues([record_title])
  sheet.appendRow(record_page_views_count)
}
```

記事毎の`いいね数`の集計は、以下のようになる。

<img width="447" alt="スクリーンショット 2019-02-07 6.16.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/320365/86898205-a8a8-ce2b-9dbf-7144ca60e001.png">

記事毎の`閲覧数`の集計は、以下のようになる。

<img width="446" alt="スクリーンショット 2019-02-07 6.16.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/320365/ec0a9d43-3efa-9f3b-c95f-378e7833e7e0.png">

# まとめ
PythonとGASで、いいね数・閲覧数を取得を実装しました。
GASの実装では、トリガーを設定することで、自動で集計結果を取得できます。
間違い・指摘等があればコメントお願いします。

# 参考文献
- [公式ドキュメント](https://qiita.com/api/v2/docs)
- [Qiita API v2 を使って投稿一覧を取得する
](https://qiita.com/fkooo/items/250f42a0b641fb96b5ff)
- [Google Apps Scriptで配列を使ってスプレッドシートにデータ行を追加する方法](https://tonari-it.com/gas-array-push-append/)