summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jan.tuomi@valuemotive.com>2021-02-02 13:43:25 +0200
committerJan Tuomi <jan.tuomi@valuemotive.com>2021-02-02 13:43:25 +0200
commit1a1dc2a9dc2380fd04fa2f2da18ff9e6ac87647d (patch)
tree847eab756e01286e0f3f36b2a076902d770120df
parent75c731c78880c5a31a50e166d33dcae03b76349a (diff)
Add Wadoku client and improve stuff
-rw-r--r--attain_vocab_to_anki_py/__init__.py26
-rw-r--r--attain_vocab_to_anki_py/io.py26
-rw-r--r--attain_vocab_to_anki_py/jisho_client.py61
-rw-r--r--attain_vocab_to_anki_py/wadoku_client.py42
4 files changed, 141 insertions, 14 deletions
diff --git a/attain_vocab_to_anki_py/__init__.py b/attain_vocab_to_anki_py/__init__.py
index dee97d6..59b2753 100644
--- a/attain_vocab_to_anki_py/__init__.py
+++ b/attain_vocab_to_anki_py/__init__.py
@@ -1,26 +1,42 @@
import argparse
import attain_vocab_to_anki_py.io
import attain_vocab_to_anki_py.jisho_client
+import attain_vocab_to_anki_py.wadoku_client
__version__ = '0.1.0'
+DEFAULT_FORMAT = 'kanji,english'
+
def main():
parser = argparse.ArgumentParser(description='Convert course vocab into Anki deck')
+ parser.add_argument('--format', metavar='format', type=str, default=DEFAULT_FORMAT,
+ help='comma-separated row format, e.g. kanji,hiragana,english,readings')
parser.add_argument('file', metavar='file', type=str,
help='vocabulary file path')
args = parser.parse_args()
file_path = args.file
+ row_format = args.format
+
+ print("row_format:", row_format)
# read entries from file
print(f"[STATUS] Reading file {file_path}")
- entries = io.read_from_file(file_path)
+ entries = io.read_from_file(file_path, row_format)
+
+ # fetch translations from Jisho
+ print(f"[STATUS] Fetching English translations from Jisho")
+ entries = jisho_client.inject_english_translation(entries)
# fetch kanji meanings from Jisho
- print(f"[STATUS] Fetching kanji data from Jisho")
- entries_with_meanings = jisho_client.inject_kanji_meanings(entries)
+ print(f"[STATUS] Fetching kanji meaning data from Jisho")
+ entries = jisho_client.inject_kanji_meanings(entries)
+
+ # fetch hiragana readings from Wadoku w/ pitch accents
+ print(f"[STATUS] Fetching reading data from Wadoku")
+ entries = wadoku_client.inject_hiragana_with_accents(entries)
# write entries to file
- out_file_name = f"{file_path}.out"
+ out_file_name = file_path.replace(".csv", ".out.csv") if ".csv" in file_path else f"{file_path}.out"
print(f"[STATUS] Writing result to file {out_file_name}")
- io.write_to_file(out_file_name, entries_with_meanings)
+ io.write_to_file(out_file_name, entries)
diff --git a/attain_vocab_to_anki_py/io.py b/attain_vocab_to_anki_py/io.py
index 4288e06..90c9507 100644
--- a/attain_vocab_to_anki_py/io.py
+++ b/attain_vocab_to_anki_py/io.py
@@ -8,24 +8,36 @@ class Entry:
english: str
meanings: str
-def read_from_file(path_str: str) -> list:
+def read_from_file(path_str: str, row_format: str) -> list:
p = path.join(path_str)
lines = []
+ format_segments = row_format.split(",")
+
with open(p, "r") as f:
lines = f.readlines()
entries = []
for line in lines:
- kanji, hiragana, english = line.split(",", 2)
- entries.append(Entry(kanji=kanji.strip(),
- hiragana=hiragana.strip(),
- english=english.strip(),
- meanings=""))
+ if len(line.strip()) == 0:
+ continue
+
+ value_dict = {}
+
+ row_values = line.split(",", len(format_segments) - 1)
+ for i, format_segment in enumerate(format_segments):
+ value_dict[format_segment] = row_values[i]
+
+ entries.append(Entry(
+ kanji=value_dict.get("kanji", "").strip(),
+ hiragana=value_dict.get("hiragana", "").strip(),
+ english=value_dict.get("english", "").strip(),
+ meanings=value_dict.get("meanings", "").strip()
+ ))
return entries
-def _entry_to_row(entry: Entry, delimiter: str = ";") -> str:
+def _entry_to_row(entry: Entry, delimiter: str = "§") -> str:
s = delimiter.join([entry.kanji, entry.hiragana, entry.english, entry.meanings])
return f"{s}\n"
diff --git a/attain_vocab_to_anki_py/jisho_client.py b/attain_vocab_to_anki_py/jisho_client.py
index 0ca2147..d2c0e4f 100644
--- a/attain_vocab_to_anki_py/jisho_client.py
+++ b/attain_vocab_to_anki_py/jisho_client.py
@@ -4,12 +4,29 @@ import urllib.parse
JISHO_BASE_URL = "https://jisho.org/search"
+def _meaning_tag_to_abbrev(tag: str) -> str:
+ if "Godan" in tag: return "G1"
+ if "Ichidan" in tag: return "G2"
+ if "Suru" in tag: return "G3"
+ if "Noun" in tag: return "N."
+ if "I-adjective" in tag: return "い-adj."
+ if "Na-adjective" in tag: return "な-adj."
+ if "No-adjective" in tag: return "の-adj."
+ if "Adverb" in tag: return "adv."
+ return tag
+
def inject_kanji_meanings(entries: list) -> list:
entries_with_meanings = []
for index, entry in enumerate(entries):
kanji = entry.kanji
- print(f"Fetching data for #{index}: {kanji}")
+
+ if len(entry.meanings) > 0:
+ print(f"Meaning data exists for #{index}: {kanji}. Skipping...")
+ entries_with_meanings.append(entry)
+ continue
+
+ print(f"Fetching meaning data from Jisho for #{index}: {kanji}")
resource_part = urllib.parse.quote_plus(f"{kanji}#kanji")
url = f"{JISHO_BASE_URL}/{resource_part}"
@@ -32,4 +49,44 @@ def inject_kanji_meanings(entries: list) -> list:
entry.meanings = result
entries_with_meanings.append(entry)
- return entries_with_meanings \ No newline at end of file
+ return entries_with_meanings
+
+def inject_english_translation(entries: list) -> list:
+ entries_with_translations = []
+
+ for index, entry in enumerate(entries):
+ kanji = entry.kanji
+
+ if len(entry.english) > 0:
+ print(f"English translation exists for #{index}: {kanji}. Skipping...")
+ entries_with_translations.append(entry)
+ continue
+
+ print(f"Fetching translation from Jisho for #{index}: {kanji}")
+
+ resource_part = urllib.parse.quote_plus(f"{kanji}")
+ url = f"{JISHO_BASE_URL}/{resource_part}"
+ resp = requests.get(url)
+ resp.raise_for_status()
+
+ soup = BeautifulSoup(resp.text, "html.parser")
+ container = soup.select_one("div#page_container")
+
+ meaning_wrapper = container.select(".meanings-wrapper")[0]
+
+ meaning_tags = meaning_wrapper.select(".meaning-tags")
+ meaning_tags_texts = map(lambda e: e.text.strip(), meaning_tags)
+ meaning_tag_abbrevs = map(_meaning_tag_to_abbrev, meaning_tags_texts)
+
+ meaning_translations = meaning_wrapper.select(".meaning-wrapper .meaning-meaning")
+ meaning_translations_texts = map(lambda e: e.text.strip(), meaning_translations)
+
+ meanings_zipped = zip(meaning_tag_abbrevs, meaning_translations_texts)
+
+ first_translation_pair = list(meanings_zipped)[0]
+ result = f"{first_translation_pair[0]} {first_translation_pair[1]}"
+
+ entry.english = result
+ entries_with_translations.append(entry)
+
+ return entries_with_translations
diff --git a/attain_vocab_to_anki_py/wadoku_client.py b/attain_vocab_to_anki_py/wadoku_client.py
new file mode 100644
index 0000000..550f801
--- /dev/null
+++ b/attain_vocab_to_anki_py/wadoku_client.py
@@ -0,0 +1,42 @@
+from bs4 import BeautifulSoup
+import requests
+import urllib.parse
+
+WADOKU_BASE_URL = "https://www.wadoku.de/search"
+
+def inject_hiragana_with_accents(entries: list) -> list:
+ entries_with_readings = []
+
+ for index, entry in enumerate(entries):
+ kanji = entry.kanji.replace("~", "")
+
+ if len(entry.hiragana) > 0:
+ print(f"Hiragana exists for #{index}: {kanji}. Skipping...")
+ entries_with_readings.append(entry)
+ continue
+
+ # Remove nasty characters from kanji since Wadoku
+ # fails to find anything otherwise
+ print(f"Fetching hiragana data for #{index}: {kanji}")
+
+ resource_part = urllib.parse.quote_plus(kanji)
+ url = f"{WADOKU_BASE_URL}/{resource_part}"
+ resp = requests.get(url)
+ resp.raise_for_status()
+
+ soup = BeautifulSoup(resp.text, "html.parser")
+ container = soup.select_one("section#content")
+
+ readings = container.select("span.reading")
+ first_reading = str(readings[0])
+
+ # Remove extra characters added by Wadoku
+ # https://www.wadoku.de/wiki/display/WAD/Hinweise+zur+Notation
+ result = first_reading \
+ .replace("~", "") \
+ .replace("|", "") \
+ .replace("・", "")
+ entry.hiragana = result
+ entries_with_readings.append(entry)
+
+ return entries_with_readings