QiitaのView数を取得する

初めに
===
QiitaのLGTM数とView数を取得するにあたって、
APIの仕様が変わったのか参考にさせていただいたもので取得できなかった箇所があったので、
取得方法を記載していきます。

環境
===
Go 1.15.2

1. アクセストークンを取得
===
[ユーザ管理画面](https://qiita.com/settings/applications)からトークンを取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/32f82553-49cb-0eb0-1675-b4403fbf83bb.png)

スコープはread_qiitaとwrite_qiitaを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/ca60a6a3-f579-4e4f-ac9e-15ff2e53e829.png)

2. 取得したい情報のURLを確認
===
[公式ドキュメント](https://qiita.com/api/v2/docs)より取得したい情報のURLを確認。今回利用するのは以下の2種類です。

```
GET /api/v2/authenticated_user/items
認証中のユーザの記事の一覧を作成日時の降順で返します。
```

```
GET /api/v2/items/:item_id
記事を取得します。
```

3. jsonを変換するstructを作成
===
公式ドキュメントよりAPIを叩いたときに返却される情報がJsonで返却されるため、
返却されたデータを扱うstructを作成。

```UserInfo.go
package data

type UserInfo struct {
	Id               string `json:"id"`
	Likes_count      int    `json:"likes_count"`
	Title            string `json:"title"`
	Page_views_count int    `json:"page_views_count"`
}
```

4. Qiita APIを叩く
===

```web.go
package qiita

import (
	"../data"
	"../exporter"
	"encoding/json"
	"io/ioutil"
	"net/http"
)

func GetQiitaViews() {                                      // main.goから呼び出す
	url := "https://qiita.com/api/v2/authenticated_user/items?page=1&per_page=20"
	resp, err := doHttpRequest(url)
	defer resp.Body.Close()                                 // Bodyをクローズ

	body, err := ioutil.ReadAll(resp.Body)                  // レスポンスのBodyから取得

	var userInfos []data.UserInfo
	if err = json.Unmarshal(body, &userInfos); err != nil { // jsonの読み出し
		return
	}

	index := 0
	for _, user := range userInfos {                       // 1記事ずつ読み出す
		url = "https://qiita.com/api/v2/items/" + user.Id  // 記事のIDを利用、view数を取得
		resp, err := doHttpRequest(url)
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)

		if err := json.Unmarshal(body, &user); err != nil {return}
		userInfos[index].Page_views_count = user.Page_views_count
		index += 1
	}
	exporter.ToCsv(userInfos)                                // csv化
}

func doHttpRequest(url string) (*http.Response, error) {     // リクエストを共通化
	req, _ := http.NewRequest("GET", url, nil)

	buf, _ := ioutil.ReadFile("token.txt")
	token := string(buf)                                     // tokenを別ファイルで管理

	req.Header.Set("content-type", "application/json")       // ヘッダーにapplication/jsonを指定
	req.Header.Set("Authorization", "Bearer " + token)       // ヘッダーにtokenを指定

	client := new(http.Client)
	resp, err := client.Do(req)
	return resp, err
}
```
以下のAPIだけだと取得できないようで、
URLにクエリをつける必要があることに最初気づかず、取得することができていませんでした。
また、page_view_countがnull（Goでstructに入れた場合0）が返ってきてしまうため、
view数は記事ごとに取得する必要があるようです。
[【Qiita API】いいね！閲覧数の自動集計](https://qiita.com/Naoto9282/items/252c4b386aeafc0052ba)の記事を参考にさせていただきました。

```
GET /api/v2/authenticated_user/items
認証中のユーザの記事の一覧を作成日時の降順で返します。
```

そこで、以下のAPIを利用しています。

```
GET /api/v2/items/:item_id
記事を取得します。
```

5. CSV出力
===

```export.go
package exporter

import (
	"../data"
	"encoding/csv"
	"os"
	"strconv"
)

func ToCsv(userInfos []data.UserInfo) {
	file, _ := os.OpenFile("result.csv", os.O_WRONLY|os.O_CREATE, 0600)  //ファイルを開く
	defer file.Close()

	writer := csv.NewWriter(file)
	writer.Write([]string{"title", "like_count", "page_views_count"})   // ヘッダーをつける
	for _, user := range userInfos {
		likesCount := strconv.Itoa(user.Likes_count)                    // intをstringへ変換
		pageViewsCount := strconv.Itoa(user.Page_views_count)
		writer.Write([]string{user.Title, likesCount, pageViewsCount})  // 書き込み
	}
	writer.Flush()
}
```

最後に
===
ソースは[ここ](https://github.com/kurramkurram/QiitaViewCounts)にあります。
GitHubにソースをアップする関係上、
token情報はmain.goと同一ディレクトリ内の別ファイルにて管理しています。
エラーハンドリングは一部省略している箇所があります。

参考文献
===
[公式](https://qiita.com/api/v2/docs)
[【Qiita API】いいね！閲覧数の自動集計](https://qiita.com/Naoto9282/items/252c4b386aeafc0052ba)
[Go言語でCSVを書き出す!エクセル用のSJIS版も!](https://qiita.com/suin/items/bb9d817af5ccedb18be9)
[Go の import cycle not allowed (循環参照) の対応](http://psychedelicnekopunch.com/archives/1311)