初投稿のPVが爆増したのがtrocco®とQiita APIでよくわかった話

# はじめに
7月8日に[「【合格体験記】DB初心者が2か月でSnowPro Coreに合格した」](https://qiita.com/SoySoySoyB/items/312df4f6d515f914d2df)という記事を投稿しました。嬉しいことに、そのPVが想像以上に爆増していたので、詳細について書いてみようと思います。

実際のPVの数値は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/d7cbe97b-941f-7f80-d90b-92d105bc5c21.png)

なんという爆増具合でしょう・・・！

# なぜ、日次の数値があるのか？
そうです、実はこの記事にはちょっとした背景があります。私が所属している株式会社primeNumberでは、[trocco®というデータ統合自動化SaaS](https://trocco.io/lp/)を運営しているのですが、自分ではまだ触ったことがなかった転送元HTTP (S)のコネクタを使ってみたいと考えていました。そんなときに少し調べてみると、

:::note info
Qiitaにはデータ取得用のAPIが存在する
:::

じゃないですか！


そこで、初めての記事を投稿してすぐに、Qiitaの数値を取得するパイプラインを遊びで組んでみたところ、早速面白いことが起きてしまったのです。

ということで、以下でtrocco®の構築方法と、Qiita APIの気になったことのメモ書きを残しておきますね。

# trocco®でQiita APIを叩いて各種数値を取得する方法
データパイプラインは下記の通り、非常にシンプルな形です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/980d2e87-61a6-2b34-5dc3-453303f9817f.png)
- trocco®の転送元HTTP (S)でQiita APIを叩いてデータを取得
- 取得したデータをBigQueryに格納
- Looker StudioからBigQueryのデータを参照


## Qiitaの個人用アクセストークンを取得する
はじめに、Qiitaの個人用アクセストークンを取得します。
- 設定＞アプリケーション＞個人用アクセストークン「新しくトークンを発行する」＞read_qiitaにチェックで「発行する」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/5fd75dc4-eede-f734-286d-15e65b1b0241.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/bdc271ec-f1ab-be1d-409f-73c719668cdd.png)

ちなみにトークンなしでも一部のAPIは使えますが、取得する理由は下記の2点になります。

- 認証をかけることでAPIリクエスト制限が緩和される（IPアドレスごとに認証済1000回/h；非認証60回/h）
- PV数は認証済でないと取得できない

## ユーザーデータの転送設定を作成
次に、ユーザーデータの転送設定を作成します。個別の投稿記事の前にユーザーデータを取得するのは、投稿記事では`page`のパラメーター付与が必須なのですが、そのためには投稿済の記事数を把握する必要があるからです。

- APIのURLを記載（https://qiita.com/api/v2/authenticated_user）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/1d893c66-2ae3-c98e-0e42-436d477bcac4.png)
- 入力ファイルはJSONPathで`$`（全て取得）
    - ちなみにAPIで返ってくるデータ形式は以下の通り（[公式ドキュメント](https://qiita.com/api/v2/docs#get-apiv2authenticated_user)）
```json
{
  "description": "Hello, world.",
  "facebook_id": "qiita",
  "followees_count": 100,
  "followers_count": 200,
  "github_login_name": "qiitan",
  "id": "qiita",
  "items_count": 300,
  "linkedin_id": "qiita",
  "location": "Tokyo, Japan",
  "name": "Qiita キータ",
  "organization": "Qiita Inc.",
  "permanent_id": 1,
  "profile_image_url": "https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/88/ccf90b557a406157dbb9d2d7e543dae384dbb561/large.png?1575443439",
  "team_only": false,
  "twitter_screen_name": "qiita",
  "website_url": "https://qiita.com",
  "image_monthly_upload_limit": 1048576,
  "image_monthly_upload_remaining": 524288
}
```
- HTTPヘッダの`Authorization`の値に`Bearer [取得したトークンの値]`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/4704d903-ea75-3eb9-ab8c-43bd8e2b0eeb.png)
- BigQueryの各種設定（接続情報の設定は省略）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/ac68c88a-a78f-a51a-b45e-d581f9062f58.png)
- 転送モードを「追記（APPEND）」にしておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/1080e3da-c81c-4170-67ac-4f431fcefba8.png)
- 自動データ設定を実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/d33dbe75-0eb5-ad16-1bcd-997325aec02c.png)
- すごい！JSONからカラムやデータ型を自動で判別してくれる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/004c626d-61ef-a435-21ab-8cdab94ad80a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/0e0655dd-21d2-6942-cbf6-94886bfafc5c.png)
- 転送日時カラムを追加しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/853b5e50-53f9-6d2e-9c64-54de4c75368c.png)

