問題文
英語を学ぶ人はおそらく、アンキに精通しているでしょう。これは、インターバルの繰り返しを使用して単語、表現、その他の情報を記憶するプログラムです。
紹介を必要としないもう1つの人気のあるサービス-LinguaLeoでは、元のテキストを読みながら、読むためになじみのない単語をすぐに送信し、発音、画像、単語の転写、およびそれが使用されるコンテキストとともに独自の辞書に保存できます。 数年前、LinguaLeoは間隔反復システムを導入しましたが、Ankiとは異なり、反復システムはそれほど強力ではなく、カスタマイズ機能を備えていません。
ハリネズミを
越えて2つのプラットフォームを利用しようとしたらどうなるでしょうか? すべてのメディアファイルと情報と共にLingua Leoから単語を取り出し、Ankiのリソースを使用してそれらを記憶します。
既製のソリューションの概要
タスクにはいくつかの既製のソリューションが既にありますが、それらはすべてユーザーフレンドリーではなく、多くの追加アクションが必要です:記録モデル、カードテンプレートの作成、CSSスタイルの追加、メディアファイルの個別アップロードなどが必要です。 など
さらに、これらはすべて別個のプログラム(
LinguaGet )として、またはブラウザーへのアドオン(
one 、
two )として作成されますが、これもあまり便利ではありません。 理想的な状況では、ユーザーがAnki自体から直接新しいカードを取得できるようにしたかった。
楽器の選択
Anki 2.0はPython 2.7で書かれており、アドオンのシステムをサポートしています。これらはPythonの個別のモジュールです。 安定版GUIはPyQt 4.8を使用します。
したがって、タスクは1つの文で説明でき
ます。PythonでAnkiから直接起動し、LinguaLeoからログインとパスワードを入力する以外のユーザーのアクションを必要としないアドオンを作成します。解決策
プロセス全体は3つの部分に分けることができます。
- LinguaLeoからの承認と辞書の取得。
- データをAnkiカードに変換します。
- グラフィックインターフェイスの作成。
データのインポート
LinguaLeoには公式のAPIは含まれていませんが、ブラウザーのアドオンコードを詳しく調べると、2つの必要なアドレスを見つけることができます。
userDictUrl = "http://lingualeo.com/userdict/json"
loginURL = "http://api.lingualeo.com/api/login"
承認手順は複雑ではなく
、Habrに関するこの
記事で詳しく説明されてい
ます 。
JSON辞書には、各ページに100語が含まれています。 urlencodeを使用して、フィルターパラメーターをすべてに渡し、ページパラメーターで必要なページの番号を渡し、それぞれを調べて辞書を保存します。
辞書認証とインポートモジュールコード import json import urllib import urllib2 from cookielib import CookieJar class Lingualeo: def __init__(self, email, password): self.email = email self.password = password self.cj = CookieJar() def auth(self): url = "http://api.lingualeo.com/api/login" values = {"email": self.email, "password": self.password} return self.get_content(url, values) def get_page(self, page_number): url = 'http://lingualeo.com/ru/userdict/json' values = {'filter': 'all', 'page': page_number} return self.get_content(url, values)['userdict3'] def get_content(self, url, values): data = urllib.urlencode(values) opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj)) req = opener.open(url, data) return json.loads(req.read()) def get_all_words(self): """ The JSON consists of list "userdict3" on each page Inside of each userdict there is a list of periods with names such as "October 2015". And inside of them lay our words. Returns: type == list of dictionaries """ words = [] have_periods = True page_number = 1 while have_periods: periods = self.get_page(page_number) if len(periods) > 0: for period in periods: words += period['words'] else: have_periods = False page_number += 1 return words
受信したデータをAnkiカードに変換します
Ankiのデータは次のように保存されます。
コレクションには、CSSスタイル、
フィールドのリスト、およびカード(前面と背面)
を設計
するためのhtmlテンプレートを含む
モデルが含まれ
ます 。
この場合、5つのフィールドがあります:単語自体、翻訳、文字起こし、発音ファイルへのリンク、画像ファイルへのリンク。
すべてのフィールドに入力すると、
レコードが取得されます。 次に、レコードから2
枚のカードを作成できます。「英語-ロシア語」と「ロシア語-英語」です。

カードは
デッキにあり
ます (
コシュチェイの卵の死とeggの卵 )。
上記に加えて、音声と画像をダウンロードする機能が必要です。
モデル、レコードなどを作成するためのユーティリティを備えたモジュールコード import os from random import randint from urllib2 import urlopen from aqt import mw from anki import notes from lingualeo import styles fields = ['en', 'transcription', 'ru', 'picture_name', 'sound_name', 'context'] def create_templates(collection): template_eng = collection.models.newTemplate('en -> ru') template_eng['qfmt'] = styles.en_question template_eng['afmt'] = styles.en_answer template_ru = collection.models.newTemplate('ru -> en') template_ru['qfmt'] = styles.ru_question template_ru['afmt'] = styles.ru_answer return (template_eng, template_ru) def create_new_model(collection, fields, model_css): model = collection.models.new("LinguaLeo_model") model['tags'].append("LinguaLeo") model['css'] = model_css for field in fields: collection.models.addField(model, collection.models.newField(field)) template_eng, template_ru = create_templates(collection) collection.models.addTemplate(model, template_eng) collection.models.addTemplate(model, template_ru) model['id'] = randint(100000, 1000000)
GUI作成
アドオンはミニマリズムを目指しているため、必要なものは次のとおりです。
- 2つの入力フィールド(LinguaLeoからのログインとパスワード)
- 未検討の単語のみをインポートするための1つのチェックボックス
- 2つのボタン(インポートとキャンセル)

GUI class PluginWindow(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.initUI() def initUI(self): self.setWindowTitle('Import From LinguaLeo')
アドベンチャーは、示されているものに加えて、ダウンロードプロセス中にアドオンが死んだとユーザーが思わないようにプログレスバーを作成するときに開始します。
GUIをフリーズせずにバーの進行状況を機能させるには、(QThreadを使用して)別のスレッドを作成し、すべてのデータをロードしてカードを作成し、進行状況カウンターのみをグラフィカルインターフェイスに送信する必要があります。 ここで、トラブルが待っています-Ankiの情報はSQliteデータベースに保存され、プログラムはメインスレッドの外部からの変更を許可しません。 解決策:主な費用のかかるタスクは、メディアファイルをダウンロードし、2番目のストリームのプログレスバーにデータを転送することです。一方、主なフィールドに入力してレコードを保存します。 したがって、凍結されたインターフェイスのない作業プログレスバーが表示されます。
エラー処理を追加するだけです。 アドオンの準備が整いました。
まだベータ版の新しいAnkaのプラグインを3番目のpythonに書き換え、メディアファイルの非同期読み込みを使用して作業を高速化する計画です。
BitBucketソースコード。
Ankiアドオンフォーラムのプラグインページ。