はじめに
Qiitaの人気記事を自動で取得し、Notionデータベースに転送するCLIツールを作りました。
いいね(LGTM)またはStock数が指定した閾値以上の記事のみを対象とし、Notion DBのカラム(プロパティ)が足りなければ自動で追加する機能も実装しています。
作ったもの
- Qiita APIから過去N日分の記事を取得
- LGTMまたはStock数が指定値以上の人気記事を抽出
- 本文を自動要約(sumy + tinysegmenter)
- Notionデータベースにupsert(新規追加 or 更新)
- Notion DBにカラムがなければ自動で追加
- CLI対話式・自動化(定時実行)どちらも対応
技術スタック
- Python 3.11
- Qiita API
- Notion API
- sumy(要約)
- tinysegmenter(日本語分かち書き)
- pytest(テスト)
実装のポイント
1. CLI対話式・自動化両対応
# 対話式(手動実行)
python main.py
# 自動化(定時実行)
python main.py --schedule --min-likes 500 --min-stocks 500 --backfill-days 1
- CLIで「最低いいね数」「最低ストック数」「バックフィル日数」を日本語で入力
- 全角/半角どちらも対応
-
--schedule
や--no-interactive
指定時は定時実行モード
2. Notion DBのカラム自動追加
def ensure_notion_properties(self) -> None:
"""Notion DBのプロパティが足りなければ自動で追加"""
current_properties = self.get_database_properties()
required_properties = {
"title": {"title": {}},
"url": {"url": {}},
"author": {"rich_text": {}},
"likes": {"number": {}},
"stocks": {"number": {}},
"tags": {"multi_select": {}},
"created_at": {"date": {}},
"summary": {"rich_text": {}}
}
# プロパティの追加処理...
3. エラーハンドリングとリトライ
def retry_with_backoff(func):
"""指数バックオフでリトライするデコレータ"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
max_retries = 3
base_delay = 1
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_retries - 1:
raise
delay = base_delay * (2 ** attempt)
time.sleep(delay)
return wrapper
4. 型ヒントとテスト
from typing import Dict, List, Optional
class NotionClient:
def get_database_properties(self) -> Dict[str, Dict]:
"""データベースのプロパティを取得"""
pass
def add_database_property(
self,
property_name: str,
property_type: str
) -> None:
"""プロパティを追加"""
pass
使い方
セットアップ
- リポジトリのクローン
git clone https://github.com/AirLabJP/QiitaNotionBridge.git
cd QiitaNotionBridge
- 必要なトークンの取得
- Qiitaアクセストークン(
read_qiita
スコープ) - Notion Integration Token
- Notion Database ID
- 環境変数の設定
cp .env.example .env
# .envファイルを編集
- 依存パッケージのインストール
pip install -r requirements.txt
実行方法
対話式(手動実行)
python main.py
自動化(定時実行)
python main.py --schedule --min-likes 500 --min-stocks 500 --backfill-days 1
バックフィル実行
python main.py --backfill days=3 --min-likes 300 --min-stocks 200
今後の展望
- Slack通知・Webhook連携
- タグごとの閾値設定
- Web UIやダッシュボード
- 要約の精度向上
まとめ
- Pythonで実用的なCLIツールを作成
- 型ヒント・テスト・エラーハンドリングを徹底
- 自動化と手動実行の両方に対応
- 拡張性を考慮した設計