Posted on Sat 30 July 2016

WaniKani on Anki

[cached]WaniKani has long been my favorite way of studying Kanji, but I've always disliked the need to type in every single reading and meaning. At 300 reviews a day that's a lot of typing!

Today I finally had enough. First I considered making a user script for WaniKani to make it work a bit more like Anki (where you don't type the answer at all, you simply indicate how well you knew it with one tap). But then I realized that I might as well just use Anki directly.

I quickly found [cached]wanikanitoanki.com, which is great to export all Radicals, Kanji and Vocabulary and has really nice Anki templates too. Alas, the exported data didn't include the critical mnemonics! Presumably because these aren't returned by WaniKani's API.

Luckily, WaniKani is almost trivial to scrape:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests
from bs4 import BeautifulSoup

s = requests.Session()
login_page = BeautifulSoup(s.get('https://www.wanikani.com/login').text,
                           'html.parser')
token = login_page.find_all(attrs={'name': 'authenticity_token'})[0]['value']
s.post('https://www.wanikani.com/login',
       data={'user[login]': username, 'user[password]': password,
             'authenticity_token': token})


def dump_radical_mnemonic(radical):
  page = s.get('https://www.wanikani.com/radicals/%s' % radical).text
  page = BeautifulSoup(page, 'html.parser')
  section = [t for t in page.find_all('section') if 'Mnemonic' in t.text][0]
  return u''.join([unicode(t) for t in section.p.children])


def dump_kanji_mnemonics(kanji):
  def get_mnemonic(kind):
    section = [t for t in page.find_all('section')
               if '%s Mnemonic' % kind in t.text][0]
    return u''.join([unicode(t) for t in section.p.children])
  page = s.get('https://www.wanikani.com/kanji/%s' % kanji).text
  page = BeautifulSoup(page, 'html.parser')
  return u'<b>Reading</b>: %s<br><b>Meaning</b>: %s' % (
      get_mnemonic('Reading'), get_mnemonic('Meaning'))

Then I simply looped through the CSV files from wanikanitoanki and fetched the mnemonic for each, then added them as an extra column to the CSVs.

I only had to slightly modify the Anki card template to include the mnemonics.

For the back template, I added:

1
2
<br/>
{{#mnemonic}}<div class="kunyomi">{{mnemonic}}</div>{{/mnemonic}}

I also took advantage of the fact that the mnemonics fetched from WaniKani include <span> tags to highlight the Kanji / Radical they are talking about by adding some extra CSS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
.kanji-highlight {
    background-color: #f100a0;
}

.reading-highlight {
    background-color: #555;
}

.radical-highlight {
    background-color: #00a0f1;
}

.kanji-highlight, .reading-highlight, .radical-highlight {
    color: white;
    padding: 2px;
}

That's pretty much it, and the cards look great both on desktop and on AnkiDroid on my phone:

The credit for the great styling goes to wanikanitoanki, I only added the mnemonics and their highlights.

Tags: japanese, languages, learning, anki

© Julian Schrittwieser. Built using Pelican. Theme by Giulio Fidente on github. .