【JavaScript初心者】QiitaAPIで投稿記事ごとのviews数、LGTM数、ストック数、コメント数を取得し一覧で表示

投稿記事が10件を超え、そろそろ各投稿記事のviews数、LGTM数、ストック数等を一覧で確認してみたくなりました。今現在、「views数については」Qiita上にて一覧で確認する方法はありません。調べてみたところ、皆さん同じことを思うようで参考になるものがありました。ありがとうございました。
以下の記事の「①HTML/JavaScript」を参考にQiitaAPI(api/v2/authenticated_user/items、api/v2/items/[記事のID])を使用して投稿記事ごとのviews数、LGTM数、ストック数を取得、表示しました。LIKE率、STOCK率は省略し、代わりにコメント数と作成日を追加しました。

https://qiita.com/yoshi_yast/items/a0dacc4dd33106e66752

#本記事の環境
※PCに環境構築を行う必要はありません。
WEBブラウザ(Google Chome)
テキストエディタ

#使用技術
* HTML
* JavaScript
* jQuery
* Ajax
* Bootstrap

#事前準備
* Qiitaにて、「設定」から「アプリケーション」を選択する。
* 「個人用アクセストークン」を発行する。※今回は読み取り権限だけで良いです。
* 発行した「個人用アクセストークン」をメモする。※後で入力します。

#使用方法
* 以下の成果物をWEBブラウザで開き、「個人用アクセストークン」を入力する。
* 「読込」ボタンを選択して、表示されるまで少し待つ。
* 表示されたら結果を確認する。※タイトルのリンクから記事に飛べるか等も。

#成果物(画面)
![Qiita投稿一覧01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1009061/78c51258-f4b9-0844-0152-8deccd9950ed.png)
![Qiita投稿一覧02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1009061/664f0b01-d2e9-d174-c808-5297e325615d.png)

#所感
* なるべくjQueryを使おうと努力した。使えたと思う。
* Ajax、Bootstrapは初めて使った。できることが増えそうなので使っていきたい。
* 投稿記事ごとのviews数、LGTM数、ストック数、コメント数を一覧で確認できるのが楽でいい。

#成果物(ソースコード)

