TOPIK中級単語1800のAnkiDeckをつくってみたやつの訂正記事
結構前にこのAnkiDeckを使ってみる内容の記事を出していました。
が、単語と音声の対応がずれちゃってる事例を見つけました。
一応直せたつもりなので訂正記事を出します:
https://anki-decks.com/anki-decks/korean/topik/
自分のAnkiDeckの作り方はこんな感じです(Linux環境前提です)
1) 見出し語の音声ファイルをダウンロードする
『韓国語能力試験 TOPIK 3・4級 中級単語1800』の公式サイトの
https://www.goken-net.co.jp/audio/#391 の
「無料音声(見出し語のみ)をダウンロードする」からダウンロードできます
ダウンロードできたら解凍して、中の0001.mp3 ~ 1800.mp3を適当なディレクトリを新規に作ってそこに移します(e.g., tango_mp3 ディレクトリ)。
(移すのはディレクトリ名が文字化けして厄介そうだったからです)
2) 音声ファイルへのパス一覧を抽出する
$ find tango_mp3 -type f | sort > audiopath.txt
3) .apkgファイルを解凍する
$ unzip TOPIK__.apkg
4) collection.anki21 ができるのでそこからスクリプトで、韓国語部分と日本語部分を取り出す
kr.txtに韓国語、ja.txtに日本語を格納しています
(rakuを使う場合はこちらからダウンロード)。
$ echo "select flds from notes" | sqlite3 collection.anki21 | raku -ne '.split(/<:Cc>/)[0].say' > kr.txt
$ echo "select flds from notes" | sqlite3 collection.anki21 | raku -ne '.split(/<:Cc>/)[1].say' > ja.txt
5) kr.txt, ja.txt, audiopath.txtを結合する
input.csvに韓国語、日本語、音声パスの順で格納しています。
ここで元DBはけっこう順番がずれているのでここのコードを使って順番を訂正します:
$ cat kr.txt | raku -e '.say for $*IN.lines' > tmp
$ raku apply-swap-ops.raku --outfile=kr.txt tmp ops.txt
$ cat ja.txt | raku -e '.say for $*IN.lines' > tmp
$ raku apply-swap-ops.raku --outfile=ja.txt tmp ops.txt
$ paste -d"," kr.txt ja.txt audiopath.txt > input.csv
6) ankiのライブラリを使ってデッキを作る
python製の公式ライブラリがあるのでそれを入れます。当時入ったのはanki==24.6.3でした:https://github.com/ankitects/anki
$ pip3 install anki
edit.pyを記述して保存します:
import anki
from anki.importing.csvfile import TextImporter
from anki.exporting import AnkiPackageExporter
from anki.collection import Collection
import anki.lang
import os
import shutil
# Initialize Anki language support (ensure it's set to the correct language)
anki.lang.set_lang("en_US")
# Create a new collection
collection_path = 'topik1800.anki2'
collection = Collection(collection_path)
# Create a new deck in the collection (otherwise the "Default" deck will be used)
deck_name = 'TOPIK1800'
deck_id = collection.decks.id(deck_name)
collection.decks.select(deck_id)
deck = collection.decks.get(deck_id)
deck['name'] = deck_name
collection.decks.save(deck)
model = collection.models.by_name('Basic')
collection.models.save(model)
# Define a function to handle media files
def add_media_file(collection, file_path):
if os.path.exists(file_path):
media_dir = collection.media.dir()
media_file = os.path.join(media_dir, os.path.basename(file_path))
shutil.copy(file_path, media_file)
return f"[sound:{os.path.basename(file_path)}]"
return ""
# Import cards from CSV into the new collection
csv_file_path = 'input.csv'
with open(csv_file_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines: # Skip the header line
front, back, audio_path = line.strip().split(',')
audio_tag = add_media_file(collection, audio_path)
note = collection.newNote()
note.fields[0] = front
note.fields[1] = f"{back} {audio_tag}"
collection.addNote(note)
# Save and export the collection to an Anki package (.apkg) file
exporter = AnkiPackageExporter(collection)
export_file_path = 'topik1800.apkg'
exporter.exportInto(export_file_path)
実行します
$ python3 edit.py
あとはtopik1800.apkgができるので、PCやスマホでAnkiのアプリに読み込ませてつかうことができます(動きはしますが、自分のコードが悪いらしく実際使うとなぜかデッキ名が"Default"のままになってしまう問題があります)。