Skip to main content

netkeiba のデータをスクレイピングして LOD 化する(1)

Kiai
@Ningensei848

改めて,Netkeiba からスクレイピングをやっていく. Python でやるのは,リクエストに間隔を開ける都合上,多少時間がかかっても問題がないことや,DataFrame 系の資産を使い回せることが利点として挙げられる

https://github.com/Ningensei848/ml4keiba

ギリシャ神話に出てくる蛇を持つ医者アスクレーピオス(へびつかい座)

前回までの反省として,何も考えずひたすらにスクレイピングしていた というものが挙げられる.すなわち,不要なデータまでも「必要かもしれない」と集めて時間を浪費していた.これは,リストを作ってそれを一つずつ実行する設計になっていたことが原因だ.

例えば本日はちょうど「弥生賞ディープインパクト記念」をやっている. このレースの予想をデータ分析によって行う場合に,「天皇賞(春)」のデータが必要だろうか?

最初から「完璧」を目指して作ろうとするからポンコツ不完全にしかならないという現実があるので,実際のレース時期に合わせてちいさくはじめていくべきだろう.

今回で言えば,弥生賞に出てくる馬それぞれの過去のレースを探ったり,過去の弥生賞についてデータを浚ったりするのが常道といえる.

てがかり

まず,レースに出走する馬の一覧を入手する必要がある.

netkeiba では,YYYYPPNNDDRR という ID でレースごとの情報が管理されている.

  • YYYY: 開催年度
  • PP: 会場コード
  • NN: N 回目
  • DD: 第 D 日
  • RR: 第 R レース

といった具合である.

過去の調査では,PP が厄介なことに,「地方」「海外」も雑多に含まれることがあり,単にインクリメントしているわけではないらしい.

(と,これを調べる過程で netkeiba.com が設立されたのが 1999 年末だということを知った,1そろそろ四半世紀にもなる上に前世紀からデータ提供をやってるんだからすげぇ)

ASCII.jp:ネットドリーマーズ、競馬のポータルサイト“netkeiba.com”を開設

これを書いているのは火曜日だが,週末に行われるレースについては現時点で出走馬も枠順も決まっていなかった.ただし週末に行われる重賞レースに登録されている馬の一覧は見ることができた.調べてみると netkeiba においては,以下のようなスケジュールで情報が書き換わるようだ:

  • 前週の日曜(G1 は前々週) 特別レース登録馬を公開
  • (netkeiba 独自)水曜 20 時ごろ 取材などからわかった水曜時点で出走意思のある馬(想定馬一覧)
  • 木曜 16 時ごろ    出走馬確定
  • レース前日 10 時ごろ 枠順確定

特別レース(特別競走) とは,"一般競走と違って、特別登録を必要とする競走。特別競走には、現在の中央競馬ではすべてレース名がつけられている。また重賞競走も特別競走のなかに含まれる" ものであるらしい.また一般競走とは,特別競走以外,すなわち新馬戦やオープン戦,条件戦などのことを指す2

つまり,おおよそほとんどの場合において,木曜日の夜あたりから情報収集を始めるのが良いということがわかる. また,枠順が決まらないことには予想も固まらないことを考えると,レース前日の夕方から準備し始めても十分に間に合う. 金曜+土日でレース本番への対策を行ない,それ以外の日には別の情報収集+メンテナンスや振り返りというペース配分になるだろう.

(※これは中央競馬だけにフォーカスした場合の話で,平日もガンガン走っている地方競馬はまた別の話)

出走馬一覧をシードとして…

netkeiba では,出走馬ごとに ID が振られており,それによって血統や戦績,厩舎や騎手などの情報を管理している.

日本生まれ,かつ出生情報がきちんと揃っている場合には https://db.netkeiba.com/horse/YYYYXXXXXX と表記される(YYYY は生年). 一方で海外産馬などの都合で情報が不明瞭な場合は https://db.netkeiba.com/horse/000a00033a といった ID が振られている(ちなみにこの URL はサンデーサイレンス). 000a はほぼ共通だが,それ以外についてはひと目見ただけではあまり共通項が見えてこない.


各馬について,スクレイピングの対象となるのは以下の5つのページである:

  • /: プロフィール
  • /result: 競走成績
  • /ped: 血統
  • /sire or /mare: 産駒の競走成績(繁殖入りした馬のみ)

プロフィール

各馬のトップページにアクセスするとまっ先に目に入るのがプロフィールである. 生まれに関する基礎情報や写真なんかもおいてあるし,他のページに詳しく掲載される情報も概要がまとめてある.

ここで収集すべきは,div.horse_title, div.db_photo_box>img, dl.tekisei>dd>table.tekisei_table, div.db_prof_table の4箇所だ. それぞれ,「名前」「写真」「適正評価」「プロフィール」が掲載されている.

また,「繁殖入りできたかどうか?」の判定のために〈産駒成績〉タブの有無も見つけられるようにしたい. ul.db_detail_menu を探るといいだろう.

競走成績

競走成績一覧のページでは,その馬が一つでもレースに出ていれば,結果が表として出力される. table.db_h_race_results を収集すればいいだろう. 未出走の場合や海外産馬の場合には表がないこともある.例外処理には気をつけたい.

血統

こちらも同じく真ん中にデカデカと血統表が出力される. table.blood_table を収集すればいいだろう. 名前等はこの時点では収集せず……と思ったが,後々必要になる気もしてきた.

また,兄弟等の近親についても情報があるが,敢えてこれを探りに行くのは骨が折れる. ある程度データを集めてから,自前で謹慎を探せるようにするほうが良いと思われる.

表の組み方が特殊なことに留意.

産駒成績

牡馬であれば /sire, 牝馬であれば /mare のページを持つ場合がある. これは,繁殖入りできるほど血統的に期待される,或いは競走成績が良かった馬ということで,勝ち馬予想のためには必要不可欠な要素ではある. が,あくまで統計的な情報でしかなく,最初から予想アルゴリズムに組み込むのは難しいかもしれない.

産駒成績のページの存在判定は各馬のトップページでもタブを見ればできるはずなので,一旦保留して関知しないこととする.

一旦まとめ

netkeiba からスクレイピングしてくるための検討をした.

スクレイピング処理の部分と LOD 化する部分の話がまだ書けていないが,一旦 Puslish しておく. (まぁどうなるかわからないが,前編ということとする)

Python によるスクレイピング処理とはすなわち, (1) requests (あるいは aiohttp )でページコンテンツを取得し,(2) それを BeautifulSoup 3 にして (3) pandas でテーブルとか引っこ抜くことである. この辺は以前に何度もやっているのでそのへんの資産を使い回せたら嬉しいな……

LOD 化するというのは,どうしようかまだ悩むところである. オープンデータにすることを考えると,いちいち事前知識が必要になる TTL 形式のみで提供するのは避けたい. となると JSON-LD か?となるがこれもこれでファイル容量の無駄遣いが大きい気がする……

TSV で提供 & TTL への変換ツールも提供という形がもっともスマートな解だと信じたい.

Footnotes

  1. というかそんな時期の記事にまだアクセスできる ASCII の根性がスゲェ,尊敬に値する

  2. レースの種類、条件など(競馬用語辞典)JRA を参照のこと

  3. 現時点 (2022/03/08) の最新版は Python 3.8 前提の 4.10.0 である(なお日本語訳は 4.2.0 までしかない模様)