Go言語で競馬データ収集ツールを作った
仕事でコードを書くことがほとんど無くなってきたのをきっかけに、3年ほど前から徐々に家で何か作りたい欲がでてきたので、色々流行りの言語やOSSを触っては飽き触っては飽きを繰り返してた。
流行りもいいけど、やっぱ自分で使いたいって思うもの作りたいなと思って色々考えてたら、高校時代からテキストデータに溜め込んでた競馬の格言やデータを機械学習とか使って競馬予測してみたいと思い、とりあえず競馬のデータを収集しようと思い立ったのが今年の春くらい。
この手のことは既に先駆者がいるのも想像するに容易かったので、それっぽいワードでググると速攻で見つかった。
netkeiba.comからスクレイピングしてsqliteにぶち込むScalaのスクリプトまで公開されていたので、とりあえず使ってみたけど、やっぱデータの持ち方は自分好みにカスタマイズしたいと思ったのと、自分でコードを書こうと思える材料があればそれでよかったので、公開されているコードを参考に一から自分で作ってみた。
Go言語でWebスクレイピング
今年の春に異動するまではずっと仮想化支援みたいなグループに所属していたため、業務で書いた唯一のプロダクトコードはC言語だったり、基本興味のレイヤは低かったりした。
その中で数年前にDockerの到来と共に(?)、流行りだした感があるGo言語になんとなく興味があったものの、だからと言って業務で携わることもなく、冒頭に書いた様に特にこれと作りたいものが無かったというのもあり、頭の片隅にギリギリ留まりながらも時間だけが過ぎて行った。
そういう経緯もあって、せっかくなので今回はGo言語でやってみようと思い、Goでのスクレイピングについて調べてみたところgoqueryが便利そうだったのでgoqueryでnetkeiba.comのレース結果のページをスクレイピングしデータを取得した。
で、書いたコードがこちら。
血統データをtoml形式で定義しDBへ格納
データの持ち方を自分好みにしたいと書いたが、こだわりたかったのが各馬の血統データだった。
今回作ったのはレースデータの取得に加えて、各馬の馬名、父、母父、母母父、父母父の馬名を一つのテーブルに格納するようにした。
この血統にこだわった理由は、月刊誌サラブレの「金満血統王国」(以下、金満)というコーナーを15年以上愛読しており、競馬予想するにあたり非常に影響を受けていることに起因する。金満では血統という観点を軸に、様々な格言が生み出されており、この格言をひたすら高校時代からPCのテキストファイルに(コースや種牡馬別にフォルダを分けて)書き溜めているのだけれど、いちいちレースの出走馬ごとにその馬の父/母父などを確認してそのデータと突きあわせを行うのは時間も要するし実に面倒だった。データさえ手元にあればある程度格言に基づいた予想も自動化できるという期待もあったが、TARGET等の有料ソフトの利用はあまり気が進まなく、ただただテキストファイルが増えていくだけだった。
このような背景もあり、今回取得するデータとして、各馬の血統情報に主眼を置いた。また、父名、母父名、だけでなく、それぞれの系統を一元管理したく、これも金満の影響に加えて、同サラブレ詩に掲載されている「バランスビーム」にも強く影響されている。種牡馬は様々な系統に分類され(大系統)、その分類の中でさらに分類することができる(小系統)。(例:大系統:ノーザンダンサー系 / 小系統:ダンチヒ系 等)
horsebaseではユーザが自分で好みの系統にカスタマイズできるように種牡馬と大系統/小系統をtoml形式で定義することで取得した競走馬のデータと紐付けるようにした。
またさすがに全データ1から自分で定義するのは面倒だと思うので、バランスビームの生みの親の亀谷敬正氏のHP*1をもとに、テンプレ的にある程度定義されたファイルを準備したのでそれをそのまま利用してもらってもよい。
使い方
基本的にはREADMEに大体書いたのでそちらを参考いただきたい。(無理して英語で書いたけど・・・)
インストール後はmysqlを起動し、mysqlへのアクセスユーザとパスワードをhorsebaseが提供しているhorsebase.tomlへ記載するだけで準備OK。このファイルには、データ取得開始年月日を指定できる。デフォルトでは20070101に設定している。注意点としては、現状コマンド実行時のパス常にfileディレクトリを掘ってその下にhorsebase.tomlを配置しないといけない。(そのうち改良予定...)
いくつかコマンドオプションは準備しているが、基本的には何も考えずに下記コマンド実行でデータが取得できる。
HTTPリクエストを繰り返しているので途中でサーバサイドからno such hostのようなエラーを返されてコマンドエラーで終了してしまうケースがある。その場合は、下記コマンドでデータ登録をエラー時点から再開することができる。(一応そうならないようにHTTPリクエストの頻度を抑えるというかインターバルをとるようにしている。)
コマンド終了後、下記コマンドで必要なデータは登録される。
また、一旦データを取得後、数日経った場合に、その間のデータを取得したい場合もは下記コマンドでOK。毎週末下記コマンド実行することで最新データの取得ができるようにした。(ちと多いが。。。)
ちなみに10年分くらいのデータを取得するのにかなりの時間を要するので、そこはご容赦いただきたい。
(追記: -uオプションで最後に取得したデータから現在のデータを一発で取得可能にしました。)
今後
とりあえずはこれまで手元にためてきたデータや格言を基に自動で予想をしてくれるようにして自分の毎週末の予想を楽にしたい。
その後はhorsebaseで作ったDBを基に、統計学的アプローチや、機械学習を利用した予想なんかに手を出してみたい。あとは様々な角度からのデータの視覚化なんかも面白そうだ。他にもデータを簡単に引っ張ってこれるようなUIも作りたい。
テストコードが中途半端だったり、他にも細かいところをチマチマ修正したい箇所があるので適宜コミットしていく。