AnkiConnect Python 実践レシピ フラッシュカード学習を効率化する自動化スクリプト集


# AnkiConnect + Python 実践レシピ: フラッシュカード学習を効率化する自動化スクリプト集

## はじめに: AnkiConnectとPythonで学習を自動化するメリット

Ankiは強力なフラッシュカードアプリですが、その真価はAnkiConnectというAPIによって飛躍的に向上します。Pythonと組み合わせることで、Ankiの可能性は無限に広がります。単純なカード作成の自動化にとどまらず、学習ログの高度な分析、Web上の最新情報との連携、AIを活用したリッチなカード生成など、創造的な学習体験を構築できます。この記事では、一般的な解説は避け、私が実際に試行錯誤の末にたどり着いた、ちょっと変わった、しかし効果的な自動化スクリプトのレシピを紹介します。単なる効率化ツールとしてではなく、Ankiを「成長する学習パートナー」に変貌させるためのヒントをお届けします。

## 開発環境構築: AnkiConnectのインストールとPython環境設定、ライブラリの準備

AnkiConnectのインストールは簡単ですが、Python環境構築で重要なのは**仮想環境の利用**です。プロジェクトごとに独立した環境を用意することで、依存関係の競合を避け、再現性を高めます。

```bash
# 仮想環境の作成
python3 -m venv .venv
# 仮想環境のアクティベート
source .venv/bin/activate  # Linux/macOSの場合
# .venv\Scripts\activate  # Windowsの場合
```

必要なライブラリは`requests` (AnkiConnectとの通信) が基本ですが、レシピによっては`beautifulsoup4`, `openai`, `Pillow`などが追加で必要になります。

```bash
pip install requests beautifulsoup4 openai Pillow
```

**ユニークなポイント**: 私はAnkiConnectのバージョン固定をおすすめします。AnkiConnectは頻繁にアップデートされますが、互換性が保証されているわけではありません。特定のバージョンで動作確認済みのスクリプトは、バージョン固定することで安定して動作させることができます。

```bash
pip install AnkiConnect==6.16.0 # 例：バージョン6.16.0をインストール
```

## AnkiConnect APIの基本: デッキ、ノート、カードの操作方法

AnkiConnect APIはJSON-RPC形式でリクエストを送信します。Pythonの`requests`ライブラリを使って、AnkiConnectにリクエストを送信し、レスポンスを受け取ります。

```python
import requests
import json

def invoke(action, version=6, params=None):
    requestJson = json.dumps({
        "action": action,
        "version": version,
        "params": params
    })
    response = requests.post('http://localhost:8765', data=requestJson).json()
    if len(response) != 2:
        raise Exception('response has an unexpected number of fields')
    if 'error' not in response:
        raise Exception('response is missing required error field')
    if 'result' not in response:
        raise Exception('response is missing required result field')
    if response['error'] is not None:
        raise Exception(response['error'])
    return response['result']

# デッキ一覧を取得
decks = invoke('deckNames')
print(decks)

# 新しいノートを作成
note = {
    "deckName": "Default",
    "modelName": "Basic",
    "fields": {
        "Front": "これはテストです",
        "Back": "This is a test."
    },
    "options": {
        "allowDuplicate": False,
        "duplicateScope": "deck"
    },
    "tags": ["python", "test"]
}

invoke('addNote', params={"note": note})
```

**ユニークなポイント**: エラーハンドリングを徹底することが重要です。AnkiConnectはエラーメッセージが分かりにくい場合があるため、例外処理を丁寧に行い、エラー発生時に詳細なログを出力するように心がけましょう。特に、`response['error']` の内容を詳しく解析することが、デバッグの鍵となります。

## レシピ1: 学習ログを自動で収集・分析し、弱点克服に役立てる

AnkiConnectを使って学習ログを収集し、pandasで分析することで、自分の弱点を可視化できます。ここでは、**カードごとの正答率推移**を分析し、苦手なカードを特定するスクリプトを紹介します。

