掌上百科 - PDAWIKI

 找回密码
 免费注册

QQ登录

只需一步,快速开始

查看: 2594|回复: 8

[经验交流] 关于用Python脚本来快速批量制卡的一些经验分享

[复制链接]
  • TA的每日心情
    慵懒
    2021-9-1 08:46
  • 签到天数: 61 天

    [LV.6]常住居民II

    发表于 2021-2-19 07:28:36 | 显示全部楼层 |阅读模式
    本帖最后由 zhangchaont 于 2021-2-20 08:21 编辑 8 B3 T' b3 A; `. h, v4 o% e6 Q
    + x. X& W. s9 t8 H: Q' B* ?
    我从2013年接触Anki,刚开始觉得很难上手,中间还放弃了一段时间,这次重新开始使用是从去年的2月份,我开始用Anki来学习日语,虽然中间也走了一些弯路,但是这个让我坚持下来了,以前去外面报学习班几次也没有学下来。现在Anki已经成了我的日常,而在这个过程中,我也学会了一些和原来的目标不一样的东西,我最开始是想学英语,后来想学日语。虽然这两个目标目前的效果还行,我英文的词汇量大概3万不到,可以比较自如的阅读英文书籍,听语音书的话80%以上吧,虽然写和说还欠缺,但是也不是不能克服的。日语学了一年,N2的水平自测没有问题,N1的语法马上学完了。除了这两个之外,因为要使用Anki,我还折腾会了一些意想不到的东西,比如:Python,html,CSS等等。会写Python的简单代码是我觉得最爽的事情,它让我觉得我身边的那些不会编程的人就像哈里波特里面的麻瓜。我女儿上一年级之前已经学会了3000个汉字,现在看书已经没什么障碍了。3 G  M& X7 c. ~4 u, F' @% S$ ?
    & R% `& R$ m/ m1 A( @
    Anki已经有这么多好用的插件了,在制卡方面有FastWordQuery,为什么我们还需要自己写代码呢?因为我们各自的需求是非常个性化的,而一个插件不可能完全满足你的要求,要完全让自己满意,那就只好自己折腾了。 最开始的时候,我经常会写邮件给WordQuery(FastWordQuery的前身)的作者,向他请教一些问题,但是那时Python也不怎么会,所以还是不得要领。后来我偶然在网上找了了一篇帖子:* |8 D1 i6 {0 M/ G% ^
    https://www.juliensobczak.com/wr ... anki-scripting.html
    # @6 b4 T* }6 _* m0 }: m这个对我非常有启发,不过好像要翻墙才能看到。我打印成PDF了,感兴趣的朋友可以下下来看看。/ j7 s+ i) P2 s: H" X$ r8 i) `
    后来我又在Anki的官方论坛里面提问,得到了Anki的作者Damien Elmes的指点,现在已经可以比较自如的用Python来制卡了。
    6 d9 j& v6 P5 R: t- R( x" f4 |- d: p4 X! j. l  S' d6 o. Y
    好了,闲话不多说,在这个帖子里面,我将演示如何通过Python代码来:
    $ U) C3 y( v7 W* x7 k1. 从百度汉语里面下载汉字的发音,解释词条等制成卡片;2 R) }( \' }) @6 ^$ V$ i6 J$ A6 _: q
    2. 从mdx词典文件里面将有需要的内容拿出来制成卡片;* X6 O5 k1 ~! l9 j% V& ^. P
    3. 用Selenium从一些不能简单用requests库扒的网站上扒数据制成卡;/ A% Y$ H/ R9 K* R% X

    + K' o" q" S. m/ f* l( @首先请安装pycharm,这是一个非常好用的IDE,CE版本的是免费的,功能已经很全了。8 D0 H, M8 y9 Z+ @; c
    4 J% ~5 O" b( n1 w
    然后新建一个项目,名字随便,这里就叫anki-scripting吧。
    9 }2 `8 V/ Z9 _: W  v参照Anki的手册里面的指导https://addon-docs.ankiweb.net/#/getting-started
    8 f  n7 \  \- m, B. A, c6 \在pycharm界面下方有一个console,点开就会出来Python的命令行解释器。
    2 u& ^8 C5 V$ [; l2 C) k1 h: }
    1. import subprocess
      / Q( V, _+ W7 J' _  X; f8 Z

    2. / _  A2 B5 G1 P  S  W
    3. subprocess.check_call(["pip3", "install", "--upgrade", "pip"]), t+ I: q" L" e" }- X7 K4 b$ m: k
    4. subprocess.check_call(["pip3", "install", "mypy", "aqt"])
    复制代码
    4 t3 [4 M4 C" @$ h+ ^$ r# ^9 O
    等安装完成,我们的准备工作就完成了,如果失败请自行搜索解决。下面的内容敬请期待,准备上班去了。
    : n3 W3 y+ o+ f
    2 a# E; }  k; ^. F6 a' z$ \
    . C4 e% J1 _- K1 V: m2 _" S7 a- F1 A' G7 u
    好了,在前面的准备工作的基础上,我们现在就可以来试着来用Python来操纵Anki了。
    8 U: |- a# O! k5 L* [, ?& p# ~3 g  D" I# _, ?* B& g8 |
    Anki的数据是保存在qlite3数据库里,在macOS上,路径是~/Library/Application Support/Anki2/username/collection.anki2,Windows的搜索一下。在用户名的文件夹下面,还有一个collection.media文件夹,这个里面保存的是媒体文件,MP3、图片之类的。; d7 q1 K* ~9 X8 r* H1 E0 A# ^& `

    % m. D& L) v- m  ?0 O下面我们可以点开PyCharm下面的Python Console。
    3 W' b! m, X9 S( R
    1. from anki.collection import Collection
      " M$ L: R. h0 i. i7 P  _; _
    2. col = Collection('path to your collection')
    复制代码

    ! ]9 a" y1 w  F/ ycollection.anki2文件的路径替换一下即可。这样我们就新建了一个collection的实例,注意,Anki软件要关掉。
    7 i' y% k' I! v; ^1 T/ @% q# N+ q4 [下面我们来看看能用这个干嘛。
    9 J; i9 @. V3 k  N% i3 n2 x2 @: L
    1. # findNotes方法非常有用,查找的条件和你在Anki的浏览器里面是一样的,返回值是笔记的id号, 这里查找的条件是今天到期的笔记。6 c4 ]$ X: {8 E9 z$ Q
    2. note_ids = col.findNotes('is:due')
      ! l4 K9 ~1 P3 X: U2 h' O
    3. # 获取笔记7 [3 s6 B' K' U+ Z) M
    4. note = col.getNote(note_ids[0])0 I" W! \4 t, ?
    5. # items方法可以获取字段名和字段内容的元组) J* z. p9 \' p! y# M
    6. print(note.items()). q& W0 V+ [3 H: R% ~3 ~
    7. # fields方法返回一个包含所有字段值的列表
      6 T8 {( e5 l. X. {
    8. print(note.fields())% h0 d( s) O0 T4 j/ _, }
    9. # model方法可以获取笔记的模板
      ! i; n5 n* R# X$ E& U+ T9 {  a& Y
    10. print(note.model())4 ^0 I# L& X2 @7 m& z1 Z
    11. # 下面这条语句可以获取笔记的所有字段名( H8 t& Q4 K8 w' ^: \1 L
    12. print(col.models.fieldsNames(note.model())
    复制代码
    " Q: g0 o: f6 V$ e  K* p

    & P7 e2 Y) R! V6 {  b* ?. E  r6 y
    # \' T3 @* i0 u  f( M& h( Z% [" ^好的,下面我们来获取今天到期的卡片的第一字段里面的内容并打印出来。
    , V4 S" J" j; R5 k
    1. from anki.collection import Collection" m, E- E7 ~" \3 Z7 X
    2. col = Collection('path to your collection')
      8 J5 p7 T% M# X! Z7 S
    3. note_ids = col.findNotes('is:due')
      . P! g) a, u" |2 A
    4. for nid in note_ids:. C; N( K3 o5 _( M, c: x6 u+ `
    5.     note = col.getNote(nid)
      % |  V: f  L  ^% p" H+ P8 M
    6.     key = note.items()[0][1]0 j: P0 U+ f' s) n3 e7 ?6 u
    7.     print(key)
    复制代码

    ! [' `; ?' F3 N, a
    / {5 }$ ]$ T, \: g6 d. ~- {你可能会想,我才不想列出这些呢,我是想修改卡片啊!!!!!别急,马上就到了。6 N7 V8 }1 s! u: w% S- a& e+ |$ ^- a1 z
    8 L- f$ h6 f% C# D+ v' `
    1. # 在 获取了note对象以后,只需要几个操作就可以完成对卡片的修改! n+ R9 b' c3 C' z* V; ^
    2. note['field_name'] = 'new value'% v0 O9 x$ z; |- g, T1 k; r2 \4 A
    3. note.flush()) k3 L* b; V+ `" [4 u2 [
    4. col.save()
    复制代码
    9 t* G) _8 f# x5 p3 {
    * {- J( o) _6 {( ^. y% X
    现在你可以获取一个note对象,然后对它进行一点小小的修改,试试看。
    8 R( E! _1 p6 I0 W
    ! a# ^  l  K2 I3 l# U+ ]* G/ I
    4 ?2 m) |7 I: o" k: l+ }" l( {2 `

    ! o1 h5 X# m" k! p1 ^( b下面来讲讲如何新建卡片,在Anki里,你点击新建的时候,会默认选择当前的deck,以及当前deck的默认卡片类型,在Python里面,我们首先需要搞定这个。
    + |2 ]0 p& L$ C5 ?/ u( G
    9 W4 i: X; K% C5 j: U2 f
    1. # 下面有deck name 和 model name分别换成你要新建卡片的牌组名称和卡片类型名称        0 W4 t( E/ Z( L( a% @/ L
    2. # select deck5 B$ P, Q5 \3 s
    3.         col.decks.select(col.decks.byName('deck name')['id'])
      $ E) V  C: S- k. Z; \7 p/ g
    4. + c& j9 ]& E# c0 N+ c
    5.         # change current model" M. v; E# h- h( I* L0 L6 D7 c
    6.         model = col.models.byName('model name')
      , u5 m/ }) A0 Z/ t9 Y% h
    7.         cdeck = col.decks.current()
      $ t) ~1 l' Q' d' @4 K: A
    8.         cdeck['mid'] = model['id']
      , u3 M8 a5 U1 k1 J6 {/ f7 y
    9.         col.decks.save(cdeck)
    复制代码

    $ l% M( @$ {/ y$ q" n! q  J' `4 J8 m' |/ b: T5 Z
    9 r3 A3 o0 J/ f
    这样我们就完成了选择牌组和卡片类型,下面就到了新建卡片了。3 I; N9 j1 L$ L. M
    1. note = col.newNote()* A" V8 ]' h( k' {; K
    2. note.model()['did'] = col.decks.current()['id']: V: j2 p- x/ U: h6 h
    3. note['field name'] = 'some value'
      9 K8 W' y$ y8 ]4 h
    4. col.addNote(note)
      ( }- t! n9 X8 L
    5. col.save()
      ( @9 b, @8 _, K9 O8 k  b3 A
    6. col.close()
    复制代码
    ' [7 `6 b; ^4 N/ `

    - |/ F! {$ I; I; `7 s新建了一条笔记后,可以分别给各个字段赋值,然后用addNote方法添加到collection中,记得要用save来保存,最后要关闭collection。$ s/ Z, v. h, g4 v  C

    6 R: B. {8 C) h现在动手试试自己添加一条笔记吧。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?免费注册

    x

    评分

    2

    查看全部评分

    该用户从未签到

    发表于 2021-2-19 21:14:20 | 显示全部楼层
    楼主出个视频吧。我一般是用python操作csv文件,然后导入。相对简单点。
  • TA的每日心情
    开心
    2022-1-5 10:27
  • 签到天数: 80 天

    [LV.6]常住居民II

    发表于 2021-2-20 09:32:48 | 显示全部楼层
    感谢分享,楼主辛苦了!
  • TA的每日心情
    慵懒
    2021-9-1 08:46
  • 签到天数: 61 天

    [LV.6]常住居民II

     楼主| 发表于 2021-2-20 16:53:33 | 显示全部楼层
    drongh 发表于 2021-2-19 21:14& y8 G. ]0 T( ^# X% O
    楼主出个视频吧。我一般是用python操作csv文件,然后导入。相对简单点。
    ) H( H3 _$ @. J8 T, F; }+ {

    $ i4 }3 `. h7 W, A6 w, A; s& \我还没有录过视频,下次试试
  • TA的每日心情
    开心
    2020-4-7 17:48
  • 签到天数: 201 天

    [LV.7]常住居民III

    发表于 2021-2-20 20:33:48 | 显示全部楼层
    LZ的思路是直接对ANKI存储卡片的数据库做直接操作呀,那确实相当灵活了。
  • TA的每日心情
    开心
    2020-2-20 10:47
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2022-5-5 18:55:40 | 显示全部楼层
    楼主牛人,谢谢教程
  • TA的每日心情
    无聊
    2022-6-23 21:02
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2022-5-6 23:00:19 | 显示全部楼层
    和anki有关的学习资料太少了。学习中
    您需要登录后才可以回帖 登录 | 免费注册

    本版积分规则

    小黑屋|手机版|Archiver|PDAWIKI |网站地图

    GMT+8, 2024-5-7 03:47 , Processed in 0.070813 second(s), 9 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2023, Tencent Cloud.

    快速回复 返回顶部 返回列表