2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C# - Qiita API v2 でページビューの一覧取得

Posted at

はじめに

Zenn では、統計ダッシュボードで、記事ごとのページビューを一覧表示できます。
Qiita にはこのような機能がないため、Qiita API v2 を用いて情報を取得する方法を説明します。

テスト環境

ここに記載した情報/ソースコードは、Visual Studio Community 2022 を利用した下記プロジェクトで生成したモジュールを Windows 11 24H2 で動作確認しています。

  • Windows Forms - .NET Framework 4.8
  • Windows Forms - .NET 8
  • WPF - .NET Framework 4.8
  • WPF - .NET 8

Visual Studio 2022 - .NET Framework 4.8 は、C# 7.3 が既定です。
このため、サンプルコードは、基本的に C# 7.3 機能範囲で記述しています。

参考情報

下記情報を参考にさせて頂きました。

前準備

アクセストークン取得

記事に関する情報取得は、/api/v2/authenticated_user/items を利用します。

上記を利用する場合、事前にアクセストークン取得が必要となります。
Qiita にログインして、右上 アカウントのアイコンから「設定」を選択します。

AccessToken-01.png

設定画面で「アプリケーション」「個人用アクセストークン - 新しくトークンを発行する」を選択します。

AccessToken-02.png

「アクセストークンの説明」を入力、スコープ「read_qiita」として「発行する」を選択します。

AccessToken-03.png

アクセストークンが表示されるので「アクセストークンをコピー」します。

AccessToken-04.png

JSON デシリアライズ

JSON デシリアライズは、現在 Microsoft が推奨している System.Text.Json を利用します。
.NET Framework の場合、System.Text.Json は標準提供されていないので、NuGet Gallery | System.Text.Json 導入が必要です。

PM> NuGet\Install-Package System.Text.Json

HttpClient

GROWI - Ubuntu 24.04 への導入と Windows C# クライアント と同様に、HttpClient を IHttpClientFactory で利用します。
DependencyInjection、IHttpClientFactory を利用するので、NuGet Gallery | Microsoft.Extensions.DependencyInjectionNuGet Gallery | Microsoft.Extensions.Http を導入します。

PM> NuGet\Install-Package Microsoft.Extensions.DependencyInjection
PM> NuGet\Install-Package Microsoft.Extensions.Http

サンプルコード

.NET Framework 4.8 と .NET 8 では、軽微な差異があるので、まず .NET 8 のサンプルコードを記載して、次に .NET Framework 4.8 の差分を記載します。

.NET 8

まずは、ServiceCollection に対して、QiitaClient という名称の HttpClient を登録した ServiceProvider を用意します。

private static IServiceProvider? MyServiceProvider = null;
private const string AccessToken = "<事前準備で取得したアクセストークン>";  // TODO
var serviceCollection = new ServiceCollection();
serviceCollection.AddHttpClient("QiitaClient", client =>
{
  client.BaseAddress = new Uri("https://qiita.com");
  client.DefaultRequestHeaders.Authorization = 
                       new AuthenticationHeaderValue("Bearer", AccessToken);
  client.DefaultRequestHeaders.Add("Accept", "application/json");
});
MyServiceProvider = serviceCollection.BuildServiceProvider();

/api/v2/authenticated_user/items クライアント処理を用意します。

// Qiita API v2 - /api/v2/authenticated_user/items
private async Task<List<ResponsePage>?> QiitaGetPageList()
{
  // IHttpClientFactory で QiitaClient という名前の HttpClient 取得
  var factory = MyServiceProvider?.GetService<IHttpClientFactory>();
  var httpClient = factory?.CreateClient("QiitaClient");
  if (httpClient == null)
  {
    // エラー発生 - TODO
    return null;
  }

  string baseUrl = "/api/v2/authenticated_user/items";
  var lstPages = new List<ResponsePage>();
  int totalCount = 0;  // 全件数
  int limit = 20;      // 1回の取得件数
  int page = 1;        // ループ回数(1~)

  // 1回の処理は limit 件のページ取得なので、ループ処理とする
  while (true)
  {
    string targetUrl = baseUrl + $"?page={page}&per_page={limit}";
    using (var request = new HttpRequestMessage(HttpMethod.Get, targetUrl))
    using (var response = await httpClient.SendAsync(request))
    {
      if (response?.IsSuccessStatusCode == true)
      {
        var content = response.Content.ReadAsStringAsync().Result;
        var obj = System.Text.Json.JsonSerializer
                     .Deserialize<ResponsePage[]>(content);
        if (obj == null)
        {
          // エラー発生 - TODO
          return null;
        }
        if (totalCount == 0) // 初回
        {
          if (response.Headers.Contains("Total-Count") 
           && int.TryParse(response.Headers.GetValues("Total-Count").First(),
                                                      out int count))
          {
            totalCount = count;
          }
        }
        if (obj.Length > 0)
        {
          lstPages.AddRange(obj);
        }
      }
      else
      {
        // エラー発生 - TODO
        return null;
      }
    }
    // 残りがあるか?
    if (totalCount <= (page++ * limit))
    {
      break;
    }
  }
  return lstPages;
}
// JSON 用クラス
public class ResponsePage
{
  // 利用する項目のみ定義
  public required string title { get; set; }   // タイトル
  public DateTime created_at { get; set; }     // 作成日時
  public DateTime updated_at { get; set; }     // 更新日時
  public int? page_views_count { get; set; }   // ページビュー
  public int? likes_count { get; set; }        // Like数
  public int? stocks_count { get; set; }       // Skocks数
}

上記処理を以下のように呼び出します。

// Qiita API v2 - /api/v2/authenticated_user/items
var lstPages = await QiitaGetPageList();
// TODO - CSV出力など...

.NET Framework 4.8

.NET Framework 4.8 では、下記差分があるので、サンプルコードの一部を書き換えます。

  • null 許容参照型の明示は不要
    • MyServiceProvider、QiitaGetPageList 戻り値、および、JSON 用クラス
private static IServiceProvider MyServiceProvider = null;
// Qiita API v2 - /api/v2/authenticated_user/items
private async Task<List<ResponsePage>> QiitaGetPageList()
{
<中略>
}
// JSON 用クラス
public class ResponsePage
{
  // 利用する項目のみ定義
  public string title { get; set; }            // タイトル
  public DateTime created_at { get; set; }     // 作成日時
  public DateTime updated_at { get; set; }     // 更新日時
  public int? page_views_count { get; set; }   // ページビュー
  public int? likes_count { get; set; }        // Like数
  public int? stocks_count { get; set; }       // Skocks数
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?