先日、 iTunes での楽曲情報を BigQuery に流し込むスクリプトを Go で書いた というタイトルで Qiita に投稿した。なにげに Qiita 初投稿。(Qiita:Team は業務で使ってるんだけどね)
GAE/G での写経は細々とやっていたんだけど、純粋にツール的なものを Go で書いたのは初めて。てなわけで(?)、特に今回のスクリプトを書いてみた上での感想をここに綴ってみる。
iTunes が吐く plist のパースは大変
いきなり Go とは関係ない感想なんだけど。。 上述の Qiita の方にも書いたんだけど、iTunes は楽曲情報その他を plist 形式の xml ファイルとして出力してくれている。楽曲をたくさん入れてる人だと100MBを超えるサイズになることも珍しくないみたいなんだけど、こいつのパースには骨が折れた。
go-plist という、golang で書かれた plist を解析するためのライブラリがあるのを知って、最初はこれを使おうとしてみてたんだけど、結局うまくいかなかった。 というのも、通常 plist は下記のような形式であるのが普通なんだけど、
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>band-size</key> <integer>8388608</integer> <key>bundle-backingstore-version</key> <integer>1</integer> <key>diskimage-bundle-type</key> <string>com.apple.diskimage.sparsebundle</string> <key>size</key> <integer>4398046511104</integer> </dict> </plist>
↑ key
で指定される文字列は、全ての dict
element において共通。
一方、iTunes の吐く plist は下記のように、key
で指定される文字列が Track ID
となっていて、 dict
element 毎に変わる。
<key>3013</key> <dict> <key>Track ID</key><integer>3013</integer> <key>Name</key><string>01_ハイファイ・ローファイ</string> <key>Artist</key><string>スピッツ</string> <key>Album</key><string>99ep</string> <key>Genre</key><string></string> <key>Kind</key><string>MPEG オーディオファイル</string> <key>Size</key><integer>3489248</integer> <key>Total Time</key><integer>145371</integer> <key>Track Number</key><integer>1</integer> <key>Date Modified</key><date>2005-09-17T13:26:15Z</date> <key>Date Added</key><date>2005-09-16T11:16:43Z</date> <key>Bit Rate</key><integer>192</integer> <key>Sample Rate</key><integer>44100</integer> <key>Persistent ID</key><string>2A0848311638F0A2</string> <key>Disabled</key><true/> <key>Track Type</key><string>File</string> <key>Location</key><string>file://localhost/xxx.mp3</string> <key>File Folder Count</key><integer>-1</integer> <key>Library Folder Count</key><integer>-1</integer> </dict>
これに、上述のライブラリは対応していなかった。
最初は、go-plist
に対して、これに対応できるようにする PR を出すとかもアリか...? とか思ったんだけど、それをするには Go 力が足りず、断念してしまった(試行錯誤したときのPR)。
結局今回は、SAXを使って地道にパースを行った。
なぜ Go を選択したか
これは簡単で、今なら Go で書けばどんなものでも話題になると思ったから。なんとも不純な動機だけど。
C言語 -> Goの人だったらまぁ、分かる。馴染むかもしれない。けど、RubyからGo言語に移行する人は正直、流行に流されている感がしている。つまりなにが良いたいかと言うと、Common Lispを書け。
— はなだのぶかずakaイケメンLisper (@nobkz) 2014, 11月 22
乗るしか無い、この(ry
一応外向け(?)の理由を付けるとするならば、"Go で書いておけばクロスプラットフォームを実現するのが簡単だから"、っていうのはあるかな。Win でも Mac でも遊べる方が、より多くの人に使ってもらいやすいと思うので。。
でも蓋を開けてみたら、大して伸びてなくて涙目w
Google Cloud Platform との連携に Google Cloud SDK(外部コマンド gcloud
)を利用している点
これも、恥を承知で、楽をしたいがために利用してしまったというかんじ。会社の同僚さんにも、「極端な話、外部コマンドの羅列なら shellscript でも出来ますしね」とも言われたので、いつかは直したいと思ってる。 ただ、メリットを無理矢理見出すとすれば、認証周りも Google Cloud SDK にお任せしているので、利用する側からすれば少しは安心できるんじゃないかな、とか思ったり。
ネーミングについて
イキって Goramoph
なんていう名前にしたんだけど、これは "蓄音機(Gramophone)" を文字ってみたもの。やろうとしてることのイメージになんとなく近いし、アルファベットの "G" も含まれているし(Go なので...)、ってことで、これにした。
もし "itunes-xml-load-to-bq" みたいな名前だったら、最後までやり通せなかったかもしれない。w