LoginSignup
0
2

Strava API を使ってアクティビティデータを Python で取得してみた

Last updated at Posted at 2023-12-17

ゴール

この記事では、Pythonを使用してStravaのAPIからアクティビティデータを取得し、そのデータを整理して出力します。

スタートライン

  • Pythonの基本的な知識
  • Stravaアカウント
  • Strava APIのクライアントIDとクライアントシークレット(StravaのWebサイトで取得)

環境

  • Windows 11
  • Python 3.11.5
  • requests ライブラリ
  • python-dotenv ライブラリ

ステップ1 環境変数の設定

今回のPythonファイルを実行するディレクトリに.envファイルを作成します。
https://www.strava.com/settings/api にアクセスし、クライアントシークレットキーを取得して、設定します。
STRAVA_TOKENは後ほど取得します。

.env
STRAVA_CLIENT_SECRET = "<YOUR STRAVA CLIENT SECRET>"
STRAVA_TOKEN = ""

  
もし、StravaのAPIキー未作成の方は、以下の記事を参考に作成してみてください。

ステップ2 Strava API で認証コードを取得

token.pyを作成し、以下のコードを追加してください。
YOUR CLIENT ID部分はご自身のクライアントIDに置き換えてください。

token.py
import requests
from dotenv import load_dotenv

load_dotenv()
import os

client_id = "<YOUR CLIENT ID>"
client_secret = os.environ["STRAVA_CLIENT_SECRET"]
redirect_uri = "http://localhost/"

request_url = (
    f"http://www.strava.com/oauth/authorize?client_id={client_id}"
    f"&response_type=code&redirect_uri={redirect_uri}"
    f"&approval_prompt=force"
    f"&scope=profile:read_all,activity:read_all"
)

print("クリックしてください:", request_url)
print("アプリを認証し、生成されたコードを以下のURLにコピー&ペーストしてください。")
code = input("URLからコードを貼り付ける: ")

このコードは、ユーザーがStravaの認証ページにアクセスし、アプリケーションに必要な権限を与えるためのURLを生成します。ユーザーが認証を完了すると、リダイレクトURIに認証コードが付与されます。このコードは次のステップでアクセストークンを取得するために使用されます。

ステップ3 アクセストークンを取得

token.pyに以下のコードを追加します。

token = requests.post(
    url="https://www.strava.com/api/v3/oauth/token",
    data={
        "client_id": client_id,
        "client_secret": client_secret,
        "code": code,
        "grant_type": "authorization_code",
    },
)

strava_token = token.json()
print(".envにアクセストークンを追加する", strava_token["access_token"])

このステップでは、先ほどの認証コードを使用してStrava APIからアクセストークンを取得します。このトークンは、APIリクエストを認証するために必要です。

ステップ4 token.pyの実行

token.pyを実行します。

クリックしてください: http://www.strava.com/oauth/authorize?client_id=53395&response_type=code&redirect_uri=http://localhost/&approval_prompt=force&scope=profile:read_all,activity:read_all
アプリを認証し、生成されたコードを以下のURLにコピー&ペーストしてください。
URLからコードを貼り付ける:

  
「クリックしてください」のURLをクリックすると、以下のような画面が表示されるので、「許可する」を選択します。

image.png
  
リダイレクト先のURLのcode部分をコピーします。
以下の画像の赤で塗りつぶされた四角の部分です。

記事投稿用 (3).png
  
コピーしたコードを先ほどのターミナル上で貼り付けるとアクセストークンが発行されます。

クリックしてください: http://www.strava.com/oauth/authorize?client_id=53395&response_type=code&redirect_uri=http://localhost/&approval_prompt=force&scope=profile:read_all,activity:read_all
アプリを認証し、生成されたコードを以下のURLにコピー&ペーストしてください。
URLからコードを貼り付ける: [先ほどコピーしたコードを貼り付ける]
.envにアクセストークンを追加する [アクセストークン]

  
発行されたアクセストークンを.envファイルに指定します。

.env
STRAVA_CLIENT_SECRET = "<YOUR STRAVA CLIENT SECRET>"
STRAVA_TOKEN = "<YOUR STRAVA TOKEN>"

ステップ5 アクティビティデータを取得して整理

