3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PowerShellでQiitaAPI入門(ステップ5指定タグ全記事取得中の複数キー集計)

Posted at

はじめに

PowerShellでQiitaAPI入門のステップ5です。今回は指定タグの全記事取得中の集計その2として複数キーによる集計を行います。具体的には年度別ユーザー別のような集計です。

前提条件

Windows11 Pro 22H2 22621.4169
PowerShell psversion 5.1.22621.4249
QiitaAPI 2.0

実行例(ステップ5)

PowerShellではInvoke-RestMethodを使ってQiitaAPIにアクセスします。

指定タグの記事取得(ページネーション指定してループ 重複ID除外+複数キー集計)

ステップ4を継承して全件の記事をためこまず、ページネーション実行中に集計を行います。その際にキー集計を入れ子にします。
具体的にはユーザ別の記事数といいね数を年度別に集計してみます。そのためには、ハッシュテーブルの構造を年度別にユーザ別データを保持するようにします。

コマンド文

# 特定のタグ名 
$tag_name = (タグ名)
# ページネーション設定 
$page = (ページ位置初期値)
$per_page = (1ページあたりの記事数)
# 記事ID格納変数
$articleIds = @() 
# 年度別の集計用ハッシュテーブル 
$yearlyStats = @{} 

# 〇ループ開始
# 1ページあたり記事格納変数初期化
# APIエンドポイントのURL(ページネーションのページ位置変化)
# APIリクエストを送信 
#  〇レスポンスのアイテムでループ開始
#  ◇記事ID格納変数にレスポンスアイテムの記事IDが含まれない場合 
#    レスポンスアイテムを1ページあたり記事格納変数に追加
#    レスポンスアイテムの記事IDを記事ID格納変数に追加
#  〇レスポンスのアイテムでループ終端
#
#  〇1ページあたり記事格納変数でループ開始
#   記事の年を年変数にセット
#   記事のユーザーIDをユーザーID変数にセット
#   ◇年度別の集計用ハッシュテーブルのキーに年変数が存在しない場合
#     年変数のハッシュテーブルを初期化
#   ◇年度別ユーザーIDの集計用ハッシュテーブル[年変数]のキーにユーザーID変数が存在しない場合
#     年変数ユーザーIDの集計用ハッシュテーブル[年変数]を初期化
#
#   各記事の投稿年ユーザーIDの記事数といいね数を集計 
#  〇1ページあたり記事格納変数でループ終端
#
# 次のページへ (ページネーションのページ位置カウントアップ)
# 〇ループ終端◇最後のページに到達したかを確認 


# 年度別の集計用ハッシュテーブル
$yearlyStats = @{}

do {
    $page_articles = @()
    $apiUrl = "https://qiita.com/api/v2/tags/$tag_name/items?page=$page&per_page=$per_page"
    $res = Invoke-RestMethod -Uri $apiUrl -Method Get

    foreach ($article in $res) {
        if (-not $articleIds.Contains($article.id)) {
            $page_articles += $article
            $articleIds += $article.id
        }
    }

    foreach ($article in $page_articles) {
        $year = (Get-Date $article.created_at).Year
        $userId = $article.user.id

        if (-not $yearlyStats.ContainsKey($year)) {
            $yearlyStats[$year] = @{}
        }

        if (-not $yearlyStats[$year].ContainsKey($userId)) {
            $yearlyStats[$year][$userId] = @{
                ArticleCount = 0
                TotalLikes = 0
            }
        }

        $yearlyStats[$year][$userId].ArticleCount++
        $yearlyStats[$year][$userId].TotalLikes += $article.likes_count
    }

    $page++ 
} while ($res.Count -eq $per_page)


# 年度別ユーザー別の集計結果を表示 
foreach ($year in $yearlyStats.Keys | Sort-Object) {
    Write-Output "年度: $year"
    $stats = $yearlyStats[$year]
    
    foreach ($userId in $stats.Keys) {
        $userStats = $stats[$userId]
        Write-Output " ユーザーID: $userId"
        Write-Output "  記事数: $($userStats.ArticleCount)"
        Write-Output "  合計いいね数: $($userStats.TotalLikes)"
    }
}

