🔗

PythonでQiitaの人気記事をNotionに自動転送するCLIツールを作った

に公開

はじめに

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

使い方

セットアップ

  1. リポジトリのクローン
git clone https://github.com/AirLabJP/QiitaNotionBridge.git
cd QiitaNotionBridge
  1. 必要なトークンの取得
  • Qiitaアクセストークン(read_qiitaスコープ)
  • Notion Integration Token
  • Notion Database ID
  1. 環境変数の設定
cp .env.example .env
# .envファイルを編集
  1. 依存パッケージのインストール
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ツールを作成
  • 型ヒント・テスト・エラーハンドリングを徹底
  • 自動化と手動実行の両方に対応
  • 拡張性を考慮した設計

参考リンク

Discussion