anki批量制卡-AnkiConnect

2,705 阅读5分钟

世纪三部曲英文版从2019年就开始看了,利用年前年后漫长的摸鱼期把世纪三部曲的最后一本《永恒的边缘》看完了。平常看英文书遇到单词不认识也就随看随查,上班时间看书竟然认真的记了笔记,总结每个小节的剧情记下不认识的单词。书看完了,这些不认识的单词想整理出来背一背,正好平常有使用anki的习惯,就想把这些单词制成卡片录入anki。

自从有了chatGpt以后,解决这些小问题变得信手拈来毫不费力了。chatGpt给的建议是使用AnkiConnect进行处理,AnkiConnect是一个强大的插件,可以允许你通过API添加、编辑和删除卡片,还可以使用Python脚本等方式实现更高级的批量操作。

既然chatGpt给了建议那当然代码也理所应当由他提供一份了,根据chatGpt提供的代码并作修改解决了问题。

Pasted image 20230220162639.png

Pasted image 20230220162705.png

Pasted image 20230220162743.png

读书笔记格式如下:


31

Lyndon Johnson 肯尼迪遇刺后新任总统继续推进民权法案,采取逐个击破的方式争取共和党议员的支持,通过发动工商界进行游说和施压,民权法案主要障碍逐渐被击破。

sabotage 破坏  
segregationist 种族隔离主义者  
fervent 热情的  
in public accommodations 在公共场所  
enlist 征集  
  
He got a standing ovation, and the Steelworkers’ thirty-three lobbyists stormed Capitol Hill. 鼓掌  说客  
cave 屈服  

image.png


首先使用python读取md文件,正则提取单词,代码如下:

# 导入python文件处理依赖  
import re  
from tqdm import tqdm  
  
def searchWordFromMd(filePath):  
    # 读取文件  
    f = open(filePath, "r", encoding='utf-8')  
    # 读取文件内容,utf-8编码  
    content = f.read()  
    # 正则匹配  
    pattern = re.compile(r'~~~.*?\s*\n([\s\S]+?)\n~~~', re.S)  
    # 匹配结果  
    result = re.findall(pattern, content)  
    words = []  
    # 遍历结果  
    for i in result:  
        # 按换行符分割  
        splits = i.split('\n')  
        # 将分割后的结果添加到words中  
        for j in splits:  
            # 去除空白符  
            j = j.strip()  
            # 不为空则输出  
            if j:  
                words.append(j)  
    return words  
  
  
def containsChinese(text):  
    # 判断text是否包含中文  
    pattern = re.compile(r'[\u4e00-\u9fa5]')  
    match = pattern.search(text)  
    return match  
  
  
def findFirstChinese(text):  
    # 查找text中第一个中文字符的位置  
    pattern = re.compile(r'[\u4e00-\u9fa5]')  
    match = pattern.search(text)  
    if match:  
        return match.start()  
    else:  
        return -1  
  
  
# 主函数  
if __name__ == '__main__':   
    words = searchWordFromMd("the edge of eternity.md")  
    print("共有" + str(len(words)) + "个单词")

将提取到的单词信息通过调用AnkiConnect的接口导入anki,首先要安装AnkiConnect插件: FooSoft Productions - Anki-Connect

Pasted image 20230220152606.png

依次点击工具-附加组件-获取插件-输入代码:2055492159-OK-重启anki生效

Pasted image 20230220152648.png 使用浏览器打开localhost:8765,验证AnkiConnect安装成功

Pasted image 20230220153224.png

下面是通过调用AnkiConnect的接口添加anki卡片的代码:ankiConnector.py

import json  
import requests  
  
# Anki Connect API地址  
ankiConnectUrl = "http://localhost:8765"  
  
  
# 定义添加笔记的函数  
def addNoteToAnki(deckName, modelName, fields, tags, printResponse=False):  
    # 构建添加笔记的请求  
    addNoteRequest = {  
        "action": "addNote",  
        "version": 6,  
        "params": {  
            "note": {  
                "deckName": deckName,  
                "modelName": modelName,  
                "fields": fields,  
                "tags": tags  
            }  
        }  
    }  
  
    # 发送请求并获取响应  
    response = requests.post(ankiConnectUrl, data=json.dumps(addNoteRequest))  
    responseJson = response.json()  
  
    # 检查响应是否包含错误  
    if printResponse:  
        if "error" in responseJson:  
            if responseJson["error"] == "None":  
                print("Note added successfully!")  
                return True  
            print("An error occurred while adding the note: ", responseJson)  
            return False  
        else:  
            print("Note added successfully!")  
            return True