実行結果

念のため初期設定から再実行しています。


PS C:\pmind> $tag_name = "mind"
PS C:\pmind> $page = 1
PS C:\pmind> $per_page = 100
PS C:\pmind> $all_articles = @()
PS C:\pmind> $articleIds = @()
PS C:\pmind> $yearlyStats = @{}
PS C:\pmind> do {
>>     $page_articles = @()
>>     $apiUrl = "https://qiita.com/api/v2/tags/$tag_name/items?page=$page&per_page=$per_page"
>>     $res = Invoke-RestMethod -Uri $apiUrl -Method Get
>>
>>     foreach ($article in $res) {
>>         if (-not $articleIds.Contains($article.id)) {
>>             $page_articles += $article
>>             $articleIds += $article.id
>>         }
>>     }
>>
>>     foreach ($article in $page_articles) {
>>         $year = (Get-Date $article.created_at).Year
>>         $userId = $article.user.id
>>
>>         if (-not $yearlyStats.ContainsKey($year)) {
>>             $yearlyStats[$year] = @{}
>>         }
>>
>>         if (-not $yearlyStats[$year].ContainsKey($userId)) {
>>             $yearlyStats[$year][$userId] = @{
>>                 ArticleCount = 0
>>                 TotalLikes = 0
>>             }
>>         }
>>
>>         $yearlyStats[$year][$userId].ArticleCount++
>>         $yearlyStats[$year][$userId].TotalLikes += $article.likes_count
>>     }
>>
>>     $page++
>> } while ($res.Count -eq $per_page)
PS C:\pmind> foreach ($year in $yearlyStats.Keys | Sort-Object) {
>>     Write-Output "年度: $year"
>>     $stats = $yearlyStats[$year]
>>
>>     foreach ($userId in $stats.Keys) {
>>         $userStats = $stats[$userId]
>>         Write-Output " ユーザーID: $userId"
>>         Write-Output "  記事数: $($userStats.ArticleCount)"
>>         Write-Output "  合計いいね数: $($userStats.TotalLikes)"
>>     }
>> }
年度: 2017
 ユーザーID: Kosen-amai
  記事数: 1
  合計いいね数: 2
 ユーザーID: MindZanmai
  記事数: 4
  合計いいね数: 8
 ユーザーID: killy
  記事数: 5
  合計いいね数: 35
 ユーザーID: t-tkd3a
  記事数: 6
  合計いいね数: 29
年度: 2018
 ユーザーID: killy
  記事数: 3
  合計いいね数: 6
年度: 2019
 ユーザーID: killy
  記事数: 3
  合計いいね数: 6
 ユーザーID: Snowman-s
  記事数: 2
  合計いいね数: 9
年度: 2020
 ユーザーID: ohisama@github
  記事数: 29
  合計いいね数: 2
 ユーザーID: Snowman-s
  記事数: 2
  合計いいね数: 5
 ユーザーID: Since1967
  記事数: 1
  合計いいね数: 1
年度: 2023
 ユーザーID: mylifewithviolin
  記事数: 43
  合計いいね数: 329
 ユーザーID: ohisama@github
  記事数: 29
  合計いいね数: 44
 ユーザーID: ITvision
  記事数: 5
  合計いいね数: 8
 ユーザーID: killy
  記事数: 6
  合計いいね数: 235
 ユーザーID: MindZanmai
  記事数: 2
  合計いいね数: 4
 ユーザーID: jpl_produire
  記事数: 1
  合計いいね数: 27
 ユーザーID: Mind-Club_2017
  記事数: 2
  合計いいね数: 3