```python
import requests
import json
import pandas as pd

def get_study_history(deck_name):
    """特定のデッキの学習履歴を取得する"""
    query = f'deck:"{deck_name}"'
    cards = invoke('findCards', params={'query': query})
    card_info = []
    for card_id in cards:
        card_history = invoke('cardInfo', params={'cards': [card_id]})[0]
        for review in card_history['history']:
            card_info.append({
                'card_id': card_id,
                'interval': review[0],
                'ease': review[1],
                'type': review[2],
                'time': review[3]
            })
    return pd.DataFrame(card_info)

# 学習履歴を取得
df = get_study_history("Japanese::Vocabulary")

# 各カードの正答率を計算（ease=1: 間違い, ease=2,3,4: 正解 とみなす）
df['correct'] = df['ease'].apply(lambda x: 1 if x > 1 else 0)
card_accuracy = df.groupby('card_id')['correct'].mean()

# 正答率が低いカードを抽出
weak_cards = card_accuracy[card_accuracy < 0.7].sort_values()

print("苦手なカード:")
print(weak_cards)
```

**ユニークなポイント**: 単純な正答率だけでなく、**間隔（interval）** と **ease** の関係を分析することで、より深い洞察が得られます。例えば、間隔が短くてもeaseが低いカードは、一時的に覚えていてもすぐに忘れてしまう可能性が高いことを示唆します。このようなカードに対しては、より丁寧な復習が必要となります。

## レシピ2: テキストファイルからAnkiカードを一括生成するスクリプト

テキストファイルからAnkiカードを生成するスクリプトは一般的ですが、ここでは**Markdown形式のテキストファイル**を解析し、画像や数式を埋め込んだリッチなカードを生成するスクリプトを紹介します。

```python
import re
import requests
import json
import markdown

def create_anki_card_from_markdown(deck_name, model_name, markdown_file):
    """MarkdownファイルからAnkiカードを生成する"""
    with open(markdown_file, 'r', encoding='utf-8') as f:
        markdown_text = f.read()

    # ---で区切られた部分をFrontとBackにする
    parts = markdown_text.split('---')
    if len(parts) != 2:
        raise ValueError("MarkdownファイルはFrontとBackを'---'で区切る必要があります。")

    front_markdown = parts[0].strip()
    back_markdown = parts[1].strip()

    # MarkdownをHTMLに変換
    front_html = markdown.markdown(front_markdown, extensions=['fenced_code', 'mdx_math'])
    back_html = markdown.markdown(back_markdown, extensions=['fenced_code', 'mdx_math'])


    note = {
        "deckName": deck_name,
        "modelName": model_name,
        "fields": {
            "Front": front_html,
            "Back": back_html
        },
        "options": {
            "allowDuplicate": False,
            "duplicateScope": "deck"
        },
        "tags": ["markdown"]
    }

    return invoke('addNote', params={"note": note})

# 例：markdown_file.mdからカードを生成
create_anki_card_from_markdown("Default", "Basic", "markdown_file.md")
```

**markdown_file.md の例:**

```markdown
# Front
What is the capital of France?

$$
E=mc^2
$$

---

# Back
Paris.

![Paris](https://example.com/paris.jpg)
```

**ユニークなポイント**:  Markdownの拡張機能 `fenced_code` (コードブロックの表示) と `mdx_math` (数式表示) を有効にすることで、コードや数式を美しく表示できます。また、画像URLをMarkdownに記述することで、画像を自動的にカードに埋め込むことができます。このスクリプトを応用すれば、LaTeX形式の数式を含む科学系の教材や、コード例を含むプログラミングの教材を効率的にAnkiカードに変換できます。

## レシピ3: Web API連携で最新情報をAnkiカードに自動追加する

ニュースAPIや辞書APIと連携することで、Ankiカードに最新情報を自動的に追加できます。ここでは、**Wikipedia API**と連携して、キーワードに関する情報をAnkiカードに自動追加するスクリプトを紹介します。

