【初心者】Amazon QuickSight を使ってみる(自分のQiita記事のView数/LGTM数の集計と可視化)


目的

  • 記事のView数やLGTM数がほんのちょっとずつ増えている。投稿した成果を定量的なものとするため、自分の記事に関する統計データ収集から可視化までを行う。

Amazon QuickSightとは(自分の理解)

  • 各種ソース(今回はAthena経由のS3)からデータを取得し、グラフ化等、集計、可視化を行うサービス。

やったこと

  • Qiita API にアクセスして、自分の記事のView数、LGTM数を取得して、結果をcsvにしてS3に保存するLambda関数を作成し、定期的に実行する。
  • S3に保存したデータをAthena経由でQuickSightに読み込んで集計、可視化する。

構成図

作業手順

Lambda関数の作成

  • Qiita API にアクセスして、自分の記事のView数、LGTM数を取得して、結果をcsvにしてS3に保存するLambda関数を作成する。関数はCloudWatch Eventsのルールを用いて、1日1回スケジュール実行する。
  • 自分の記事の情報(View数等)を取るにはアクセストークンが必要なので予め入手しておく。
  • PythonのRequests モジュールを使いたいので、Layersで組み込んで使えるようにしておく。
  • 記事一覧を取得するAPIでは記事毎のLGTM数は取れるがView数が取れない。そのため、最初に記事一覧を取得後、全ての記事IDに対しAPIをたたいて、それぞれのView数とLGTM数を取得する。記事毎のストック数も取りたかったがちょっと面倒なので今回は諦める。
  • Lambda関数の中身は以下の通り。
lambda_function.py
import json
import requests   #標準で含まれていないので、Layers機能で追加しておく
import datetime
import boto3

s3 = boto3.resource('s3') 

def lambda_handler(event, context):
    dt_now = datetime.datetime.now()
    bucket = "保存先バケット"
    key = str(dt_now) + ".csv"   #結果を保存するファイル名を"日時.csv"とする

    headers = {
    'Authorization': 'Bearer "自分のアクセストークン"',  #Qiita APIにアクセスして自分の記事情報を取るためのアクセストークン
    }   
    params = (
        ('page', '1'),
        ('per_page', '100'),
    )
    #まず自分の記事一覧を取得し、記事IDのリストを取得する
    response = requests.get('https://qiita.com/api/v2/authenticated_user/items', headers=headers, params=params)
    data = json.loads(response.text)
    count = len(data)
    print("記事数", count)

    #記事ID毎にタイトル、View数、LGTM数を取得して、csvで保存する。タイトル内に","があったら"、"に変換しておく
    baseurl = "https://qiita.com/api/v2/items/"
    tmpfile = open('/tmp/tmp.csv', 'w', encoding='utf-8')

    for i in range(count):
        requesturl = baseurl + data[i]["id"]
        response2 = requests.get(requesturl, headers=headers)
        data2 = json.loads(response2.text)
        data2["title"] = data2["title"].replace(',' , '、')
        print(str(dt_now) + "," + data2["id"] + "," + data2["title"] + "," + str(data2["page_views_count"]) + "," + str(data2["likes_count"]))
        print(str(dt_now) + "," + data2["id"] + "," + data2["title"] + "," + str(data2["page_views_count"]) + "," + str(data2["likes_count"]), file=tmpfile)

    tmpfile.close()
    s3.meta.client.upload_file('/tmp/tmp.csv',bucket,key)
  • 結果として以下のような内容のcsvファイルがS3に1日1回保存される。(日時, 記事ID, 記事タイトル, View数, LGTM数 のリスト)
日時.csv
2020-07-01 05:16:22.344539,146b721f2e1f5dc4de30,【初心者】AWS Connect を使ってみる (Connect + Lambda + DynamoDB + SNS),2206,5
2020-07-01 05:16:22.344539,d8f26737e128243257f7,【初心者】AWS Global Accelerator を使ってみる,7841,10
2020-07-01 05:16:22.344539,2854ee0b83e2043b5313,【初心者】AWS kinesis を使ってみる,2733,4
2020-07-01 05:16:22.344539,9bb260d6e5270fadc369,Amazon FSx for Windows File Server を使ってみる,2882,3

CloudWatch Eventsによる定期実行設定

  • CRON式「0 0 * * ? *」で設定し、毎日0時に上記のLambda関数が実行されるようにする。

Athenaでのデータ読み込み設定

  • S3に保存したcsvデータをAthenaでテーブルを定義した上で読み込み、データを検索できるようにする。
  • Athenaの画面にて、「テーブルの作成-S3バケットデータから」を選択する。

  • データベース名、テーブル名、データ取得元S3バケットを指定してデータベースとテーブルを作成する。

  • データ形式はcsvを指定する。

  • csvの内容に合わせて列を定義する。

  • テーブルを作成する式が自動的に作成されるため、確認して実行する。

  • 作成したテーブルに対してselect文を実行し、検索結果が返ってくることを確認する。

QuickSightでのデータ集計、可視化

QuickSight 初期設定

データの管理

  • まず、分析したいデータソースを登録する必要がある。
  • QuickSightのスタート画面にて「データの管理」を選択する。

  • 「新しいデータセット」を選択する。

  • 今回はデータソースとして「Athena」を選択する。

  • データソース名を設定し、Athenaのworkgroupを指定し、「データソースを作成」に進む。

  • Athenaのデータベースおよびテーブルを指定する。

  • 今回はSPICE(インメモリDB)を使わず直接アクセスとする。

データの可視化

いくつかグラフを作成してみる。

  • 2020/7/1~7/15の、記事毎のView数推移(Top10のみ)
    • 設定内容
      • ビジュアルタイプを「AutoGraph」(自動)に設定
      • フィールド「time」をビジュアルに追加
      • フィールド「view」をビジュアルに追加
      • フィールド「title」をビジュアルに追加
      • フィールド「title」にフィルタ「上位と下位のフィルタ-上」、値「10」、検索条件「view(合計)」を追加
    • 2週間で数十~数百件、各記事のView数が増えていることが分かる。

  • 2020/7/1~7/15の、全体のLGTM数の推移(記事毎の内訳付)
    • 設定内容
      • ビジュアルタイプを「垂直積み上げ棒グラフ」に設定
      • フィールド「time」をビジュアルに追加
      • フィールド「LGTM」をビジュアルに追加
      • フィールド「title」をビジュアルに追加
    • LGTM数が微妙に増えていること、どの記事のLGTMが多いのかが視覚的に分かる。

所感

  • データがしょぼいので今回は大した集計はできてないが、データの保存、集計、可視化の段取りは分かったので、別のデータソースでの分析を試してみたい。
  • 今回は2週間くらい分のデータしかないため、記事を増やしつつ、1年くらいデータ取れば何か見えてくるかもしれない。