年度: 2024
 ユーザーID: mylifewithviolin
  記事数: 88
  合計いいね数: 218
 ユーザーID: ohisama@github
  記事数: 33
  合計いいね数: 50
 ユーザーID: ITvision
  記事数: 12
  合計いいね数: 26
 ユーザーID: killy
  記事数: 13
  合計いいね数: 43
 ユーザーID: MindZanmai
  記事数: 2
  合計いいね数: 4
 ユーザーID: Chairs
  記事数: 1
  合計いいね数: 0
 ユーザーID: KajizukaTaichi
  記事数: 1
  合計いいね数: 2
 ユーザーID: Mind-Club_2017
  記事数: 6
  合計いいね数: 15

指定タグの記事取得(ページネーション指定してループ 重複ID除外+複数キー集計+並べ替え)

今度は記事数降順で並べ替えを行って集計値を出力してみます。GetEnumerator()メソッドを使ってハッシュテーブルを列挙し、Sort-ObjectでArticleCountプロパティに基づいて降順にソートします。

コマンド文

# 年度別ユーザー別の集計結果を表示(並べかえて出力) 
foreach ($year in $yearlyStats.Keys | Sort-Object) {
    Write-Output "年度: $year"
    $stats = $yearlyStats[$year]
    
    # ユーザー集計を記事数降順にソート
    $sortedStats = $stats.GetEnumerator() | Sort-Object -Property {$_.Value.ArticleCount} -Descending
    
    foreach ($entry in $sortedStats) {
        $userId = $entry.Key
        $userStats = $entry.Value
        Write-Output " ユーザーID: $userId"
        Write-Output "  記事数: $($userStats.ArticleCount)"
        Write-Output "  合計いいね数: $($userStats.TotalLikes)"
    }
}

実行結果

記事取得中の集計元データはリセットされていませんので、並べ替え集計表示のみ実行しています。

年度: 2017
 ユーザーID: t-tkd3a
  記事数: 6
  合計いいね数: 29
 ユーザーID: killy
  記事数: 5
  合計いいね数: 35
 ユーザーID: MindZanmai
  記事数: 4
  合計いいね数: 8
 ユーザーID: Kosen-amai
  記事数: 1
  合計いいね数: 2
年度: 2018
 ユーザーID: killy
  記事数: 3
  合計いいね数: 6
年度: 2019
 ユーザーID: killy
  記事数: 3
  合計いいね数: 6
 ユーザーID: Snowman-s
  記事数: 2
  合計いいね数: 9
年度: 2020
 ユーザーID: ohisama@github
  記事数: 29
  合計いいね数: 2
 ユーザーID: Snowman-s
  記事数: 2
  合計いいね数: 5
 ユーザーID: Since1967
  記事数: 1
  合計いいね数: 1
年度: 2023
 ユーザーID: mylifewithviolin
  記事数: 43
  合計いいね数: 329
 ユーザーID: ohisama@github
  記事数: 29
  合計いいね数: 44
 ユーザーID: killy
  記事数: 6
  合計いいね数: 235
 ユーザーID: ITvision
  記事数: 5
  合計いいね数: 8
 ユーザーID: Mind-Club_2017
  記事数: 2
  合計いいね数: 3
 ユーザーID: MindZanmai
  記事数: 2
  合計いいね数: 4
 ユーザーID: jpl_produire
  記事数: 1
  合計いいね数: 27
年度: 2024
 ユーザーID: mylifewithviolin
  記事数: 88
  合計いいね数: 218
 ユーザーID: ohisama@github
  記事数: 33
  合計いいね数: 50
 ユーザーID: killy
  記事数: 13
  合計いいね数: 43
 ユーザーID: ITvision
  記事数: 12
  合計いいね数: 26
 ユーザーID: Mind-Club_2017
  記事数: 6
  合計いいね数: 15
 ユーザーID: MindZanmai
  記事数: 2
  合計いいね数: 4
 ユーザーID: Chairs
  記事数: 1
  合計いいね数: 0
 ユーザーID: KajizukaTaichi
  記事数: 1
  合計いいね数: 2

おわりに

いかがでしたか?なにかの参考になれば幸いです。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?