昨天把網頁載好,不過裡面的資料似乎很難處理。後來有找到另一個 API:
https://www.moedict.tw/a/字.json
它會回傳 JSON 格式的字串,解析簡單很多。而 YAML 套件也能解析 JSON,直接上吧!
開工 首先先把 URL 改掉:
const ( dictionary = `https://www.moedict.tw/a/%s.json` )
呼叫改使用 fmt.Sprintf()
:
req := goreq.Request{ Uri: fmt.Sprintf(dictionary, string (word)), }
這樣執行應該回傳就會變成 JSON 格式了。
下一步是要把 JSON 轉成 go 的資料型態,這次的結構就很鬆散了,改用 Map 做會比較簡單:
type MoeDict struct { Heteronyms []Heteronym } type Heteronym struct { Definitions []string } func convertJsonToStruct (json string ) (dict MoeDict, err error ) { m := make (map [interface {}]interface {}) yaml.Unmarshal([]byte (json), &m) heteronyms := convertHeteronyms(m["h" ]) return MoeDict{heteronyms}, err } func convertSliceMap (sliceMap []interface {}) (sm []map [interface {}]interface {}) { for _, m := range sliceMap { sm = append (sm, m.(map [interface {}]interface {})) } return sm } func convertHeteronyms (in interface {}) (out []Heteronym) { heteronyms := convertSliceMap(in.([]interface {})) for _, heteronym := range heteronyms { definitions := convertDefinitions(heteronym["d" ]) out = append (out, Heteronym{ definitions, }) } return } func convertDefinitions (in interface {}) (out []string ) { definitions := convertSliceMap(in.([]interface {})) for _, definition := range definitions { def := convertDef(definition["f" ].(string )) out = append (out, def) } return } func convertDef (in string ) string { def := in def = strings.Replace(def, "~" , "" , -1 ) def = strings.Replace(def, "`" , "" , -1 ) return def }
因為原始資料的設計是多讀音配多種解釋,會是樹狀結構加一堆陣列,所以必須要很多 for
來處理。
而 QueryCommand 改寫成這樣:
dict, err := provider.Query(str) for _, heteronym := range dict.Heteronyms { for _, definition := range heteronym.Definitions { fmt.Println(definition) } }
展示 $ go run main.go query 萌 草木初生的芽。 事物發生的開端或徵兆。 人民。 姓。如五代時蜀有萌慮。 發芽。 發生。
目前沒把讀音做篩選,不過這樣也感覺蠻有樣子了。
程式碼可以參考 PR Day 22
參考資料