はじめに
特定期間の自身の活動を振り返るため、Qiitaの投稿数やリアクション数を集計するプログラムを作成しました。
コード
pip install pydantic-settings
qiita_count.py
import datetime
from collections import defaultdict
import requests
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
qiita_token: str = Field(..., description="Qiitaのアクセストークン")
start_month: str = Field(default="1900-01", description="合計期間の開始月")
end_month: str = Field(default="2100-01", description="合計期間の終了月")
model_config = SettingsConfigDict(
env_file=".env",
case_sensitive=False,
cli_parse_args=True,
extra="allow",
)
def main():
# 設定の読み込み
settings = Settings()
# ここにQiitaのアクセストークンを設定
ACCESS_TOKEN = settings.qiita_token
headers = {"Authorization": f"Bearer {ACCESS_TOKEN}"}
# 認証済みユーザーの投稿を取得するエンドポイント
url = "https://qiita.com/api/v2/authenticated_user/items"
items = []
page = 1
per_page = 100 # 1ページあたりの取得件数
# ページネーションに対応してすべての投稿を取得する
while True:
params = {"page": page, "per_page": per_page}
resp = requests.get(url, headers=headers, params=params)
if resp.status_code != 200:
print("Error:", resp.text)
break
data = resp.json()
if not data: # 取得データがなくなったらループ終了
break
items.extend(data)
page += 1
# 月ごとの投稿数とリアクション数を集計する
monthly_stats = defaultdict(
lambda: {
"post_count": 0,
"likes_count": 0,
"stocks_count": 0,
"page_views_count": 0,
}
)
for item in items:
created_at = item.get("created_at")
# 日時文字列をdatetimeオブジェクトに変換
dt = datetime.datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%S%z")
month_str = dt.strftime("%Y-%m")
if settings.start_month <= month_str <= settings.end_month:
monthly_stats[month_str]["post_count"] += 1
monthly_stats[month_str]["likes_count"] += item.get("likes_count", 0)
monthly_stats[month_str]["stocks_count"] += item.get("stocks_count", 0)
monthly_stats[month_str]["page_views_count"] += item.get(
"page_views_count", 0
)
# 結果の出力
for month, stats in sorted(monthly_stats.items()):
print(
f"{month}: 投稿数: {stats['post_count']}, いいね数: {stats['likes_count']}, ストック数: {stats['stocks_count']}, 閲覧数: {stats['page_views_count']}"
)
# 指定された期間の合計を計算
total_posts = sum(
monthly_stats[m]["post_count"]
for m in monthly_stats
if settings.start_month <= m <= settings.end_month
)
total_reactions = sum(
monthly_stats[m]["likes_count"] + monthly_stats[m]["stocks_count"]
for m in monthly_stats
if settings.start_month <= m <= settings.end_month
)
total_page_views = sum(
monthly_stats[m]["page_views_count"]
for m in monthly_stats
if settings.start_month <= m <= settings.end_month
)
print(f"\n{settings.start_month}から{settings.end_month}の合計:")
print(f"投稿数: {total_posts}")
print(f"リアクション数: {total_reactions}")
print(f"閲覧数: {total_page_views}")
if __name__ == "__main__":
main()
出力は以下のような感じです。
QIITA_TOKENを環境変数に設定しますstart_month、end_monthで指定した期間の月ごとの数値と合計を出力します。
合計を出力する際、いいね数とストック数はリアクション数としてまとめられます。
% python qiita_count.py --start_month 2024-10 --end_month 2025-03
2024-10: 投稿数: 19, いいね数: 13, ストック数: 4, 閲覧数: 15617
2024-11: 投稿数: 8, いいね数: 9, ストック数: 1, 閲覧数: 6732
2024-12: 投稿数: 6, いいね数: 3, ストック数: 3, 閲覧数: 3802
2025-01: 投稿数: 6, いいね数: 2, ストック数: 3, 閲覧数: 4291
2025-02: 投稿数: 5, いいね数: 1, ストック数: 0, 閲覧数: 1882
2025-03: 投稿数: 7, いいね数: 1, ストック数: 0, 閲覧数: 894
2024-10から2025-03の合計:
投稿数: 51
リアクション数: 40
閲覧数: 33218
解説
設定値の取得
pydantic-settingを使うことで、環境変数またはコマンドライン引数から必要な情報を取得します。両方で指定される場合はコマンドライン引数が優先されます。
class Settings(BaseSettings):
qiita_token: str = Field(..., description="Qiitaのアクセストークン")
start_month: str = Field(default="1900-01", description="合計期間の開始月")
end_month: str = Field(default="2100-01", description="合計期間の終了月")
model_config = SettingsConfigDict(
env_file=".env",
case_sensitive=False,
cli_parse_args=True,
extra="allow",
)
投稿数とリアクション数の取得
QIITA_TOKENの発行元ユーザのすべての投稿を取得し、月単位で合計します。
# 認証済みユーザーの投稿を取得するエンドポイント
url = "https://qiita.com/api/v2/authenticated_user/items"
items = []
page = 1
per_page = 100 # 1ページあたりの取得件数
# ページネーションに対応してすべての投稿を取得する
while True:
params = {"page": page, "per_page": per_page}
resp = requests.get(url, headers=headers, params=params)
if resp.status_code != 200:
print("Error:", resp.text)
break
data = resp.json()
if not data: # 取得データがなくなったらループ終了
break
items.extend(data)
page += 1
# 月ごとの投稿数とリアクション数を集計する
monthly_stats = defaultdict(
lambda: {
"post_count": 0,
"likes_count": 0,
"stocks_count": 0,
"page_views_count": 0,
}
)
for item in items:
created_at = item.get("created_at")
# 日時文字列をdatetimeオブジェクトに変換
dt = datetime.datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%S%z")
month_str = dt.strftime("%Y-%m")
if settings.start_month <= month_str <= settings.end_month:
monthly_stats[month_str]["post_count"] += 1
monthly_stats[month_str]["likes_count"] += item.get("likes_count", 0)
monthly_stats[month_str]["stocks_count"] += item.get("stocks_count", 0)
monthly_stats[month_str]["page_views_count"] += item.get(
"page_views_count", 0
)