Quantcast
Channel: 簡睿隨筆
Viewing all articles
Browse latest Browse all 897

AHK64|用AutoHotkey V2產生Yanki MD檔,快速建立Anki閃卡

$
0
0

gh|700

本次介紹由文字檔產生出Yanki .md檔的方法,使用AutoHotkey v2腳本達成。

gh

gh

gh

1. 設定文字檔格式

  • 文字檔檔案編碼:UTF-8
  • 以分號(;)或井號(#)開頭是不處理的註解行
  • 非註解的第一行必須是以正斜線(/)開頭的路徑,指定檔案的存放資料夾
    ; ==========
    ; 單字
    ; 第1課
    /j:\JERRY\MOC\060-Anki\English-7\English-7A-1-words
    park
    koala
    ; ==========
    ; 第2課
    /j:\JERRY\MOC\060-Anki\English-7\English-7A-2-words
    postcard
    years old
    famous
    all over the world
    easy
    wait

2. 腳本

#Requires AutoHotkey v2.0
#SingleInstance Force

/*
1. 分號(;)或井號(#)開頭表示是註解行。
2. 斜線(/)開頭表示輸出資料夾
3. 單字
一行一個單字,自動到Yahoo!奇摩網站取回解釋、音標與詞類
park
*/
Global _EXPL_ := 1  ; 解釋
Global _NOTION_ := 2  ; 詞類
Global _PRONOUNCE_ := 3  ; 發音音標

; 輸入文字檔有3種格式
;  1=英文單字
;  2=片語 [Tab] 中文解釋
;  3=克漏字
Global _ACTION_WORD_ := 1
Global _ACTION_PHRASE_ := 2
Global _ACTION_CLOZE_ := 3

Global sInputFile := "j:\AHK2\English-7A.txt"  ; 輸入的設定檔, 檔案編碼:UTF-8
;;Global sOutputFolder := "j:\JERRY\MOC\060-Anki\English-7\English-7-1-words\"
Global sSeparator := A_Tab  ; 輸入檔的分隔字元

Global action_word

; 要產生的模板
; {1}=單字 {2}=詞類+中文解釋 {3}=音標 {4}=空白未用
action_word := "
(
---
tags:
  - english
  - english-word
  - english-7A
---
# {1}

---
---

{2}

{3}
{4}
)"  ; action_word

;f1::
oInputBox := InputBox("輸入設定檔名:", "輸入檔名", "w300 h100", sInputFile)
if (oInputBox.Result = "Cancel") {
  Return
}
sInputFile := oInputBox.Value

if !FileExist(sInputFile) {
  MsgBox(sInputFile . "必須先建立。", "Error!", 0)
  Return
}
_iCount := 0

FileEncoding "UTF-8"

_sTags := ""
_sOutputFolder := ""
_aEnglishWords := []
_aOutputFolders := []
_iWordCount := 0

; 為了顯示進度條,將要處理的單字加入陣列,並找出單字數目
Loop read, sInputFile
{
  iLineNumber := A_Index
  Loop parse, A_LoopReadLine, "`n"
  {
    ;MsgBox line #%A_Index%=%_sLine%.
    _sLine := A_LoopField
    _sFirstChar := SubStr(_sLine, 1, 1)
    if (_sFirstChar == ";" or _sFirstChar == "#") {  ;; 第一個字元分號或井號是註解行
      continue
    }
    if (_sFirstChar == "/") {  ;; 第一個字元 / 指定輸出資料夾
      _sOutputFolder := SubStr(_sLine, 2, 255)
      _sLastChar := SubStr(_sOutputFolder, StrLen(_sOutputFolder) - 1, 1)
      if (_sLastChar != "\") {
        _sOutputFolder := _sOutputFolder . "\"
      }
      if (!FileExist(_sOutputFolder)) {
        DirCreate(_sOutputFolder)
      }
      continue
    }
    _iWordCount++
    _aEnglishWords.Push(_sLine)
    _aOutputFolders.Push(_sOutputFolder)
  }
}  

_fProgressInc := Float(100 / _iWordCount)  ; 進度條每次要增加的數字
MyGui := Gui()
oText := MyGui.Add("Text", "w200", "產生總數: " . "0 / " . _iWordCount)
MyGui.Add("Progress", "w200 h20 cBlue vMyProgress", 0)
MyGui.Show()

_iCount := 0
Loop _iWordCount
{
  _sEnglishWord := _aEnglishWords[A_Index]
  _sOutputFolder := _aOutputFolders[A_Index]
  _iCount++

  oText.Value := "產生總數: " . _iCount . " / " . _iWordCount
  MyGui["MyProgress"].Value := _iCount * _fProgressInc
  output(_ACTION_WORD_, _sOutputFolder, _sEnglishWord, "", "")
}
MyGui.Destroy

MsgBox("處理數: " . _iCount, "Result", 0)
ExitApp(0)
Return

;; 寫出單字 sNotion: 詞性
output(iActionKind, sOutputFolder, sEnglish, sChinese, sNotion) {
  ;MsgBox("Text " . sEnglish . "=" . sChinese, "Title", 0)
  local _sOutput, _aTokens, _sChineseGet, _sNotion

  if (iActionKind == _ACTION_WORD_) {  ; 單字
    action := action_word
    try {
      _aTokens := translate(sEnglish)  ; 取翻譯、音標與詞類
      _sChineseGet := _aTokens[_EXPL_]
      _sNotion := _aTokens[_NOTION_]  ; 詞類
      ;; \r與\t會造成寫入失敗,必須先行轉換
      _sChineseGet := StrReplace(_sChineseGet, "`r", " ")
      _sChineseGet := _sNotion . " " . StrReplace(_sChineseGet, "`t", " ")
      _sEnghishGet := " " . _aTokens[_PRONOUNCE_]
      _sEnghishGet := StrReplace(_sEnghishGet, "`r", " ")

      _sOutputFilename := sEnglish . ".md"
      if (FileExist(sOutputFolder . _sOutputFilename)) {
        FileDelete(sOutputFolder . _sOutputFilename)
      }
      _sOutput := Format(action, sEnglish, _sChineseGet, _sEnghishGet, "")
      FileAppend(_sOutput, sOutputFolder . _sOutputFilename)
      return 1
    } catch (Error as err) {
      MsgBox(sEnglish . " " . err.Message, "Error!", 0)
      return 0
    }
  }
}

;; 傳入要搜尋的文字,傳回查詢到的結果
;; 再將結果以Markdown格式輸出到檔案
translate(sSearch) {
  ;msgbox sSearch=%sSearch%
  url := "https://tw.dictionary.search.yahoo.com/search?p=" . sSearch . "&fr=sfp&iscqry="

  httpClient := ComObject("WinHttp.WinHttpRequest.5.1")
  httpClient.Open("POST", url, false)
  httpClient.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
  httpClient.Send()
  httpClient.WaitForResponse()
  Result := httpClient.ResponseText

  html := ComObject("HTMLFile")
  html.write(Result)

  elements := html.getElementsByTagName("div")
  _sPronounce := ""  ; 發音
  _sNotion := ""     ; 詞類
  _sDictionaryExplanation := ""  ; 解釋

  _isFirstNotion := true
  _isFirstExplain := true
  ;MsgBox("length=" . elements.Length, "Length", 0)
  Loop elements.length
  {
    ele := elements(A_Index - 1) ; zero based collection. 不能用 []
    _sClassName := ele.className

    if (InStr(_sClassName, "pos_button") > 0) and (_isFirstNotion) {  ; 詞類
      _sNotion := ele.innerHTML
      _sNotion := StrReplace(_sNotion, "[", "\[")  ; n.[C]改成 n.\[C]
      _isFirstNotion := false
    } else if (InStr(_sClassName, "compList d-ib") > 0) {  ; 音標
      _sPronounce := ele.innerText
      _iPos := InStr(_sPronounce, "DJ[")
      _sPronounce := SubStr(_sPronounce, 1, _iPos - 1)
      _sPronounce := StrReplace(_sPronounce, "[", "\[")  ; KK[改成 KK\[
      ;Msgbox("pronounce="  _sPronounce, "pronounce", 0)
    } else if (InStr(_sClassName, "dictionaryExplanation") > 0 and _isFirstExplain) {
      _sDictionaryExplanation .= ele.innerHTML . "`r"
      _sDictionaryExplanation := StrReplace(_sDictionaryExplanation, "[", "\[")
      _isFirstExplain := false
    }
  }
  ;;MsgBox("expl=" . _sDictionaryExplanation . ", notion=" . _sNotion . ", pron=" . _sPronounce, "title",0)
  _aTokens := []
  _aTokens.Push(_sDictionaryExplanation, _sNotion, _sPronounce)

  return _aTokens
}

3. 💡 相關鏈接

💡 解說文章: https://jdev.tw/blog/8408/
✅ AutoHotkey下載: https://www.autohotkey.com/download/
✅ Google Drive原始碼、執行檔與範例設定檔下載: https://drive.google.com/drive/folders/1hoznn6SMcwkGCvAUPek5ODGMlDSNAYfO?usp=sharing
✅ yanki1.ahk 原始碼: https://gist.github.com/emisjerry/5e460bd0ea47e5a58871ed4fa6077fad

4. 教學影片

https://youtu.be/X4c4MItuBS8

##

您可能也會有興趣的類似文章


Viewing all articles
Browse latest Browse all 897

Trending Articles