```python
import requests
import json
import wikipedia

def create_anki_card_from_wikipedia(deck_name, model_name, keyword):
    """Wikipedia APIから情報を取得してAnkiカードを生成する"""
    try:
        wikipedia.set_lang("ja") # 日本語Wikipedia
        page = wikipedia.page(keyword)
        title = page.title
        summary = wikipedia.summary(keyword, sentences=3) # 最初の3文を取得
        url = page.url

        note = {
            "deckName": deck_name,
            "modelName": model_name,
            "fields": {
                "Front": keyword,
                "Back": f"<b>{title}</b><br>{summary}<br><a href='{url}'>Wikipediaで詳細を見る</a>"
            },
            "options": {
                "allowDuplicate": False,
                "duplicateScope": "deck"
            },
            "tags": ["wikipedia"]
        }

        return invoke('addNote', params={"note": note})

    except wikipedia.exceptions.PageError:
        print(f"キーワード '{keyword}' に該当するWikipediaページが見つかりませんでした。")
        return None
    except wikipedia.exceptions.DisambiguationError as e:
        print(f"キーワード '{keyword}' は曖昧です。以下のいずれかのページを選択してください:\n{e.options}")
        return None


# 例：キーワード "深層学習" に関するカードを生成
create_anki_card_from_wikipedia("Default", "Basic", "深層学習")
```

**ユニークなポイント**:  `wikipedia` ライブラリを使うことで、Wikipedia APIへのアクセスが非常に簡単になります。エラーハンドリングを丁寧に行い、ページが見つからない場合や曖昧なキーワードが入力された場合に、適切なメッセージを表示するようにしています。また、取得した情報をHTML形式でカードに埋め込むことで、リンクや強調表示などのリッチな表現が可能になります。

## レシピ4: 画像認識AIと連携して画像付きカードを自動生成する

画像認識AIと連携することで、画像の内容に基づいてAnkiカードを自動生成できます。ここでは、**Google Cloud Vision API** と連携して、画像に写っている物体を認識し、その名前をカードに追加するスクリプトを紹介します。（APIキーが必要）

```python
import io
import os
import requests
import json
from google.cloud import vision

def create_anki_card_from_image(deck_name, model_name, image_path, api_key):
    """画像認識AIを使ってAnkiカードを生成する"""
    os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'path/to/your/credentials.json' # サービスアカウントキーのパス

    client = vision.ImageAnnotatorClient()

    with io.open(image_path, 'rb') as image_file:
        content = image_file.read()

    image = vision.Image(content=content)

    response = client.label_detection(image=image)
    labels = response.label_annotations

    # 認識されたラベルをAnkiカードに追加
    labels_str = ", ".join([label.description for label in labels])

    note = {
        "deckName": deck_name,
        "modelName": model_name,
        "fields": {
            "Front": f"<img src='{image_path}'>",
            "Back": f"この画像には何が写っていますか？<br>答え: {labels_str}"
        },
        "options": {
            "allowDuplicate": False,
            "duplicateScope": "deck"
        },
        "tags": ["image_recognition"]
    }

    return invoke('addNote', params={"note": note})

# 例：image.jpgに関するカードを生成 (APIキーが必要)
create_anki_card_from_image("Default", "Basic", "image.jpg", "YOUR_API_KEY")
```

**ユニークなポイント**:  Google Cloud Vision APIは非常に強力な画像認識能力を持っていますが、APIキーの設定や認証処理が少し複雑です。`GOOGLE_APPLICATION_CREDENTIALS` 環境変数を設定することで、認証を簡略化できます。また、画像ファイルを直接アップロードするのではなく、ローカルのパスを指定することで、大量の画像を処理する場合に効率が向上します。

## レシピ5: 音声合成APIと連携して音声付きカードを自動生成する

音声合成APIと連携することで、Ankiカードに音声を追加し、リスニング学習を強化できます。ここでは、**Google Text-to-Speech API** と連携して、テキストを音声ファイルに変換し、Ankiカードに埋め込むスクリプトを紹介します。（APIキーが必要）

```python
import os
import requests
import json
from google.cloud import texttospeech

def create_anki_card_with_audio(deck_name, model_name, text, api_key):
    """音声合成APIを使ってAnkiカードを生成する"""
    os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'path/to/your/credentials.json' # サービスアカウントキーのパス

    client = texttospeech.TextToSpeechClient()

    synthesis_input = texttospeech.SynthesisInput(text=text)

    voice = texttospeech.VoiceSelectionParams(
        language_code='ja-JP',
        name='ja-JP-Wavenet-A' # 日本語の音声を選択
    )

    audio_config = texttospeech.AudioConfig(
        audio_encoding=texttospeech.AudioEncoding.MP3
    )

    response = client.synthesize_speech(
        input=synthesis_input, voice=voice, audio_config=audio_config
    )

    # 音声ファイルを保存
    audio_file_name = f"{text.replace(' ', '_')}.mp3"
    with open(audio_file_name, 'wb') as out:
        out.write(response.audio_content)
        print(f'Audio content written to file "{audio_file_name}"')

    # Ankiカードを作成
    note = {
        "deckName": deck_name,
        "modelName": model_name,
        "fields": {
            "Front": text,
            "Back": f"[sound:{audio_file_name}]" # 音声ファイルを埋め込む
        },
        "options": {
            "allowDuplicate": False,
            "duplicateScope": "deck"
        },
        "tags": ["audio"]
    }

    return invoke('addNote', params={"note": note})

# 例：テキスト "こんにちは" に関するカードを生成 (APIキーが必要)
create_anki_card_with_audio("Default", "Basic", "こんにちは", "YOUR_API_KEY")
```