activity.pyを作成し、以下のコードを追加してください。

activity.py
import os
import requests
from dotenv import load_dotenv

load_dotenv()

import requests
import json

url = "https://www.strava.com/api/v3/athlete/activities"
access_token = os.environ["STRAVA_TOKEN"]

headers = {"Authorization": f"Bearer {access_token}"}

response = requests.get(url, headers=headers)

activities = response.json()

activities_list = []
for activity in activities:
    activity_info = {
        "id": activity.get("id"),
        "name": activity.get("name"),
        "distance": activity.get("distance"),
        "moving_time": activity.get("moving_time"),
        "elapsed_time": activity.get("elapsed_time"),
        "total_elevation_gain": activity.get("total_elevation_gain"),
        "type": activity.get("type"),
        "start_date": activity.get("start_date"),
        "start_date_local": activity.get("start_date_local"),
        "timezone": activity.get("timezone"),
        "utc_offset": activity.get("utc_offset"),
        "average_speed": activity.get("average_speed"),
        "max_speed": activity.get("max_speed"),
        "average_cadence": activity.get("average_cadence"),
        "average_temp": activity.get("average_temp"),
        "average_heartrate": activity.get("average_heartrate"),
        "max_heartrate": activity.get("max_heartrate"),
    }
    activities_list.append(activity_info)

print(json.dumps(activities_list, indent=4))

このコードでは、Strava APIを使用してアクティビティデータを取得し、そのデータを整理してリストに格納しています。取得したデータはJSON形式で出力されます。

ステップ6 activity.pyの実行

activity.pyを実行します。
最新のアクティビティがjson形式で30件取得できます。