```html:qiita_item_get.html
<!DOCTYPE html>
<html>
  <head>
    <title>Qiita Item</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  </head>
  <body>
    <template id="tdTemp">
      <tr id="trTemp">
        <th id="td_no" scope="row">1</th>
        <th id="td_create_datetime" scope="row">0000-00-00 00:00:00</th>
        <td id="td_title"><a id="td_link" href="temp" target="_blank">タイトル</a></td>
        <td id="td_views">1</td>
        <td id="td_lgtm">2</td>
        <td id="td_stock">3</td>
        <td id="td_comment">4</td>
      </tr>
    </template>
    <div class="container">
      <br>
      <h3>Qiita投稿一覧</h3>
      <br>
      <div class="input-group flex-nowrap" id="main">
        <div class="input-group-prepend">
          <span class="input-group-text">Qiitaアクセストークン設定</span>
        </div>
        <input type="text" class="form-control" id="accesstoken" placeholder="Access Token">
      </div>
      <br>
      <button type="button" class="btn btn-primary" onclick="getQiitaItem()">読込</button>
      <br>
      <br>
      <div id="result">
        <table  class="table table-dark" id="itemTable">
          <thead id="itemThead" style="display: none;">
            <tr>
              <th scope="col">No</th>
              <th scope="col">作成日</th>
              <th scope="col">タイトル</th>
              <th scope="col">views</th>
              <th scope="col">LGTM</th>
              <th scope="col">ストック</th>
              <th scope="col">コメント</th>
            </tr>
          </thead>
          <tbody id="itemTbody"></tbody>
        </table>
        <p id="loading" style="display: none;">Now Loading...</p>
      </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK" crossorigin="anonymous"></script>
    <script>
      // Qiita投稿一覧取得処理
      function getQiitaItem () {
        // 画面入力されたQiitaアクセストークンを取得する。
        let token = $('#main > #accesstoken').val();
        if (token == '') {
          alert('アクセストークンを入れてください');
          return;
        }
        
        // 見出し行を表示する。
        $("#result > #itemTable > #itemThead").show();
        // ローディングを表示する。
        $("#result > #loading").show();
        
        // Qiitaアクセストークンに対応するユーザの記事の一覧を作成日時の降順で取得する。
        let items = [];
        $.ajax({
          type: "GET",
          url: "https://qiita.com/api/v2/authenticated_user/items",
          headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + token,
          },
          dataType: "json",
          success: function(data) {
            $("#result > #loading").hide();
            
            items = data;
            let sum_view = 0;
            let sum_lgtm = 0;
            let sum_stock = 0;
            let sum_comment = 0;
            items.forEach (function(element, index) {
              // 記事取得処理を呼び出す。
              let item = [];
              item = getItemCore(element.id, token);
              // ストック数取得処理を呼び出す。
              let cnt_stock = 0;
              cnt_stock = getQiitaStock(element.id, token);
              
              // 取得したデータを設定する。
              let content_tdTemp = $("#tdTemp").contents();
              let no = items.length - index;
              content_tdTemp.children("#td_no").text(no);
              let create_datetime = item.created_at.substring(0, 10);
              create_datetime = create_datetime.replace(/-/g, "/");
              content_tdTemp.children("#td_create_datetime").text(create_datetime);
              content_tdTemp.children("#td_title").children("#td_link").attr("href", item.url);
              let title = item.title;
              if (title.trim().length >= 50) {
                  // 記事タイトルが長すぎる場合は、一部を「 ...」に置換する。
                  title = title.substring(0, 50) + " ...";
              }
              content_tdTemp.children("#td_title").children("#td_link").text(title);
              content_tdTemp.children("#td_views").text(item.page_views_count);
              content_tdTemp.children("#td_lgtm").text(item.likes_count);
              content_tdTemp.children("#td_stock").text(cnt_stock);
              content_tdTemp.children("#td_comment").text(item.comments_count);
              content_tdTemp.clone().appendTo("#result > #itemTable > #itemTbody");
              $("#result").show();
              
              sum_view += item.page_views_count;
              sum_lgtm += item.likes_count;
              sum_stock += cnt_stock;
              sum_comment += item.comments_count;
            });
            // 合計行を設定する。
            let content_tdTemp_sum = $("#tdTemp").contents();
            content_tdTemp_sum.children("#td_no").text("計");
            content_tdTemp_sum.children("#td_create_datetime").text("－");
            content_tdTemp_sum.children("#td_title").text("－");
            content_tdTemp_sum.children("#td_views").text(sum_view);
            content_tdTemp_sum.children("#td_lgtm").text(sum_lgtm);
            content_tdTemp_sum.children("#td_stock").text(sum_stock);
            content_tdTemp_sum.children("#td_comment").text(sum_comment);
            content_tdTemp_sum.clone().appendTo("#result > #itemTable > #itemTbody");
            $("#result").show();
          },
          error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert('getQiitaItem() ERROR : ' + errorThrown);
          }
        });
      };
      
      // 記事取得処理
      function getItemCore(item_id, token) {
        let item = [];
        $.ajax({
          type: "GET",
          url: 'https://qiita.com/api/v2/items/' + item_id,
          headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + token,
          },
          dataType: "json",
          async: false,      // 同期通信
          success: function(data){
            item = data;
          },
          error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert('getQiitaViews() ERROR : ' + errorThrown);
          }
        });
        return item;
      };
      
      // ストック数取得処理
      function getQiitaStock(item_id, token) {
        // APIの仕様上、ストック数を瞬時には取得できないため、やや面倒な処理を実施。
        let stock = [];
        let flg = true;
        let index_page = 1;
        let cnt_stock = 0;
        while (flg) {
          $.ajax({
            type: "GET",
            url: 'https://qiita.com/api/v2/items/' + item_id + '/stockers?page=' + index_page + '&per_page=100',
            headers: {
              "Content-Type": "application/json",
              "Authorization": "Bearer " + token,
            },
            dataType: "json",
            async: false,      // 同期通信
            success: function(data){
              stock = data;
              cnt_stock += stock.length;
              if (stock.length < 100) {
                flg = false;
              }
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
              alert('getQiitaStock() ERROR : ' + errorThrown);
              flg = false;
            }
          });
          index_page++;
        }
        return cnt_stock;
      };
    </script>
  </body>
</html>
```