代码定义了一个名为 addNoteToAnki 的函数,该函数使用Anki Connect API向Anki中添加一张笔记卡片。函数接受五个参数:deckName 表示笔记所属的牌组名称,modelName 表示笔记的类型名称,fields 是一个字典,包含笔记的各个字段的内容(需要与卡片模板字段进行对应),tags表示卡片要添加的tag标签,printResponse表示运行时是否打印日志,默认False不打印。 当你使用Anki Connect API向Anki中添加一张笔记时,需要构建一个符合Anki Connect API规范的请求。在这个请求中,需要指定要执行的动作以及相关参数。添加卡片api的请求体如下:

{
    "action": "addNote",  # 表示要执行的动作为添加笔记
    "version": 6,         # 表示使用的Anki Connect API版本号,这里使用的是版本6
    "params": {           # 表示动作的参数
        "note": {         # 表示要添加的卡片
            "deckName": "MyDeck",        # 卡片所属的牌组名称
            "modelName": "Basic",        # 卡片的模板名称
            "fields": {                  # 卡片的字段内容:要跟卡片模板字段对应
                "Front": "Hello",        # 笔记正面的内容
                "Back": "你好"            # 笔记背面的内容
            },
            "tags": []                   # 笔记的标签
        }
    }
}

这个请求的结构比较简单,通过这个请求,Anki Connect会向Anki中添加一张笔记,并返回一个响应。如果响应中包含 error 字段,说明添加笔记时出现了错误,否则说明添加成功。

接下来再写一些胶水代码把正则提取单词、AnkiConnect制卡的逻辑连接起来就好了,请确保在运行代码之前,已经启动了Anki,并安装并启用了Anki Connect插件。代码如下:

# 导入python文件处理依赖  
import re  
from tqdm import tqdm  
from ankiConnector import addNoteToAnki  
  
  
def searchWordFromMd(filePath):  
    # 读取文件  
    f = open(filePath, "r", encoding='utf-8')  
    # 读取文件内容,utf-8编码  
    content = f.read()  
    # 正则匹配  
    pattern = re.compile(r'~~~.*?\s*\n([\s\S]+?)\n~~~', re.S)  
    # 匹配结果  
    result = re.findall(pattern, content)  
    words = []  
    # 遍历结果  
    for i in result:  
        # 按换行符分割  
        splits = i.split('\n')  
        # 将分割后的结果添加到words中  
        for j in splits:  
            # 去除空白符  
            j = j.strip()  
            # 不为空则输出  
            if j:  
                words.append(j)  
    return words  
  
  
def containsChinese(text):  
    # 判断text是否包含中文  
    pattern = re.compile(r'[\u4e00-\u9fa5]')  
    match = pattern.search(text)  
    return match  
  
  
def findFirstChinese(text):  
    # 查找text中第一个中文字符的位置  
    pattern = re.compile(r'[\u4e00-\u9fa5]')  
    match = pattern.search(text)  
    if match:  
        return match.start()  
    else:  
        return -1  
  
  
# 主函数  
if __name__ == '__main__':  
    # 测试代码  
    words = searchWordFromMd("the edge of eternity.md")  
    print("共有" + str(len(words)) + "个单词")  
  
    bar = tqdm(total=len(words))  
    for index, word in enumerate(words):  
        chinese = ""  
        english = ""  
        # word包含中文  
        if containsChinese(word):  
            # print(word+"|"+str(findFirstChinese(word)))  
            english = word[:findFirstChinese(word)].strip()  
            chinese = word[findFirstChinese(word):]  
        else:  
            if ":" in word:  
                english = word.split(":")[0].strip()  
                chinese = word.split(":")[1].strip()  
            elif ":" in word:  
                english = word.split(":")[0].strip()  
                chinese = word.split(":")[1].strip()  
            else:  
                english = word  
                chinese = ""  
        # print(english + "|" + chinese)  
        deckName = "原句划词"  
        modelName = "AnKindle-新版"  
        fields = {  
            "Clipping": english,  
            "Note": chinese,  
            "Book": "edge of eternity",  
        }  
        tags = []  
        addNoteToAnki(deckName, modelName, fields, tags, printResponse=False)  
        bar.update(index)

最终200多个单词制卡不到2分钟就录入完毕了。