Anki 2.0 plugin fix

could somebody help me fix this anki 2.0 plugin so it works again

code is here. it’s called hanseido and grabs definitions from this website: krdict
it used to work and now it doesnt.

1 Like
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
	Korean Definitions plugin for Anki
	pulls definitions from https://krdict.korean.go.kr/

	Forked from kqueryful's Sanseido-Definitions


	Definition fetching adapted from rikaichan.js
	Field updating modified from Sentence_Gloss.py
	@author		= wezurii
	@author		= jjamaja
	@date 		= 14/12/2017
	@version 	= 1.0
"""
from bs4.BeautifulSoup import BeautifulSoup
import urllib
import re


# Edit these field names if necessary ==========================================
expressionField = 'Word'
definitionField = 'Sanseido'
hanjaField = 'han'
# if yes, you get a (word) at the beginning of the definitions if you search for
# a hanja, so you know how the hanja is spelled in contemporary Korean
convertHanjaToHangeul = True
# ==============================================================================

# Fetch definition from Hanseido ===============================================
def fetchDef(term):

        # cleanup the term from any html
        term = re.sub("<.*?>", "", term)
        term = re.sub("&.+;", "", term)
        term = term.strip()

	pageUrl = "https://krdict.korean.go.kr/dicSearch/search?mainSearchWord=" + urllib.quote(term.encode('utf-8'))
	response = urllib.urlopen(pageUrl)
	soup = BeautifulSoup(response)

        # if we have a hanja as request, we will take the first definition
        wehaveahanjaword = re.match(u'[\u4E00-\u9FFF]+', term, re.U)                

        allhanjas = ""
        alldefinitions = ""
        # each result comes back with a <dl> with id=article0, article1, article2, so we
        # will loop through until we run out, but we'll keep checking that the word is the same
        # because sometimes you get results for words that are linked to the one we're searching
        # If the word search is in its hanja form, we will return only the first block of definition
        i = 0
	while 1:
                articleid = "article" + repr(i)
                i += 1
                defText = ""
                NetDicBody = soup.find("dl", id=articleid, class_="printArea")

                if not NetDicBody: break
                # we're only interested in the blocks that contain the exact same word as what we're asking
                wordDefined = NetDicBody.find("span", class_="word_type1_17")


                # if we don't get a word_type1_17 it probably means the interface has changed
                if  (not wordDefined) or (len(wordDefined.contents) == 0): break
                if term != wordDefined.contents[0].strip() and (not wehaveahanjaword):
                        break

                if NetDicBody != None:
                        definitions = NetDicBody.find_all('dd')
                        defFinished = False

                        for singledef in definitions:
                                if defText:
                                        defText += "<br>"
                                else:
                                        # if word is a hanja, and we have a definition, the KoreanJamo word will be
                                        # in this value, let's put it in the definition in case it is needed
                                        # We only do this at the very beginning when no definition has been added yet.
                                        if(wehaveahanjaword and convertHanjaToHangeul):
                                                print("Hanja Korean equivalent should be added to definition")
                                                defText = "(" + wordDefined.contents[0].strip() + ") "

                                for line in singledef.children:
                                        if line.find("strong"):
                                                defText += line.string.strip()
                                        elif line.string != None and line.string != u"\n":
                                                defText += line.string.strip()
                                                
                        spans = NetDicBody.find_all('span')
                        for singlespan in spans:
                                hanja = ""
                                for line in singlespan.children:
                                        if line.string != None:

                                                linewithparenthesis = re.search("\((.+)\)", line.string)
                                                if(linewithparenthesis):
                                                        newhanja = linewithparenthesis.group(1)
                                                        if newhanja not in allhanjas:
                                                                hanja += newhanja + " "
                                                                if allhanjas: allhanjas += " "
                                allhanjas += hanja
                                                        
                        if alldefinitions: alldefinitions += "<br>"
                        alldefinitions += defText
                        # once we got one definition this should be enough when it's a hanja word.
                        wehaveahanjaword = False

                else: break
                        
                                                
	return alldefinitions, allhanjas


# Update note ==================================================================
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from anki.hooks import addHook
from anki.notes import Note
from aqt import mw

def glossNote( f ):
   if f[ definitionField ] and (not hanjaField or (hanjaField and f[ hanjaField ])): return
   definition, hanja = fetchDef( f[ expressionField ] )
   if not f[ definitionField ]: f[ definitionField ] = definition
   if not hanjaField: return
   if not f[ hanjaField ]: f[ hanjaField ] = hanja


def setupMenu( ed ):
	a = QAction( 'Regenerate Korean definitions', ed )
	ed.connect( a, SIGNAL('triggered()'), lambda e=ed: onRegenGlosses( e ) )
	ed.form.menuEdit.addAction( a )

def onRegenGlosses( ed ):
	n = "Regenerate Korean definitions"
	ed.editor.saveNow()
	regenGlosses(ed, ed.selectedNotes() )
	mw.requireReset()

def regenGlosses( ed, fids ):
	mw.progress.start( max=len( fids ) , immediate=True)
	for (i,fid) in enumerate( fids ):
		mw.progress.update( label='Generating Korean definitions...', value=i )
		f = mw.col.getNote(id=fid)
		try: glossNote( f )
		except:
			import traceback
			print 'definitions failed:'
			traceback.print_exc()
		try: f.flush()
		except:
			raise Exception()
		ed.onRowChanged(f,f)
	mw.progress.finish()

addHook( 'browser.setupMenus', setupMenu )

Addons mentioned:

Hanseido - Korean Definitions
2.0 Addon, Updated 2018-01-29.


There is Korean Support, which may be an alternative and is well maintained

1 Like

the code i posted is not the code that you download from anki addons page. i had someone update the code so that it works since the website the plugin is based on still works. so this version worked a year or two ago but now it doesn’t work.

i understand you’re just tryig to be helpful but the plugin youre linking is useless to me. it’s just a crappy translation generator. this pulls the korean defintion for the korean word from the dictionary.

You already might know this, but I’ll mention anyway that yomitan has a krdict for it and they have a mass note generator feature now. I don’t use yomitan/learn Korean but I assume the definitions won’t be much different from what you seek.

1 Like

I fixed this add-on for Anki24+ and uploaded it to AnkiWeb.

The error seems to be caused by the web page being updated, so if you want to use Anki 2.0 change the pageUrl to this and it will probably work.

    pageUrl = (
"https://krdict.korean.go.kr/kor/dicMarinerSearch/search?nationCode=&ParaWordNo=&mainSearchWord="
1 Like

I, for some reason always used to think you link people to add-ons you previously have fixed. Here, it seems you are uploading it only today, in mere 14 hours! I’m impressed ngl.

1 Like

thanks for converting it to the new anki version but did you test it? i just did and it didn’t work. if you need a korean word you can use 사랑.

and just to reiterate the code i pasted above is not the same code as the code that is up for hanseido 2.0 on the anki plugins page. i had it updatd by somebody and it worked until last year


Debug info:
Anki 2.1.44 (b2b3275f) Python 3.8.6 Qt 5.14.2 PyQt 5.14.2
Platform: Windows 10
Flags: frz=True ao=True sv=1
Add-ons, last update check: 2024-08-23 13:44:23

Caught exception:
Traceback (most recent call last):
  File "C:\Users\Owner\AppData\Roaming\Anki2\addons21\286402228\__init__.py", line 173, in <lambda>
    a.triggered.connect(lambda : onRegenGlosses(browser))
  File "C:\Users\Owner\AppData\Roaming\Anki2\addons21\286402228\__init__.py", line 180, in onRegenGlosses
    regenGlosses(browser, browser.selectedNotes())
  File "C:\Users\Owner\AppData\Roaming\Anki2\addons21\286402228\__init__.py", line 189, in regenGlosses
    note = mw.col.get_note(id=fid)
AttributeError: 'Collection' object has no attribute 'get_note'
1 Like

Thanks for the error report.
It seems you are using Anki 2.1.44, perhaps updating to the latest version of Anki will work.

yeah i don’t know about that. it won’t install it without uninstalling the anki i currentlyhave.

1 Like

If I remember correctly, if you have Anki version ≤ 2.1.49 and want to install version ≥ 2.1.50, you will be prompted to uninstall the old version first.

However, you can later reinstall the old version without needing to uninstall the new one.

1 Like

yeah that’s too much work/risk. i tink i’ll try installing the new anki on another computer or computer login or something. or if someone else could test it and let me know if it actually works. you just need a card with fields named Word and Sanseido. in the word field you fill it with a korean word like 사랑, then you go to browse, get to the card, select it, hit edit then regenerate korean definitions

I added support for Anki 2.1.44, perhaps it will work. Basically I recommend the latest version of Anki if possible because older versions are developed slower.

Anki 23.12.1 (1a1d4d54) (ao)
Python 3.9.15 Qt 6.6.1 PyQt 6.6.1
Platform: Windows-10-10.0.22631

Traceback (most recent call last):
File “aqt.webview”, line 628, in handler
File “aqt.reviewer”, line 756, in _onTypedAnswer
File “decorator”, line 232, in fun
File “anki.hooks”, line 89, in decorator_wrapper
File “anki.hooks”, line 86, in repl
File “C:\Users\robyv\AppData\Roaming\Anki2\addons21\1374772155\main.py”, line 278, in on_show_answer
return old(self)
File “aqt.reviewer”, line 466, in showAnswer
File “aqt.hooks", line 4229, in call
File "C:\Users\robyv\AppData\Roaming\Anki2\addons21\50293437_init
.py”, line 30, in count_consecutive
Calculate_the_number_of_cards(card)
File "C:\Users\robyv\AppData\Roaming\Anki2\addons21\50293437_init
.py", line 79, in Calculate_the_number_of_cards
filtered_list2 = [entry for entry in rating_list if entry[1] > cutoff]
File "C:\Users\robyv\AppData\Roaming\Anki2\addons21\50293437_init
.py", line 79, in
filtered_list2 = [entry for entry in rating_list if entry[1] > cutoff]
NameError: free variable ‘cutoff’ referenced before assignment in enclosing scope

Error in sys.excepthook:
Traceback (most recent call last):

Original exception was:
Traceback (most recent call last):

===Add-ons (active)===
(add-on provided name [Add-on folder, installed at, version, is config changed])
Advanced Browser [‘874215009’, 2023-10-22T01:34, ‘None’, ‘’]
AnKing Note Types Easy Customization [‘952691989’, 2024-08-19T18:41, ‘None’, mod]
Anki Remote - Customize [‘693153301’, 2024-08-03T09:25, ‘None’, mod]
AnkiHub [‘1322529746’, 2024-07-10T03:26, ‘None’, mod]
Batch Editing [‘291119185’, 2023-10-26T11:38, ‘None’, ‘’]
Cloze Overlapper [‘cloze_overlapper’, 2023-12-21T20:15, ‘None’, ‘’]
Colorful Tags Hierarchical Tags [‘594329229’, 2022-09-16T01:06, ‘None’, ‘’]
Contanki - Controller Support for Anki beta [‘1898790263’, 2024-03-01T12:22, ‘v1.0.2’, mod]
Convert Subdecks to Tag Hierarchy [‘1172858842’, 2023-02-08T05:15, ‘None’, ‘’]
Edit Field During Review Cloze [‘385888438’, 2024-01-03T18:19, ‘6.18’, mod]
FSRS Helper Postpone Advance Load Balance Easy Days Disperse Siblings [‘759844606’, 2024-08-19T12:05, ‘None’, mod]
Image Occlusion Enhanced [‘1374772155’, 2022-04-09T17:15, ‘None’, ‘’]
More Decks Stats and Time Left [‘1556734708’, 2024-08-20T08:49, ‘None’, ‘’]
More Overview Stats 21 [‘738807903’, 2024-08-22T19:14, ‘None’, mod]
Multiple Choice for Anki [‘1566095810’, 2023-11-18T07:59, ‘None’, ‘’]
PDF Glossary Exporter [‘pdf_glossary’, 2019-08-19T22:35, ‘None’, ‘’]
Progress Graphs and Stats for Learned and Matured Cards [‘266436365’, 2020-03-29T17:26, ‘None’, ‘’]
Quick tagging 21 [‘304770511’, 2020-02-11T17:17, ‘None’, ‘’]
Scale Images [‘1312865748’, 2023-11-02T17:45, ‘None’, ‘’]
Today Again Count Created by Shige [‘50293437’, 2023-12-13T20:58, ‘None’, mod]

===IDs of active AnkiWeb add-ons===
1172858842 1312865748 1322529746 1374772155 1556734708 1566095810 1898790263 266436365 291119185 304770511 385888438 50293437 594329229 693153301 738807903 759844606 874215009 952691989

===Add-ons (inactive)===
(add-on provided name [Add-on folder, installed at, version, is config changed])
Due Cards Badge [‘due_cards_badge’, 2024-01-05T01:52, ‘None’, ‘’]
Sync to Obsidian Fixed for Anki 23 by Shige [‘1979329733’, 2024-02-22T09:24, ‘None’, mod]
UpToDate Addon [‘utd_anki_addon’, 2023-05-09T01:16, ‘None’, ‘’]

1 Like

Hello thanks for the error report, I fixed it and uploaded it.

omg thanks so much. it works beautifully! I will share this felicitous news with other korean learners

1 Like