Blog

Pythonista3とBeautiful Soupで競馬の分析やってみた

私はギャンブルにはほとんど興味が無いのですが、ある美術展の仕事でパリの凱旋門賞の映像を見てからというもの競走馬に惚れてしまい、何回か競馬に行きました。お馬さん本当にかっこいい。

レースの情報はnetkeiba.comなどを参考にしているのですが、過去のデータをもっと自由に俯瞰して見たいなと思い、iOSアプリのPythonista3を使って、Webスクレイピングした情報をプロットするプログラムを書いてみました(本気じゃねえか)。

Pythonista3の設定

Pythonista3はiOS上でPythonのコーディング、実行ができるアプリです。できることの幅が広くて凄いです。

しかし、そのままでは使えるパッケージに限りがあるので、こちらを参考にPythonistaにシェルを導入します。導入したらpipでパッケージがインストールできるので、BeautifulSoupを導入します。(と思いきや、後で調べたらBeautifulSoupは元からPythonistaに入っているらしいので、シェルの導入は必要ではないです。)

pip install BeautifulSoup

呼び出すパッケージは以下のような感じ。ちなみに、実行環境は3.5です。

import numpy as np
import urllib.request
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
import re

BeautifulSoupでスクレイピング

netkeiba.comの未実施レースのページからデータを取得するとこまで書きます。

URLは直接扱えないので、urllibを使います。

race_url = 'http://race.netkeiba.com/?pid=race_old&id=c201705050211'
html = urllib.request.urlopen(race_url).read()
root = BeautifulSoup(html, 'html5lib')

BeautifulSoupの基本の記法は、以下のサイトを参考にさせて頂きました。

Pythonista3ではpandasが使えないので(2017年11月現在)、辞書にデータを保存していきます。

race_dict = {}

# Get race title
race_dict['race_title'] = root.find('dl', class_='racedata fc').dd.h1.contents[0]

# Get race date
year = race_url.split('&id=')[1][1:5]
race_dict['race_date'] = year + '/' + root.find('dl', id='race_list_header').find('a', class_='active').contents[0][:-3]

# Get race place
race_dict['race_place'] = root.find('div', class_='race_place fc').find('a', class_='active').contents[0]

# Get race num
race_dict['race_num'] = root.find('div', class_='race_num fc').find('a', class_='active').contents[0]

# Get race ground, race distance, race weather, race condition, race time
temp = root.find('dl', class_='racedata fc').p.span.contents[0].split('\xa0/\xa0')

race_dict['race_ground'] = temp[0][0]
race_dict['race_distance'] = int(temp[0][1:-1])
race_dict['race_weather'] = temp[1][3:]
race_dict['race_condition'] = temp[2][3:]
race_dict['race_time'] = temp[3][3:]

レースのページから、馬ごとのデータを取得して、オッズ順にリストに格納。

list_odds = [float(i.contents[0]) for i in root.find_all('td', class_='txt_r')]

s = np.argsort(race_dict['list_odds'])

race_dict['list_odds'] = np.array(list_odds)[s] list_horse = root.find_all(href=re.compile("http://db.netkeiba.com/horse/"))
race_dict['list_horse_name'] = np.array([i.contents[0] for i in list_horse])[s]
race_dict['list_horse_url'] = np.array([i.get("href") for i in list_horse])[s]
race_dict['list_umaban'] = np.arange(len(list_horse))[s] + 1 list_jockey = root.find_all(href=re.compile("http://db.netkeiba.com/jockey/"))
race_dict['list_jockey_name'] = np.array([i.contents[0] for i in list_jockey])[s]

list_sex_age = []
for i in root.find_all('td', class_='txt_l horsename'):
    list_sex_age.append(i.next_sibling.next_sibling.string)
race_dict['list_sex_age'] = np.array(list_sex_age)[s]

list_horse_weight = []
for i in root.find_all('a', href=re.compile('http://db.netkeiba.com/trainer/')):
    list_horse_weight.append(i.parent.next_sibling.next_sibling.string.split('(')[0])
race_dict['list_horse_weight'] = np.array(list_horse_weight)[s]

以上を元に、それぞれの馬のページにアクセスして、同様に好きな情報を取得していきます。この場合、アクセス先のサーバーに負担をかけないように、アクセス間隔を調整するなどした方が良いと思います。

matplotlibの日本語出力

どのような情報を元に何をプロットしたかは省略します、コードもめちゃめちゃ長くなってしまうので。私も現在諸々検討中。馬や騎手の調子や、体重変化とスピード、着順などを綺麗に可視化できたらなと思っています。また記事にするかもです。

ただ、デフォルトでPythonista上のmatplotlibで日本語をプロットすると、豆腐文字になってしまいます。お馬さんの名前はカタカナなのでこれでは大問題。なので、IPAフォントをPythonistaに持ってきて、プロットの際にフォントを指定してあげます。

ここから、IPAexfont00301.zipをダウンロード。解凍したipaexg.ttfとipaexm.ttfを、Pythonistaのsite-packagesフォルダにコピー。(私はDropbox経由でiOSの共有機能を使って持ってきました。)

次に、以下のようにFontPropertiesをインポートし、fp=FontProperties(fname=r’ipaexg.ttf’)でフォントを指定。

from matplotlib.font_manager import FontProperties
fp=FontProperties(fname=r'ipaexg.ttf')

プロットの際に、fontproperties=fpと指定する。

fig, axs = plt.subplots(1, 1, figsize=(8, 6))
axs.text(1, 1, 'ほげ', fontproperties=fp)
fig.savefig('graph.png')
fig.clf()

以上で、無事に日本語が出力できるはずです。savefigで保存された画像はPythonistaに保存されます。

This Post Has 0 Comments

Leave A Reply