Qiita API v2をPowerShellから実行してみる

管理用にQiitaに公開した記事の一覧を取得したいと調べてみたら、[Qiita API v2](https://qiita.com/api/v2/docs)としてAPIが公開されていました。

本記事では`Qiita API v2`を`PowerShell`から実行して指定ユーザの公開記事一覧を取得してみます。

## APIを実行するPowerShellコマンドレットについて

今現在の`Windows 10`では`curl.exe`が標準インストールされていますが、ここでは`PowerShell`の
`Invoke-WebRequest`コマンドレットを利用してAPIを実行しています。

`Invoke-RestMethod`でもいいのですが、`Windows PowerShell`だと`Invoke-RestMethod`にはレスポンスヘッダを取得する`ResponseHeaders`パラメータがないので`Windows PowerShell`と`PowerShell 7`の両方で動くにように書いたので今回は`Invoke-WebReques`を利用しています。

ちなみに`Invoke-WebRequest`のaliasは`iwr`。

更に余談ですが`Invoke-RestMethod`に`ResponseHeadersVariable`オプションが追加された経緯については下記に記載があったりします。

[New PowerShell Core Feature: Invoke-RestMethod -ResponseHeadersVariable
](https://get-powershellblog.blogspot.com/2017/09/new-powershell-core-feature-invoke.html)

## ドキュメント

- [Qiita API v2](https://qiita.com/api/v2/docs)

# Qiita API v2 の利用制限について

[Qiita API v2/利用制限](https://qiita.com/api/v2/docs#%E5%88%A9%E7%94%A8%E5%88%B6%E9%99%90)

2021年7月現在は下記のようになっていました。

![利用制限](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/027421c5-a67e-beeb-5af5-79bf24d822c5.png)

## まずは認証しないで使えるAPIを実行して任意のユーザの公開記事一覧を取得してみる

ドキュメントを読むと、指定されたユーザの記事一覧を、作成日時の降順で返す　`GET /api/v2/users/:user_id/items`　があったのでまずはこれを利用して指定ユーザの記事一覧を取得してみます。

[Qiita API v2/GET /api/v2/users/:user_id/items](https://qiita.com/api/v2/docs#get-apiv2usersuser_iditems)

```PowerShell
# Invoke-WebRequeset
iwr https://qiita.com/api/v2/users/SAITO_Keita/items
```

実行すると、ドキュメントにある通りの項目が`Content`に取得できている事が確認できます。

今回は記事一覧をつくりたかったので下記のようにして作成日、URL、タイトル、更新日付　項目を選択してみます。

```PowerShell
# select-objectで作成日、URL,タイトル、更新日付を取得
( iwr https://qiita.com/api/v2/users/SAITO_Keita/items | select-object -ExpandProperty content |  Convertfrom-Json ) | select-object created_at,url,title,updated_atat
```

これで指定したユーザの公開記事の一覧が取得できました。
ただし、ドキュメントを読むとページネーションの部分に一度に取得できる件数について記載があり、上記の例では`20`件までの記事一覧しか取得できません。

[Qiita API v2/ページネーション](https://qiita.com/api/v2/docs#%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%8D%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)

ドキュメントを読むと、

- レスポンスヘッダの`Total-Count`でアイテムの合計数
- `page`でページ指定
- `per_page`で1ページあたりに取得する要素の設定（デフォルト20,最大100）

と記載があるのでここらへんを考慮して全件取得する場合は下記のように`PowerShell`スクリプト`Get-PublicQiitaItemList.ps1`かいてみました。

やっている事としては、初回リクエスト時のレスポンスヘッダからアイテムの要素数を取得して、残りのページ回数分APIを実行してデータを取得しています。

```PowerShell:Get-PublicQiitaItemList.ps1
#!/usr/bin/env pwsh
<#
.SYNOPSIS
    qiitaの公開記事リストをとるやつ
.DESCRIPTION
    qiitaの公開記事リストをとるやつ
    qiitaのapi v2を利用しているので利用制限に引っかかるととまります
    https://qiita.com/api/v2/docs#利用制限
.EXAMPLE
    PS C:\> ./Get-PublicQiitaItemList.ps1 -UserId <<UserId>>
    PS C:\> "<<UserId>>"| ./Get-PublicQiitaItemList.ps1
.INPUTS
    System.String
.OUTPUTS
    System.Collections.ArrayList
.NOTES
    None
#>
param (
    [Parameter(ValueFromPipeline = $True, Mandatory = $True)]
    [String]$UserId
)

PROCESS {

    Set-StrictMode -Version Latest
    $ErrorActionPreference = "stop"

    # 出力用配列
    $output = New-Object System.Collections.ArrayList
    # 1ページ目取得
    $uri = ('https://qiita.com/api/v2/users/{0}/items??page=1&per_page=100' -f $UserId)
    $1stResponse = Invoke-WebRequest -Uri $uri
    $output += ( $1stResponse | Select-Object -ExpandProperty Content | ConvertFrom-Json ) | Select-Object created_at, url, title, updated_at

    #ページ処理
    #レスポンスヘッダから記事数を取得
    $totalCount = ([int[]]$1stResponse.Headers["Total-Count"])[0]
    # ページ数を計算
    $maxPage = [Math]::Ceiling($totalCount / 100)
    # 2ページ以降があったら取得
    for ($nowPage = 2; $nowPage -le $maxPage; $nowPage++) {
        $uri = 'https://qiita.com/api/v2/users/{0}/items?page={1}&per_page=100' -f $UserId, $nowPage
        $output += $(Invoke-WebRequest -Uri $uri | Select-Object -ExpandProperty Content |  ConvertFrom-Json) | Select-Object created_at, url, title, updated_at
    }

    Write-Output $output
}

```

## 認証して認証したユーザの記事一覧を取得してみる

ここでは認証したユーザの記事一覧を取得する`/api/v2/authenticated_user/items`を利用してみます。

[Qiita API v2/GET /api/v2/authenticated_user/items](https://qiita.com/api/v2/docs#get-apiv2authenticated_useritems)
[Qiita API v2/認証認可](https://qiita.com/api/v2/docs#%E8%AA%8D%E8%A8%BC%E8%AA%8D%E5%8F%AF)　

認証については　[認証認可](https://qiita.com/api/v2/docs#%E8%AA%8D%E8%A8%BC%E8%AA%8D%E5%8F%AF)　　に記載があり、[ユーザ管理画面/アプリケーション](https://qiita.com/settings/applications) から`アクセストークン`を取得してそれを`リクエストヘッダ`として送ってあげればよさそうです。


ユーザ管理画面のアプリケーションページで個人用アクセストークンを発行する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/25ef7757-e595-25a1-233a-a8b316dd2bc6.png)


[Qiita API v2/スコープ](https://qiita.com/api/v2/docs#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97)

今回は読みだしたいだけなので`read_qiita`を指定してアクセストークンの名前をqiita-readonlyとしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/5f3837a7-94de-03f4-8c9a-20f6c0c16977.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/2993492c-f9a8-6d5d-3ded-7c7fffdac778.png)

アクセストークンが発行されるのでこの文字列を控えておきます。

ここでも`GET /api/v2/users/:user_id/items`を実行したときと同様に`Invoke-RestMethod`を利用して`GET /api/v2/authenticated_user/items`を実行します。

```PowerShell
# headersでtokenを渡して　/api/v2/authenticated_user/items　を実行
$token="<<発行したトークン>>"
iwr https://qiita.com/api/v2/authenticated_user/items -Headers @{Authorization = "Bearer $token"}
```

実行してみると、認証しているユーザの記事一覧が出力され、こちらについては認証がなかった`GET /api/v2/users/:user_id/items`とは違い限定共有の記事も取得できているようです。
（`private`の項目が`True`になっている）

上記の例についてもページ処理をしていないので取得できるのは20件までなので全件取得する場合は下記のような`PowerShell`スクリプト`Get-AuthQiitaItamList.ps1`をかいてみました、

```PowerShell:Get-AuthQiitaItamList.ps1
#!/usr/bin/env pwsh
<#
.SYNOPSIS
    qiitaの認証ユーザの記事リストをとるやつ
.DESCRIPTION
    qiitaの認証ユーザの記事リストをとるやつ
    qiitaのapi v2を利用しているので利用制限に引っかかるととまります
    https://qiita.com/api/v2/docs#利用制限
    .EXAMPLE
    PS C:\> ./Get-AuthQiitaItamList.ps1 -Token <<access token>>
    PS C:\> "<<Token>>" | ./Get-AuthQiitaItamList.ps1
.INPUTS
    System.String
.OUTPUTS
    System.Collections.ArrayList
.NOTES
    None
#>

param (
    [Parameter(ValueFromPipeline = $True, Mandatory = $True)]
    [String]$Token
)
PROCESS {

    Set-StrictMode -Version Latest
    $ErrorActionPreference = "stop"

    # 認証用
    $headers = @{Authorization = "Bearer $Token" }

    # 出力用配列
    $output = New-Object System.Collections.ArrayList
    # 1ページ目取得
    $uri = 'https://qiita.com/api/v2/authenticated_user/items?page=1&per_page=100'
    $1stResponse = Invoke-WebRequest -Headers $headers -Uri $uri
    $output += ($1stResponse | Select-Object -ExpandProperty Content | ConvertFrom-Json ) | Select-Object created_at, url, title, updated_at, private

    #ページ処理
    #レスポンスヘッダから記事数を取得
    $totalCount = ([int[]]$1stResponse.Headers["Total-Count"])[0]
    # ページ数を計算
    $maxPage = [Math]::Ceiling($totalCount / 100)
    # 2ページ以降があったら取得
    for ($nowPage = 2; $nowPage -le $maxPage; $nowPage++) {
        $uri = 'https://qiita.com/api/v2/authenticated_user/items?page={1}&per_page=100' -f $userId, $nowPage
        $output += $(Invoke-WebRequest -Headers $headers -Uri $uri | Select-Object -ExpandProperty Content | ConvertFrom-Json) `
        | Select-Object created_at, url, title, updated_at, private
    }

    Write-Output $output
}

```

## 総評

Qiitaは技術者を対象としたサービスなだけあり、普通にAPIが用意されていて便利に使えるのはいいですね。

お手軽なんでたまには`PowerShell`からAPIを実行するのいかがでしょうか？