**ユニークなポイント**:  Google Text-to-Speech APIは高品質な音声合成を提供しますが、APIキーの設定が必要です。また、音声ファイル名はAnkiが認識できる形式にする必要があります。`[sound:{audio_file_name}]` のように、`[sound:...]` タグで音声ファイルを指定することで、Ankiが自動的に音声を再生してくれます。このスクリプトを応用すれば、外国語学習や、発音練習に役立つAnkiカードを簡単に作成できます。

## トラブルシューティング: よくあるエラーとその解決策

AnkiConnectの利用時に発生しやすいエラーは、APIリクエストの形式の間違い、AnkiConnectが起動していない、ポート番号が間違っているなどです。

**特殊なケース**: AnkiConnectが起動しているにも関わらず、`requests.exceptions.ConnectionError: HTTPConnectionPool` が発生する場合、AnkiConnectの設定で**"Webサーバーを起動する"** にチェックが入っているか確認してください。また、ファイアウォールがAnkiConnectの通信をブロックしている可能性も考慮してください。

**高度な問題解決**: 複数のAnkiConnectクライアントが同時にアクセスすると、競合が発生する可能性があります。このような場合は、リクエストをキューイングする仕組みを導入したり、リトライ処理を追加したりすることで、問題を回避できます。

## セキュリティとプライバシー: AnkiConnect利用時の注意点

AnkiConnectはローカルネットワーク上で動作するため、基本的には安全ですが、**公開されたネットワーク上でAnkiConnectを起動することは避けるべき**です。また、AnkiConnectのAPIキーを公開しないように注意してください。

**重要な注意点**: スクリプトにAPIキーを埋め込むのではなく、環境変数からAPIキーを読み込むようにすることで、セキュリティリスクを軽減できます。

## ベストプラクティス: 効率的な自動化スクリプトの設計と運用

効率的な自動化スクリプトを設計するためには、以下の点に注意してください。

*   **モジュール化**: 機能を細かく分割し、再利用可能なモジュールとして実装する。
*   **設定ファイル**: デッキ名、モデル名、APIキーなどの設定をハードコードせず、設定ファイルから読み込むようにする。
*   **ロギング**: スクリプトの動作状況を記録し、エラー発生時に原因を特定しやすくする。
*   **テスト**: 自動化スクリプトが正しく動作することを確認するために、テストコードを作成する。

**独自の視点**: 自動化スクリプトは、一度作ったら終わりではありません。学習の進捗や、Ankiのアップデートに合わせて、定期的にメンテナンスを行うことが重要です。

## まとめ: AnkiConnectとPythonで広がる学習の可能性

AnkiConnectとPythonを組み合わせることで、フラッシュカード学習は、単なる暗記ツールから、**創造的でインタラクティブな学習プラットフォーム**へと進化します。この記事で紹介したレシピは、ほんの一例に過ぎません。あなたのアイデア次第で、Ankiの可能性は無限に広がります。ぜひ、AnkiConnectとPythonを使って、自分だけの学習環境を構築してみてください。

## 関連リソース

**Zenn.book**
[AnkiConnect × Python: フラッシュカード学習を極める - 自動化レシピと高度なカスタマイズ](https://zenn.dev/idev/books/book-20250304-045421)

本書では、AnkiConnectとPythonを活用した自動化スクリプトの作成方法を体系的に解説しています。外部APIとの連携やデータ解析の手法も詳細に紹介。自動化による学習の最適化に興味のある方はご活用ください。