掌上百科 - PDAWIKI

 找回密码
 免费注册

QQ登录

只需一步,快速开始

查看: 2549|回复: 8

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

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

    [LV.6]常住居民II

    发表于 2021-2-19 07:28:36 | 显示全部楼层 |阅读模式
    本帖最后由 zhangchaont 于 2021-2-20 08:21 编辑
    + S4 r1 `3 v  H8 L' i4 R8 z7 ^- u4 F3 l, x1 v8 D8 ~
    我从2013年接触Anki,刚开始觉得很难上手,中间还放弃了一段时间,这次重新开始使用是从去年的2月份,我开始用Anki来学习日语,虽然中间也走了一些弯路,但是这个让我坚持下来了,以前去外面报学习班几次也没有学下来。现在Anki已经成了我的日常,而在这个过程中,我也学会了一些和原来的目标不一样的东西,我最开始是想学英语,后来想学日语。虽然这两个目标目前的效果还行,我英文的词汇量大概3万不到,可以比较自如的阅读英文书籍,听语音书的话80%以上吧,虽然写和说还欠缺,但是也不是不能克服的。日语学了一年,N2的水平自测没有问题,N1的语法马上学完了。除了这两个之外,因为要使用Anki,我还折腾会了一些意想不到的东西,比如:Python,html,CSS等等。会写Python的简单代码是我觉得最爽的事情,它让我觉得我身边的那些不会编程的人就像哈里波特里面的麻瓜。我女儿上一年级之前已经学会了3000个汉字,现在看书已经没什么障碍了。
    * T) h! c8 I& |" l: _
    ' q8 p6 s6 U: Y. t9 h& ]Anki已经有这么多好用的插件了,在制卡方面有FastWordQuery,为什么我们还需要自己写代码呢?因为我们各自的需求是非常个性化的,而一个插件不可能完全满足你的要求,要完全让自己满意,那就只好自己折腾了。 最开始的时候,我经常会写邮件给WordQuery(FastWordQuery的前身)的作者,向他请教一些问题,但是那时Python也不怎么会,所以还是不得要领。后来我偶然在网上找了了一篇帖子:
    8 C  w6 s! x/ G/ [8 ghttps://www.juliensobczak.com/wr ... anki-scripting.html, S1 `3 ]4 g- P% Y
    这个对我非常有启发,不过好像要翻墙才能看到。我打印成PDF了,感兴趣的朋友可以下下来看看。
    3 M3 |8 j9 r; L& d: q后来我又在Anki的官方论坛里面提问,得到了Anki的作者Damien Elmes的指点,现在已经可以比较自如的用Python来制卡了。
    6 S1 _7 `) {! v" S# P& i/ Z
    % v$ j$ G/ L1 _" f* Z好了,闲话不多说,在这个帖子里面,我将演示如何通过Python代码来:
    ) z3 W( s5 }7 I1. 从百度汉语里面下载汉字的发音,解释词条等制成卡片;
    : f1 }8 ]# ^& t, ^& ~" L. W) c2. 从mdx词典文件里面将有需要的内容拿出来制成卡片;
    4 s  m* W2 S# t& I3. 用Selenium从一些不能简单用requests库扒的网站上扒数据制成卡;
    2 B$ d$ B" W6 `+ D2 H/ E( a! {$ B. O; f4 T3 ?
    首先请安装pycharm,这是一个非常好用的IDE,CE版本的是免费的,功能已经很全了。3 }, v+ n! A5 y1 x
    , `5 |8 _% I) K1 g) J2 u
    然后新建一个项目,名字随便,这里就叫anki-scripting吧。
    ) M/ }& p# H8 I0 G参照Anki的手册里面的指导https://addon-docs.ankiweb.net/#/getting-started; m9 B6 u* s1 S" ~1 e$ Q
    在pycharm界面下方有一个console,点开就会出来Python的命令行解释器。5 p( j8 i4 y3 w3 e
    1. import subprocess
      & \; T2 `+ Y: `4 \7 N4 g8 m

    2. . ~9 U2 o- I" _5 q5 m" }
    3. subprocess.check_call(["pip3", "install", "--upgrade", "pip"]), D+ n. h% d& m9 o; n/ p
    4. subprocess.check_call(["pip3", "install", "mypy", "aqt"])
    复制代码
    9 K0 `3 Z9 z1 S; a" t- t! s: ]
    等安装完成,我们的准备工作就完成了,如果失败请自行搜索解决。下面的内容敬请期待,准备上班去了。( S0 \( Z$ x" M: j" {

    5 S# o; Q4 ?! ]! ~8 O! g6 s& p4 H$ X  n! Y
    ( }. O# p0 x  [) \/ R. E2 ^( F
    好了,在前面的准备工作的基础上,我们现在就可以来试着来用Python来操纵Anki了。- R5 A) L; B& m( Z! n4 h

    " \% k* X7 L' f: D# m5 J4 J& XAnki的数据是保存在qlite3数据库里,在macOS上,路径是~/Library/Application Support/Anki2/username/collection.anki2,Windows的搜索一下。在用户名的文件夹下面,还有一个collection.media文件夹,这个里面保存的是媒体文件,MP3、图片之类的。. t0 Q- }/ ~- h: O) f& |+ N/ c

    ' @/ k; R# E9 Z2 F下面我们可以点开PyCharm下面的Python Console。
    # v# y/ p  H, U% q8 T8 \
    1. from anki.collection import Collection
      ! j7 }# ~! a7 p5 L5 O5 z" E
    2. col = Collection('path to your collection')
    复制代码

    $ h' Z) E' Q+ \/ qcollection.anki2文件的路径替换一下即可。这样我们就新建了一个collection的实例,注意,Anki软件要关掉。
    8 [  C# C- S7 c. ?. t% A, c" }! V下面我们来看看能用这个干嘛。
    9 R: C& [! c" T5 i3 p2 K" G$ t
    1. # findNotes方法非常有用,查找的条件和你在Anki的浏览器里面是一样的,返回值是笔记的id号, 这里查找的条件是今天到期的笔记。4 W& l: j, `6 a2 I8 _
    2. note_ids = col.findNotes('is:due')
      . W: X9 o$ p' Y8 E$ P" l
    3. # 获取笔记, K! ]1 f0 N9 o
    4. note = col.getNote(note_ids[0])
      $ l4 w, E) l2 g8 ~* i
    5. # items方法可以获取字段名和字段内容的元组; D' k) [" Z  J! V0 s6 Z2 x1 `
    6. print(note.items())
      4 y8 x' A" H1 l1 H) I
    7. # fields方法返回一个包含所有字段值的列表  o4 n4 ?4 M  ~7 Y1 b0 G
    8. print(note.fields())# {9 G6 Z  j. ^% j! O  b. {
    9. # model方法可以获取笔记的模板
      ) X" r, o5 \5 S0 b9 x% a
    10. print(note.model())
      8 t1 ?1 o3 T6 b* @. U6 c
    11. # 下面这条语句可以获取笔记的所有字段名
      ' R$ x$ Y- [5 n! k, d+ E! F; _
    12. print(col.models.fieldsNames(note.model())
    复制代码

    0 R' s+ t% ^7 _/ e1 d- C- z
    " e+ n. W  q5 i% s& y/ ~
    ) z; A4 p# q! K4 T3 E好的,下面我们来获取今天到期的卡片的第一字段里面的内容并打印出来。
    - r/ K2 a( x( Y! u
    1. from anki.collection import Collection
      $ W4 c' P4 M) _" E* W
    2. col = Collection('path to your collection')( z; L7 ?; t: n5 H4 x3 J2 y
    3. note_ids = col.findNotes('is:due')- k* c( G" W$ W$ E% D! B: z
    4. for nid in note_ids:
      4 K1 q: W" \" W# l. Y0 n* ?
    5.     note = col.getNote(nid)
      : A8 p) b9 Y$ H4 H- e: E
    6.     key = note.items()[0][1]
      0 e/ O' n0 Z5 P6 \# `
    7.     print(key)
    复制代码
    0 @3 Q( N7 c' @; T5 z  E
    . g5 T# ?+ R4 M/ Q& J( ^  S
    你可能会想,我才不想列出这些呢,我是想修改卡片啊!!!!!别急,马上就到了。' I- L4 w9 e& j+ n% O2 r4 P

    8 }5 X6 A8 p' E2 y& R, u
    1. # 在 获取了note对象以后,只需要几个操作就可以完成对卡片的修改
      / A0 o; x% P: [- K! S8 i1 |
    2. note['field_name'] = 'new value'" F: T% {2 G0 g/ Z
    3. note.flush()6 |) T5 g) Y3 }9 u9 E2 j
    4. col.save()
    复制代码

      ]0 m$ J( t& z  f- Z; @3 y. }& G) X
    现在你可以获取一个note对象,然后对它进行一点小小的修改,试试看。6 h+ s5 o/ C5 e' O! ^

    7 E  M5 Y4 h7 p  E" `+ N& T$ u  `! t6 q8 s, y- R( Y, Z

    ( G: _' ~! i% H& N. r! w7 C  B; @+ w$ V
    下面来讲讲如何新建卡片,在Anki里,你点击新建的时候,会默认选择当前的deck,以及当前deck的默认卡片类型,在Python里面,我们首先需要搞定这个。) X5 O' z* ~& M: p" }

    5 O0 |3 k/ e  F! h
    1. # 下面有deck name 和 model name分别换成你要新建卡片的牌组名称和卡片类型名称        0 I  B1 M6 K- b4 S3 a# S* a0 M
    2. # select deck, R, G2 m8 E3 Z1 c
    3.         col.decks.select(col.decks.byName('deck name')['id'])
      & |- z# e8 m/ k4 W2 e! t  r# H

    4. # x- Q. T  o- N8 P) }; t
    5.         # change current model
      / g+ l1 `; _0 Q4 k& w
    6.         model = col.models.byName('model name')/ L9 p$ ]8 n$ B6 @( h  z
    7.         cdeck = col.decks.current()
      / Z9 n' G  i) i& @$ b2 A. Z; _
    8.         cdeck['mid'] = model['id']2 T% S: q( K# l8 H2 f5 S+ y8 L
    9.         col.decks.save(cdeck)
    复制代码

    ! p$ E( c+ J2 \  P( y8 V0 ^' d
    2 j) t4 M' U% J" |% Z) a/ y
    , L" k7 V7 k7 V' h8 @, x$ P" ?, H: |这样我们就完成了选择牌组和卡片类型,下面就到了新建卡片了。. l( \, D( ^4 ^+ e; c$ L: J4 T0 A
    1. note = col.newNote()
        W3 E' ]$ O, p+ Q
    2. note.model()['did'] = col.decks.current()['id']& \0 |( x: v2 B$ }0 p. g
    3. note['field name'] = 'some value'% F3 s! E/ h$ {: r& w
    4. col.addNote(note)
      $ Y9 M, \7 ~) B! P! G, `
    5. col.save()
      # o. x+ p( J4 i& M0 ~. q
    6. col.close()
    复制代码
    9 U% Z4 I, e& ^% Z/ g
    / U: q' q6 l/ Q: s+ {5 q
    新建了一条笔记后,可以分别给各个字段赋值,然后用addNote方法添加到collection中,记得要用save来保存,最后要关闭collection。
    : [+ q8 v) C" R- x# ]# O" G
    + A  w) B1 u& Q9 {( B现在动手试试自己添加一条笔记吧。

    本帖子中包含更多资源

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

    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
    , \- p' v/ q3 n( G- V+ R楼主出个视频吧。我一般是用python操作csv文件,然后导入。相对简单点。

    ) l  z, P. R9 R6 ~0 r# T, A/ U/ O
    . G( H% Q/ C$ h, m+ z我还没有录过视频,下次试试
  • 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-4-28 03:17 , Processed in 0.062589 second(s), 9 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2023, Tencent Cloud.

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