[
    {
        "id": 10386737564,
        "name": "Lunch Run",
        "distance": 2199.1,
        "moving_time": 609,
        "elapsed_time": 1285,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-16T02:05:25Z",
        "start_date_local": "2023-12-16T11:05:25Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.611,
        "max_speed": 6.258,
        "average_cadence": 87.6,
        "average_temp": 19,
        "average_heartrate": 131.5,
        "max_heartrate": 155.0
    },
    {
        "id": 10386565542,
        "name": "Morning Run",
        "distance": 1381.5,
        "moving_time": 393,
        "elapsed_time": 872,
        "total_elevation_gain": 6.0,
        "type": "Run",
        "start_date": "2023-12-16T01:02:07Z",
        "start_date_local": "2023-12-16T10:02:07Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.515,
        "max_speed": 5.812,
        "average_cadence": 86.9,
        "average_temp": 18,
        "average_heartrate": 131.0,
        "max_heartrate": 155.0
    },
    {
        "id": 10386453730,
        "name": "Morning Run",
        "distance": 1546.5,
        "moving_time": 521,
        "elapsed_time": 521,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-16T00:25:05Z",
        "start_date_local": "2023-12-16T09:25:05Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 2.968,
        "max_speed": 3.964,
        "average_cadence": 85.7,
        "average_temp": 21,
        "average_heartrate": 131.1,
        "max_heartrate": 146.0
    },
    {
        "id": 10381558391,
        "name": "Morning Run",
        "distance": 12006.7,
        "moving_time": 4044,
        "elapsed_time": 4044,
        "total_elevation_gain": 15.0,
        "type": "Run",
        "start_date": "2023-12-14T21:42:50Z",
        "start_date_local": "2023-12-15T06:42:50Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 2.969,
        "max_speed": 3.984,
        "average_cadence": 85.2,
        "average_temp": 21,
        "average_heartrate": 137.2,
        "max_heartrate": 153.0
    },
    {
        "id": 10376442702,
        "name": "Morning Run",
        "distance": 3724.0,
        "moving_time": 1258,
        "elapsed_time": 1258,
        "total_elevation_gain": 12.0,
        "type": "Run",
        "start_date": "2023-12-13T22:34:25Z",
        "start_date_local": "2023-12-14T07:34:25Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 2.96,
        "max_speed": 3.668,
        "average_cadence": 85.4,
        "average_temp": 13,
        "average_heartrate": 149.8,
        "max_heartrate": 158.0
    },
    {
        "id": 10376440203,
        "name": "Morning Run",
        "distance": 6748.9,
        "moving_time": 2059,
        "elapsed_time": 2068,
        "total_elevation_gain": 6.0,
        "type": "Run",
        "start_date": "2023-12-13T21:45:50Z",
        "start_date_local": "2023-12-14T06:45:50Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.278,
        "max_speed": 3.852,
        "average_cadence": 86.0,
        "average_temp": 17,
        "average_heartrate": 135.8,
        "max_heartrate": 153.0
    },
    {
        "id": 10373471072,
        "name": "Evening Run",
        "distance": 2017.4,
        "moving_time": 708,
        "elapsed_time": 708,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-13T11:44:42Z",
        "start_date_local": "2023-12-13T20:44:42Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 2.849,
        "max_speed": 3.62,
        "average_cadence": 86.2,
        "average_temp": 14,
        "average_heartrate": 135.1,
        "max_heartrate": 147.0
    },
    {
        "id": 10373348485,
        "name": "Evening Run",
        "distance": 7333.3,
        "moving_time": 1557,
        "elapsed_time": 1573,
        "total_elevation_gain": 1.0,
        "type": "Run",
        "start_date": "2023-12-13T11:03:02Z",
        "start_date_local": "2023-12-13T20:03:02Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 4.71,
        "max_speed": 6.322,
        "average_cadence": 88.0,
        "average_temp": 15,
        "average_heartrate": 144.8,
        "max_heartrate": 158.0
    },
    {
        "id": 10373163073,
        "name": "Evening Run",
        "distance": 2037.5,
        "moving_time": 601,
        "elapsed_time": 601,
        "total_elevation_gain": 2.0,
        "type": "Run",
        "start_date": "2023-12-13T10:39:46Z",
        "start_date_local": "2023-12-13T19:39:46Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.39,
        "max_speed": 4.348,
        "average_cadence": 85.6,
        "average_temp": 17,
        "average_heartrate": 136.8,
        "max_heartrate": 151.0
    },
    {
        "id": 10361039846,
        "name": "Morning Run",
        "distance": 10276.5,
        "moving_time": 2774,
        "elapsed_time": 2777,
        "total_elevation_gain": 14.0,
        "type": "Run",
        "start_date": "2023-12-10T22:10:39Z",
        "start_date_local": "2023-12-11T07:10:39Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.705,
        "max_speed": 4.376,
        "average_cadence": 84.8,
        "average_temp": 19,
        "average_heartrate": 148.2,
        "max_heartrate": 173.0
    },
    {
        "id": 10356566613,
        "name": "Afternoon Run",
        "distance": 11805.8,
        "moving_time": 3671,
        "elapsed_time": 3672,
        "total_elevation_gain": 14.0,
        "type": "Run",
        "start_date": "2023-12-10T07:37:23Z",
        "start_date_local": "2023-12-10T16:37:23Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.216,
        "max_speed": 4.0,
        "average_cadence": 84.5,
        "average_temp": 21,
        "average_heartrate": 138.1,
        "max_heartrate": 150.0
    },
    {
        "id": 10351174510,
        "name": "Afternoon Run",
        "distance": 3269.9,
        "moving_time": 1260,
        "elapsed_time": 1260,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-09T07:05:05Z",
        "start_date_local": "2023-12-09T16:05:05Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 2.595,
        "max_speed": 3.274,
        "average_cadence": 85.6,
        "average_temp": 25,
        "average_heartrate": 137.7,
        "max_heartrate": 151.0
    },
    {
        "id": 10351088686,
        "name": "Afternoon Run",
        "distance": 5117.2,
        "moving_time": 1051,
        "elapsed_time": 1051,
        "total_elevation_gain": 1.0,
        "type": "Run",
        "start_date": "2023-12-09T06:23:03Z",
        "start_date_local": "2023-12-09T15:23:03Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 4.869,
        "max_speed": 5.988,
        "average_cadence": 91.4,
        "average_temp": 25,
        "average_heartrate": 192.2,
        "max_heartrate": 200.0
    },
    {
        "id": 10350990778,
        "name": "Afternoon Run",
        "distance": 205.0,
        "moving_time": 40,
        "elapsed_time": 40,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-09T05:37:36Z",
        "start_date_local": "2023-12-09T14:37:36Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 5.126,
        "max_speed": 5.472,
        "average_cadence": 92.4,
        "average_temp": 23,
        "average_heartrate": 129.0,
        "max_heartrate": 152.0
    },
    {
        "id": 10350990633,
        "name": "Afternoon Run",
        "distance": 204.6,
        "moving_time": 40,
        "elapsed_time": 40,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-09T05:36:24Z",
        "start_date_local": "2023-12-09T14:36:24Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 5.116,
        "max_speed": 5.478,
        "average_cadence": 91.8,
        "average_temp": 24,
        "average_heartrate": 114.4,
        "max_heartrate": 128.0
    },
    {
        "id": 10350990467,
        "name": "Afternoon Run",
        "distance": 1800.5,
        "moving_time": 461,
        "elapsed_time": 461,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-09T05:26:08Z",
        "start_date_local": "2023-12-09T14:26:08Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.906,
        "max_speed": 4.546,
        "average_cadence": 85.7,
        "average_temp": 24,
        "average_heartrate": 164.9,
        "max_heartrate": 181.0
    },
    {
        "id": 10345232017,
        "name": "Morning Run",
        "distance": 10474.2,
        "moving_time": 3182,
        "elapsed_time": 3182,
        "total_elevation_gain": 5.0,
        "type": "Run",
        "start_date": "2023-12-07T21:45:02Z",
        "start_date_local": "2023-12-08T06:45:02Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.292,
        "max_speed": 3.878,
        "average_cadence": 86.5,
        "average_temp": 11,
        "average_heartrate": 143.1,
        "max_heartrate": 156.0
    },
    {
        "id": 10340205704,
        "name": "Morning Run",
        "distance": 11807.3,
        "moving_time": 3645,
        "elapsed_time": 3645,
        "total_elevation_gain": 12.0,
        "type": "Run",
        "start_date": "2023-12-06T21:39:21Z",
        "start_date_local": "2023-12-07T06:39:21Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.239,
        "max_speed": 4.158,
        "average_cadence": 85.5,
        "average_temp": 16,
        "average_heartrate": 141.2,
        "max_heartrate": 156.0
    },
    {
        "id": 10337091503,
        "name": "Evening Run",
        "distance": 1255.5,
        "moving_time": 480,
        "elapsed_time": 480,
        "total_elevation_gain": 1.0,
        "type": "Run",
        "start_date": "2023-12-06T11:37:08Z",
        "start_date_local": "2023-12-06T20:37:08Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 2.616,
        "max_speed": 3.314,
        "average_cadence": 85.0,
        "average_temp": 16,
        "average_heartrate": 148.4,
        "max_heartrate": 158.0
    },
    {
        "id": 10337012170,
        "name": "Evening Run",
        "distance": 4534.9,
        "moving_time": 972,
        "elapsed_time": 972,
        "total_elevation_gain": 1.0,
        "type": "Run",
        "start_date": "2023-12-06T11:07:27Z",
        "start_date_local": "2023-12-06T20:07:27Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 4.665,
        "max_speed": 6.15,
        "average_cadence": 89.4,
        "average_temp": 17,
        "average_heartrate": 152.5,
        "max_heartrate": 166.0
    },
    {
        "id": 10336830661,
        "name": "Evening Run",
        "distance": 2344.2,
        "moving_time": 645,
        "elapsed_time": 645,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-06T10:40:08Z",
        "start_date_local": "2023-12-06T19:40:08Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.634,
        "max_speed": 4.744,
        "average_cadence": 86.6,
        "average_temp": 23,
        "average_heartrate": 137.4,
        "max_heartrate": 153.0
    },
    {
        "id": 10324615724,
        "name": "Morning Run",
        "distance": 15072.0,
        "moving_time": 4510,
        "elapsed_time": 4510,
        "total_elevation_gain": 15.0,
        "type": "Run",
        "start_date": "2023-12-03T21:36:21Z",
        "start_date_local": "2023-12-04T06:36:21Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.342,
        "max_speed": 4.046,
        "average_cadence": 88.2,
        "average_temp": 11,
        "average_heartrate": 142.6,
        "max_heartrate": 156.0
    },
    {
        "id": 10319301286,
        "name": "Morning Run",
        "distance": 1696.9,
        "moving_time": 314,
        "elapsed_time": 314,
        "total_elevation_gain": 14.0,
        "type": "Run",
        "start_date": "2023-12-03T01:19:46Z",
        "start_date_local": "2023-12-03T10:19:46Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 5.404,
        "max_speed": 6.326,
        "average_cadence": 93.9,
        "average_temp": 22,
        "average_heartrate": 141.8,
        "max_heartrate": 159.0
    },
    {
        "id": 10319174762,
        "name": "Morning Run",
        "distance": 171.4,
        "moving_time": 30,
        "elapsed_time": 30,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-03T00:50:27Z",
        "start_date_local": "2023-12-03T09:50:27Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 5.714,
        "max_speed": 5.972,
        "average_cadence": 99.6,
        "average_temp": 17,
        "average_heartrate": 100.7,
        "max_heartrate": 111.0
    },
    {
        "id": 10319174531,
        "name": "Morning Run",
        "distance": 153.4,
        "moving_time": 25,
        "elapsed_time": 25,
        "total_elevation_gain": 0.0,
        "type": "Run",
        "start_date": "2023-12-03T00:49:03Z",
        "start_date_local": "2023-12-03T09:49:03Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 6.134,
        "max_speed": 6.672,
        "average_cadence": 104.7,
        "average_temp": 18,
        "average_heartrate": 76.9,
        "max_heartrate": 90.0
    },
    {
        "id": 10319174185,
        "name": "Morning Run",
        "distance": 3546.4,
        "moving_time": 900,
        "elapsed_time": 900,
        "total_elevation_gain": 14.0,
        "type": "Run",
        "start_date": "2023-12-03T00:30:23Z",
        "start_date_local": "2023-12-03T09:30:23Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.94,
        "max_speed": 4.91,
        "average_cadence": 86.0,
        "average_temp": 18,
        "average_heartrate": 147.4,
        "max_heartrate": 162.0
    },
    {
        "id": 10314570922,
        "name": "Afternoon Run",
        "distance": 8519.3,
        "moving_time": 2820,
        "elapsed_time": 2820,
        "total_elevation_gain": 43.0,
        "type": "Run",
        "start_date": "2023-12-02T07:39:14Z",
        "start_date_local": "2023-12-02T16:39:14Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.021,
        "max_speed": 4.032,
        "average_cadence": 85.7,
        "average_temp": 17,
        "average_heartrate": 149.9,
        "max_heartrate": 174.0
    },
    {
        "id": 10313577291,
        "name": "Morning Run",
        "distance": 8317.3,
        "moving_time": 2589,
        "elapsed_time": 2589,
        "total_elevation_gain": 42.0,
        "type": "Run",
        "start_date": "2023-12-01T23:31:54Z",
        "start_date_local": "2023-12-02T08:31:54Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.213,
        "max_speed": 4.238,
        "average_cadence": 85.9,
        "average_temp": 15,
        "average_heartrate": 146.2,
        "max_heartrate": 167.0
    },
    {
        "id": 10308646155,
        "name": "Morning Run",
        "distance": 15070.7,
        "moving_time": 4511,
        "elapsed_time": 4511,
        "total_elevation_gain": 16.0,
        "type": "Run",
        "start_date": "2023-11-30T21:36:50Z",
        "start_date_local": "2023-12-01T06:36:50Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.341,
        "max_speed": 4.054,
        "average_cadence": 86.6,
        "average_temp": 15,
        "average_heartrate": 145.4,
        "max_heartrate": 160.0
    },
    {
        "id": 10303511405,
        "name": "Morning Run",
        "distance": 15049.8,
        "moving_time": 4591,
        "elapsed_time": 4597,
        "total_elevation_gain": 16.0,
        "type": "Run",
        "start_date": "2023-11-29T21:39:00Z",
        "start_date_local": "2023-11-30T06:39:00Z",
        "timezone": "(GMT+09:00) Asia/Tokyo",
        "utc_offset": 32400.0,
        "average_speed": 3.278,
        "max_speed": 4.19,
        "average_cadence": 86.3,
        "average_temp": 15,
        "average_heartrate": 134.2,
        "max_heartrate": 161.0
    }
]

フィニッシュ

お疲れ様でした!
以下のXアカウントでも情報発信を行っていますので、ぜひフォローしてください!

参考文献

0
2
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
0
2