掌上百科 - PDAWIKI

 找回密码
 免费注册

QQ登录

只需一步,快速开始

查看: 2550|回复: 8

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

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

    [LV.6]常住居民II

    发表于 2021-2-19 07:28:36 | 显示全部楼层 |阅读模式
    本帖最后由 zhangchaont 于 2021-2-20 08:21 编辑
    9 v: x  I4 v: J2 J: I2 F$ W/ o: n) O' B! I- p+ z1 n
    我从2013年接触Anki,刚开始觉得很难上手,中间还放弃了一段时间,这次重新开始使用是从去年的2月份,我开始用Anki来学习日语,虽然中间也走了一些弯路,但是这个让我坚持下来了,以前去外面报学习班几次也没有学下来。现在Anki已经成了我的日常,而在这个过程中,我也学会了一些和原来的目标不一样的东西,我最开始是想学英语,后来想学日语。虽然这两个目标目前的效果还行,我英文的词汇量大概3万不到,可以比较自如的阅读英文书籍,听语音书的话80%以上吧,虽然写和说还欠缺,但是也不是不能克服的。日语学了一年,N2的水平自测没有问题,N1的语法马上学完了。除了这两个之外,因为要使用Anki,我还折腾会了一些意想不到的东西,比如:Python,html,CSS等等。会写Python的简单代码是我觉得最爽的事情,它让我觉得我身边的那些不会编程的人就像哈里波特里面的麻瓜。我女儿上一年级之前已经学会了3000个汉字,现在看书已经没什么障碍了。1 b0 m+ _4 E# l9 d3 w

    4 V9 K7 R' o! ?' OAnki已经有这么多好用的插件了,在制卡方面有FastWordQuery,为什么我们还需要自己写代码呢?因为我们各自的需求是非常个性化的,而一个插件不可能完全满足你的要求,要完全让自己满意,那就只好自己折腾了。 最开始的时候,我经常会写邮件给WordQuery(FastWordQuery的前身)的作者,向他请教一些问题,但是那时Python也不怎么会,所以还是不得要领。后来我偶然在网上找了了一篇帖子:! b" y7 h5 ?! j/ G/ M0 t0 w8 i
    https://www.juliensobczak.com/wr ... anki-scripting.html
    / P  A* v, D5 l8 p2 |这个对我非常有启发,不过好像要翻墙才能看到。我打印成PDF了,感兴趣的朋友可以下下来看看。
    6 g; p  K5 R+ t8 b. [- |后来我又在Anki的官方论坛里面提问,得到了Anki的作者Damien Elmes的指点,现在已经可以比较自如的用Python来制卡了。
    5 h" x- l. f9 ~0 ]: u5 I5 O: O4 W" }) v  ^: T. T  C# r
    好了,闲话不多说,在这个帖子里面,我将演示如何通过Python代码来:' l) y4 d3 u/ m0 B0 E+ i* F
    1. 从百度汉语里面下载汉字的发音,解释词条等制成卡片;
      d, H8 c/ [) x6 D! p+ z3 T  B2. 从mdx词典文件里面将有需要的内容拿出来制成卡片;
    , R9 o7 b7 y% P' T- ]- M, F3. 用Selenium从一些不能简单用requests库扒的网站上扒数据制成卡;
      V: }, B7 i" e) O: U5 Q0 x! O  i) n% L0 o+ R5 `( ^
    首先请安装pycharm,这是一个非常好用的IDE,CE版本的是免费的,功能已经很全了。1 [0 c0 J, i- ]2 ^

    4 ~) c/ ~. r; X3 a# O4 @5 l- j然后新建一个项目,名字随便,这里就叫anki-scripting吧。
    7 k* i6 n! n% V- E9 N* h. Y# i$ Z  e参照Anki的手册里面的指导https://addon-docs.ankiweb.net/#/getting-started
    ' X- M7 ~# _: {; F, K- |- ~在pycharm界面下方有一个console,点开就会出来Python的命令行解释器。
    ) Y! x5 `+ ^; j  [: K
    1. import subprocess
      , Q4 T" i  q6 D7 f  |3 S0 \( I) c  F% u

    2. 7 w, t: I9 P8 P) W# B5 _8 u
    3. subprocess.check_call(["pip3", "install", "--upgrade", "pip"])
      - h3 y4 G. }$ ]& @
    4. subprocess.check_call(["pip3", "install", "mypy", "aqt"])
    复制代码
    - E0 F" A3 U: z9 f8 }$ y' W
    等安装完成,我们的准备工作就完成了,如果失败请自行搜索解决。下面的内容敬请期待,准备上班去了。
    ! n/ a& s2 d! o0 k, S/ p5 k/ V2 J7 a5 _( b/ m

    2 P5 ]) g- `6 j/ N
    3 A/ g* B9 w. Z, X$ r好了,在前面的准备工作的基础上,我们现在就可以来试着来用Python来操纵Anki了。& _/ {( T6 ?+ {! \' x
    9 [* x' B3 u) A" N1 x6 m
    Anki的数据是保存在qlite3数据库里,在macOS上,路径是~/Library/Application Support/Anki2/username/collection.anki2,Windows的搜索一下。在用户名的文件夹下面,还有一个collection.media文件夹,这个里面保存的是媒体文件,MP3、图片之类的。+ P% S% Y5 X, _# Y3 R

    ( O; k8 _8 c( R; R. k- u3 [下面我们可以点开PyCharm下面的Python Console。
    " q- s6 O& }# r0 q
    1. from anki.collection import Collection
      & A+ k4 b+ D# a% H8 H7 V+ f
    2. col = Collection('path to your collection')
    复制代码
    % a* j- D3 L" v
    collection.anki2文件的路径替换一下即可。这样我们就新建了一个collection的实例,注意,Anki软件要关掉。# G! T' y" c8 [% G: D+ [
    下面我们来看看能用这个干嘛。' Y' f% _. T" m+ p9 k$ U
    1. # findNotes方法非常有用,查找的条件和你在Anki的浏览器里面是一样的,返回值是笔记的id号, 这里查找的条件是今天到期的笔记。8 X2 l5 \1 l7 l2 X$ l$ A: c
    2. note_ids = col.findNotes('is:due')5 m8 K% {& r. N. ]+ S' t+ Q
    3. # 获取笔记, `' k' Q9 s- V  b
    4. note = col.getNote(note_ids[0])# Q4 L9 g& x2 b* l) Y+ Q3 m
    5. # items方法可以获取字段名和字段内容的元组9 G: s3 N* T" x, A/ H+ {
    6. print(note.items())
      # G, k. s, x7 `7 m+ g
    7. # fields方法返回一个包含所有字段值的列表  ?' k% r- [  K# L4 g2 [
    8. print(note.fields())
      6 ~; [+ ~5 K. q# A4 q: U, r
    9. # model方法可以获取笔记的模板2 ?) S, t/ S7 ?" f+ U5 V
    10. print(note.model())
      , h* p0 H2 A4 M5 \* q( [
    11. # 下面这条语句可以获取笔记的所有字段名
      " a0 Y4 B, |( T: T8 }, E: a& a6 N
    12. print(col.models.fieldsNames(note.model())
    复制代码

    9 W9 K. j- ]  t, g' ~( l# Y8 b- D( B" F% R' u! ?5 ]' r$ Y9 ~5 ]

    & w- r7 m1 [4 [4 h9 |- ~8 a% P好的,下面我们来获取今天到期的卡片的第一字段里面的内容并打印出来。
    5 M9 l( B% m4 }) `1 s2 M! X
    1. from anki.collection import Collection1 e' H( I2 F+ s- U5 C
    2. col = Collection('path to your collection')) K+ z4 B2 D$ o6 B6 V) O# @7 O
    3. note_ids = col.findNotes('is:due'): |) b4 M1 s: u
    4. for nid in note_ids:
      0 @$ z% h' s! O3 t
    5.     note = col.getNote(nid)' m! P6 a% c. b6 V
    6.     key = note.items()[0][1]8 f5 P( u3 B2 \, z: g3 A2 h
    7.     print(key)
    复制代码
    # B! O+ V/ C, w; O

    . r6 ~/ b& `7 }" U) K' j, O/ p你可能会想,我才不想列出这些呢,我是想修改卡片啊!!!!!别急,马上就到了。
    / n% `  P7 `$ Y% W+ g: E
    4 j, k) r) q+ F  ^
    1. # 在 获取了note对象以后,只需要几个操作就可以完成对卡片的修改9 Y% y: H, K0 {6 w: P
    2. note['field_name'] = 'new value'2 n, ^# g3 A1 U: x* M5 H, O4 A9 `; v
    3. note.flush()
      - n- A6 w7 [3 T9 r1 w' d' v
    4. col.save()
    复制代码

    1 l% V$ I* T, P8 @& S) M+ ?
    & R1 F. y1 Z& |  M- U' o+ S, `* H, W# `现在你可以获取一个note对象,然后对它进行一点小小的修改,试试看。+ N3 ]( T# \; K* D. A% s
    * u- m9 k3 ~6 Q) v; M# s
    $ N; v3 ]  s; t- p# j

    0 z) `' |+ W  w$ f2 n0 A  b8 o: }) s2 G2 R) Y- K; R7 O
    下面来讲讲如何新建卡片,在Anki里,你点击新建的时候,会默认选择当前的deck,以及当前deck的默认卡片类型,在Python里面,我们首先需要搞定这个。7 }: \1 r# N) r$ M" e/ }) G: v

    ( D+ T3 F& H7 @
    1. # 下面有deck name 和 model name分别换成你要新建卡片的牌组名称和卡片类型名称        6 k8 s5 k: ^2 P, {
    2. # select deck5 r/ Z- J; I7 s$ ^
    3.         col.decks.select(col.decks.byName('deck name')['id']); `+ U' t8 b& \" P

    4. 9 {' i. N7 a7 @. t) d
    5.         # change current model: a; l$ {3 R8 b" j2 \4 e" T
    6.         model = col.models.byName('model name')8 y# K: a& M" h! q! P7 P9 U# X9 y1 [
    7.         cdeck = col.decks.current()
      # j5 [( U9 e/ D' l' o
    8.         cdeck['mid'] = model['id']
      : ?# ?9 R. G% P; m2 J
    9.         col.decks.save(cdeck)
    复制代码
    5 g/ j7 b. J# O! O2 b5 |, Z7 \
    5 i( g& |0 I" T0 d( N

    0 Q2 p) ?7 f$ s% N4 F这样我们就完成了选择牌组和卡片类型,下面就到了新建卡片了。, W+ r. A) z" E
    1. note = col.newNote()/ f- v9 V1 p4 e# ?5 {' x0 \9 o
    2. note.model()['did'] = col.decks.current()['id']
      3 z6 V, T4 n0 `" ~9 \! H
    3. note['field name'] = 'some value'
      ; D! ?, m) s! b! l: ^" z; D
    4. col.addNote(note)5 r* |  g$ O" M# |' W9 g
    5. col.save()
      6 g* V0 [/ V6 u# T8 H+ Q! b8 ?( j
    6. col.close()
    复制代码
    2 ]  a8 q% s8 J5 U' O' O! q$ W
    8 w1 k7 t7 S: H
    新建了一条笔记后,可以分别给各个字段赋值,然后用addNote方法添加到collection中,记得要用save来保存,最后要关闭collection。
    - j* W' I) O. x& Q# W# [9 }0 ~5 X' ]5 @& [/ |
    现在动手试试自己添加一条笔记吧。

    本帖子中包含更多资源

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

    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:142 e* d7 }' z6 b# T1 y
    楼主出个视频吧。我一般是用python操作csv文件,然后导入。相对简单点。

    $ e% u( M. B: z) B2 b1 @. c+ k" m9 a( D6 c. O
    我还没有录过视频,下次试试
  • 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 19:25 , Processed in 0.061233 second(s), 9 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2023, Tencent Cloud.

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