Python 一键灌卡把真题词表批量变成 Anki 牌组【免费下载链接】ankiAnki is a smart spaced repetition flashcard program项目地址: https://gitcode.com/GitHub_Trending/an/anki背单词圈的共识越来越一致Anki 不是背单词软件而是一套基于间隔重复的调度系统。但真正劝退大多数人的从来不是复习本身而是制卡。翻真题、抄词表、逐条手工录入一个学期 3000 个单词录入成本往往比复习成本还高。社区里最活跃的 Python 侧工具如 anki-vocab 这类命令行背词工具也都在反复做同一件事把结构化词表灌进 Anki。本文结合 Anki 源码讲清楚一条可复现的词表 → 牌组流水线清洗、转换、灌入、补多媒体全程脚本化单词量越大越划算。词表清洗一切格式最终都收敛到 UTF-8 纯文本先明确一个底层事实Anki 的文本导入器不认识.xlsx、.doc或.rtf。官方文档写得很直白——导入前必须先另存为纯文本plain text文件且必须是UTF-8 编码见 docs-site/manual/importing/text-files.mdx。换句话说无论你手里的真题词表是 Excel、WPS 表格还是在线文档Python 侧的第一步都是把它读出来、清洗、再写成 UTF-8 文本。以最常见的 Excel 词表为例标准动作是import pandas as pd df pd.read_excel(2024_考研真题词表.xlsx, usecols[0, 1, 2]) df.columns [word, definition, example] # 清洗去首尾空白、合并换行、剔除空行与纯注释行 df df.dropna(subset[word]) df[word] df[word].str.strip() df[definition] df[definition].str.replace(r\s, , regexTrue) df.to_csv( anki_import.txt, sep;, # 见下文分隔符选择有讲究 indexFalse, headerTrue, encodingutf-8, # Anki 硬性要求 UTF-8 lineterminator\n, )清洗阶段有三条值得写进脚本的规则字段数必须一致。Anki 以第一行非注释行决定文件有几个字段后续记录缺字段按空处理多出来的内容会被丢弃。所以清洗时要么统一列数要么用空字符串补齐。分隔符要选稳的。Anki 会自动猜测分隔符逗号、分号、Tab 等猜测算法的优先级见proto/anki/import_export.proto中的Delimiter枚举注释——按文本中预期出现频率的升序排布。词条释义里出现逗号、括号的几率极高用;或Tab比用逗号稳得多。字段内容里想带换行/分隔符官方给了两条路用引号包起来转义或者开启 Allow HTML in fields 后用br换行。解析多行字段时引号转义对 cloze 型笔记不友好词表场景推荐后者。真题词表里常有的第几套卷年份这类元信息也不需要扔掉——它们天然适合做成标签而不是字段这样既不影响卡片排版又能在复习时按套卷筛选详见下文 tags 部分。批量制卡一条#key:value头就把牌组规则写进文件里词表清洗成纯文本后制卡路径有两条图形界面导入或直接调用 API。无论哪条背后的解析引擎是同一套——Rust 侧的统一实现 rslib/src/import_export/text/csv/import.rs 中的import_csvPython 侧则暴露为 pylib/anki/collection.py 的col.import_csv()与col.get_csv_metadata()。对脚本化灌卡最有用的是 Anki 2.1.54 的**文件头File Headers**机制在文件顶部写若干#key:value行导入时这些规则会被parse_meta_lines解析并写进CsvMetadata解析逻辑见 rslib/src/import_export/text/csv/metadata.rs。支持的指令包括指令作用#separator:;强制分隔符跳过自动猜测#html:true字段按 HTML 处理#tags:2024真题 考研给每条导入的笔记打上全局标签#columns:单词;释义;例句指定列名与列数#notetype:Basic指定笔记类型不存在则报错#deck:考研英语::2024指定目标牌组不存在则创建#notetype column:/#deck column:用某一列的值逐条指定类型/牌组#tags column:指定哪一列是标签列#guid column:指定 GUID 列用于幂等更新#if matches:/#match scope:控制重复笔记的处理策略把这些头写进 Python 输出文件的开头等于把映射关系固化在数据文件本身里之后无论谁导入、无论 GUI 还是脚本导入行为都一致header \n.join([ #separator:;, #html:true, #notetype:Basic (and reversed card), #deck:考研英语::2024真题, #tags:2024真题 考研, #columns:单词;释义;例句, , ]) with open(anki_import.txt, w, encodingutf-8) as f: f.write(header) df.to_csv(f, sep;, indexFalse, headerFalse, encodingutf-8)注意#notetype必须引用库中已存在的笔记类型。内置的标准类型由get_stock_notetypes()提供见 pylib/anki/stdmodels.py包括 Basic、Basic (and reversed card)、Cloze 等。真题词表场景的黄金配置是Basic (and reversed card)正面英文、背面释义/例句同时生成英→中与中→英两张卡一个词条产出两次主动回忆机会正好命中社区反复强调的选择题卡触发深度回忆机制。对于更复杂的映射——比如想让真题例句出处做成独立字段、或不同行的词条要用不同笔记类型——可以走notetype column/deck column的逐行映射或者直接在 Python 侧构造ImportCsvRequest的CsvMetadata完整字段定义见 proto/anki/import_export.proto把列到字段的映射关系field_columns精确指定到位。去重与增量更新重复灌同一套词表不会产生垃圾卡批量灌卡最怕一件事换了个来源重新导入同一套词表结果库里出现几千张重复卡。Anki 的处理机制是——以第一字段作为唯一性判据。默认行为下如果导入文件的第一字段与库中同类型笔记相同会更新原笔记的其它字段而不是新建也可以在导入对话框里改成忽略重复或照常新建。相关选项在CsvMetadata中对应DupeResolutionUPDATE / PRESERVE / DUPLICATE与MatchScope按笔记类型或按类型牌组双重匹配详见 proto/anki/import_export.proto。match_scope建议显式设置。词表场景里同一个单词可能在不同牌组如六级核心真题超纲词中分别出现如果只按笔记类型匹配后导入的会被误判为重复而整体覆盖按类型牌组匹配则各归各的。脚本里若走 API 灌入这两个字段必须显式声明否则默认值可能不符合直觉。另外注意更新已有笔记时其现有卡片的调度信息scheduling会被保留。也就是说你可以放心地在新一轮真题出来后重新导入旧词表让释义、例句刷新为新版本而间隔重复进度不受影响——这正是增量更新词表的正确姿势。进阶玩法例句、发音与图片自动补齐基础词条灌进去只是及格线。单词卡的记忆质量很大程度取决于多媒体与语境信息的密度。Anki 的字段是纯文本但支持两类特殊引用导入时需开启#html:true会自动解析音频引用[sound:xxx.mp3]。把音频文件放进集合的collection.media文件夹字段里写[sound:abandon.mp3]复习时自动播放。媒体引用解析的正则定义在 pylib/anki/media.pysound_regexps与html_media_regexps最终由 pylib/anki/sound.py 的SoundOrVideoTag拼接出实际播放路径。批量场景下发音文件可以按单词名命名后一并复制进 media 文件夹import shutil from pathlib import Path # 假设已有 tts_cache/{word}.mp3 或下载好的发音包 src_dir Path(tts_cache) media_dir Path(collection.media) # 与集合文件同名、后缀为 .media media_dir.mkdir(exist_okTrue) df[audio] df[word].map( lambda w: f[sound:{w}.mp3] if (src_dir / f{w}.mp3).exists() else ) for w in df[word]: f src_dir / f{w}.mp3 if f.exists(): shutil.copy(f, media_dir / f.name) # 之后把 audio 列写进 CSV 的对应字段列即可图片引用img srcxxx.jpg。同样把图片放进 media 文件夹字段里写img srcabandon.jpg即可。文档明确提醒media 文件夹里不要放子目录否则部分功能会失效。注意不要在模板里写img src{{field}}这种写法Anki 出于搜索成本考量不支持模板内嵌媒体引用官方推荐的就是数据文件里直接写引用见 docs-site/manual/importing/text-files.mdx。TTS 合成连音频文件都不用准备。Anki 内置了 TTS 过滤器模板里写{{tts en_US:字段名}}复习时实时合成发音实现见 qt/aqt/tts.py。这意味着自动补发音可以零文件成本完成——Python 脚本只管把词条灌进去发音由 Anki 按需合成正面模板{{tts en_US:单词}} 背面模板{{tts en_US:单词}}br{{释义}}br{{例句}}{{tts}}的第一个参数必须是下划线语言代码如en_US还支持voices参数指定音色列表。社区里像 anki-vocab 这类工具把Claude 生成释义 TTS 合成语音 自动同步 Anki做成了一整条链路而它的落点同样是这套模板过滤器与[sound:]机制。例句的补齐则有更工程化的思路与其在 Excel 里人工攒例句不如在 Python 侧按词条自动抓取/生成与发音一样按单词名对齐写入对应字段列。整个流程跑完后一次col.import_csv()或 GUI 导入就把单词、释义、例句、音频四列数据连同牌组、标签、类型规则一次性灌入——3000 词的真题词表从 Excel 到可复习的牌组脚本运行时间以秒计。收尾把制卡做成增量管道最后提炼一下这套流水线的工程要点清洗层统一输出 UTF-8 纯文本字段数严格对齐分隔符优先;或 Tab规则层用#key:value文件头把分隔符、HTML、笔记类型、牌组、标签固化进文件映射关系随数据走可复现可审查唯一性层显式设置match scope与去重策略让重复导入变成幂等更新调度进度不被破坏多媒体层用[sound:]/img/{{tts}}三种引用把音频、图片、合成发音补进字段文件落位与字段生成全部脚本化。背单词的真正成本在复习不在制卡。把制卡做成一条可重复执行的管道之后真题词表、考纲词表、阅读生词——任何结构化词条数据都可以在几分钟内变成一套带例句、带发音、带标签体系的牌组。这才是Python 一键灌卡相对于手工抄卡最本质的收益不是省掉一次劳动而是让换一套词表这件事从几小时手工劳动降级为一次脚本重跑。【免费下载链接】ankiAnki is a smart spaced repetition flashcard program项目地址: https://gitcode.com/GitHub_Trending/an/anki创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?