## 投稿記事データの転送設定を作成
続けて、投稿記事データの転送設定を作成します。大体設定はユーザーデータと同じなので、違うところのみ記載します。

- APIのURLはhttps://qiita.com/api/v2/authenticated_user/items
- カスタム変数を仕込んでおく（ワークフローで活用する）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/a5786cfd-975c-b1bb-8dd8-9c496a047f94.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/18fc9262-1c37-825c-efde-1ec5e3191cde.png)
- こちらも入力ファイルはJSONPathで`$`（全て取得）
    - ちなみにAPIで返ってくるデータ形式は以下の通りで、こちらはJSONの配列形式（[公式ドキュメント](https://qiita.com/api/v2/docs#get-apiv2authenticated_useritems)）
```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",
      "description": "This group is for developers.",
      "name": "Dev",
      "private": false,
      "updated_at": "2000-01-01T00:00:00+00:00",
      "url_name": "dev"
    },
    "id": "c686397e4a0f4f11683d",
    "likes_count": 100,
    "private": false,
    "reactions_count": 100,
    "stocks_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/Qiita/items/c686397e4a0f4f11683d",
    "user": {
      "description": "Hello, world.",
      "facebook_id": "qiita",
      "followees_count": 100,
      "followers_count": 200,
      "github_login_name": "qiitan",
      "id": "qiita",
      "items_count": 300,
      "linkedin_id": "qiita",
      "location": "Tokyo, Japan",
      "name": "Qiita キータ",
      "organization": "Qiita Inc.",
      "permanent_id": 1,
      "profile_image_url": "https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/88/ccf90b557a406157dbb9d2d7e543dae384dbb561/large.png?1575443439",
      "team_only": false,
      "twitter_screen_name": "qiita",
      "website_url": "https://qiita.com"
    },
    "page_views_count": 100,
    "team_membership": {
      "name": "Qiita キータ"
    },
    "organization_url_name": "qiita-inc"
  }
]
```
- こちらも自動データ設定をすると、勝手にいい感じにしてくれる！

## 日次で動かすワークフローを作成
最後に下記の流れで処理を設計していきます。
- 1つ目の処理：ユーザーデータを取得（これは普通に実行）
- 2つ目の処理：1日1行のデータになっているかをクエリを叩いてチェック
- 3つ目の処理：記事数に合わせて投稿記事データをループ処理で取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/7f88279f-0541-4eaa-0b91-17f677780928.png)

- 下記のクエリを叩いて、データが1行であることを確認
```sql
select
  count(*) as cnt
from
  `project-name.dataset_name.qiita_api_authenticated_user_SoySoySoyB`
where
  date(timestamp_add(transferred_at, interval 9 hour)) = current_date('Asia/Tokyo')
having
  cnt = 1
```

- troccoのワークフローにはBigQueryのクエリ結果でループ実行という便利機能があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492462/79852fb2-3229-af0e-61a1-e20c05745811.png)
- 下記のクエリで処理する
```sql
select
  page
from
  unnest(generate_array(1, (
    select div(items_count - 1, 100) + 1
    from `project-name.dataset_name.qiita_api_authenticated_user_SoySoySoyB`
    where date(timestamp_add(transferred_at, interval 9 hour)) = current_date('Asia/Tokyo')
    ))) page
```

まだ1記事しかないので、ループ処理もなにも`page=1`にしかならないのですが、これなら記事が増えても安心ですね。

# さいごに
以上ご紹介したように、trocco®でのQiitaのデータ取得は非常に簡単に行うことができます。無料で利用できるフリープランも提供していますので、ぜひご活用くださいませ！（[trocco®サービスページはこちら](https://trocco.io/lp/)）

# おまけ：Qiita APIについて気になったこと
自分のデータを取れるってなったら、組織のデータを全部取りたくなるじゃないですか。それでやろうとしてみたのですが・・・

- APIのうち、組織をベースにして取れるデータがない
- ユーザーデータは取得できるが、組織を限定した取得ができない
- 投稿記事データでは、公式ドキュメントに記載がないが、一部の条件を限定して抽出ができる
    - 検索時のパラメータは[「検索時に利用できるオプション」](https://help.qiita.com/ja/articles/qiita-search-options)の通り（例：`query=org:primenumber_inc`）
- 前述の通り、PVを取得するには当該ユーザーによる認証が必要

ということで、組織のデータを取得するには、自分ものとは別の工夫や手間が必要になりそうです。