本記事の目的
本記事は、下記事項を目的としています。
競走馬の競争成績

作業概要
以降では、下記の手順で「netkeiba.com」から競走馬の競争成績を取得します。
- ①競走馬IDリストを作成
※データ取得先のURLを作成するために必要となります。
- ②競走馬の競争成績を入手
①競走馬IDリスト作成
horse_id_list = race_result['競走馬ID'].unique()
解説
競走馬の競争結果のURLは、下記の構成になっています。

そのため、複数の競走馬データを取得するには、まず競走馬IDを取得する必要があります。
前回の記事で作成した「race_result」に競争馬IDが含まれているので、本処理ではそこから競走馬IDを抽出します。
変数名 | 型 | 説明 |
race_result | DataFrame | レース結果 |
「race_result」の取得方法については、↓の記事で紹介しているのでまずは読んでみてください。
実行結果

②競走馬の競争成績を入手
#メソッド:競走馬の競争成績を取得
def get_horse_result(horse_id_list):
#初期値を設定
horse_result = pd.DataFrame()
date_id_list = []
area_id_list = []
race_id_list = []
jockey_id_list = []
win_horse_id_list = []
for horse_id in tqdm(horse_id_list):#・・・・・・・・・・・・・・・・・・・・・・(※1)
time.sleep(1)# ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・(※2)
try:
#競争成績を取得
url = 'https://db.netkeiba.com/horse/result/' + horse_id
df = pd.read_html(url)[0] #・・・・・・・・・・・・・・・・・・・・・・・(※3)
#競走馬IDを追加
df['競走馬ID'] = [horse_id] * len(df)
#WEBデータを解析・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・(※4)
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html, 'html.parser')
a_all = soup.find_all('a')
cnt = 0
for a in a_all:
try:
href = a.attrs['href']
text = a.text
href_split = href.split('/')
#「日付ID」を取得・・・・・・・・・・・・・・・・・・・・・・・・・(※4)
if 'race' in href and 'list' in href and len(href) == 20:
date_id_list.append(href_split[-2])
#「競馬場ID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・(※4)
elif 'race' in href and 'sum' in href and len(href) == 22:
area_id_list.append(href_split[-3])
#「レースID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・(※4)
elif 'race' in href and len(href) == 19:
race_id_list.append(href_split[-2])
#「騎手ID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・・(※4)
elif 'jockey' in href and len(href) == 14:
jockey_id_list.append(href_split[-2])
#「勝ち馬ID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・(※4)
if 'horse' in href and len(href) == 18:
cnt = cnt + 1
if cnt > 1:
win_horse_id = href_split[-2]
#テキストに「(」が含まれている場合は、win_horse_idに置換する
if '(' in text:
win_horse_id = horse_id
win_horse_id_list.append(win_horse_id)
except:
pass
#データフレームに取得した競争成績を追加
horse_result = horse_result.append(df)
except Exception as e:
print(e)
#データフレームから不要な列を削除する
drop_list = ['映像', '馬場指数', 'タイム指数', '厩舎コメント', '備考', '賞金']
horse_result = horse_result.drop(drop_list, axis=1)
#データフレームに列を追加する
horse_result['日付ID'] = date_id_list
horse_result['競技場ID'] = area_id_list
horse_result['レースID'] = race_id_list
horse_result['騎手ID'] = jockey_id_list
horse_result['勝ち馬ID'] = win_horse_id_list
return horse_result
◆メソッドの引数と戻り値◆
カテゴリ | 変数 | 型 | 説明 |
引数 | horse_id_list | list | 取得対象の競走馬ID |
戻り値 | horse_result | DataFrame | 競走馬の競争成績 |
解説
プログレスバーを表示する(※1)
本処理では、「tqdm」を使用することでプログレスバーを表示させています。
処理状況が分かるようになるので、処理時間が長いループ処理の際に利用することをおすすめします。
for race_id in tqdm(race_id_list):#・・・・・・・・・・・・・・・・・・・・・・・・・・・・(※1)
時間間隔を設定する(※2)
スクレイピングする際には、Webサイトへの負荷を考慮する必要があります。
Webサーバーに負荷をかけると、他のユーザーがそのWebサイトを参照できなかったり、ひどい場合はサーバーが落ちてしまう場合もあります。
Pythonオンライン学習サービス PyQ
そのような迷惑をかけないためにも、クローラーは間隔をあけてWebサーバーにアクセスするといった対応が必要となります。最低1秒以上は間隔をあけるようにしましょう。
上記のように、スクレイピングする際には最低1秒以上は間隔を空けましょう。
time.sleep(1)#・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・(※2)
レース結果を取得する(※3)
スクレイピングする際には、まずは欲しい情報のHTMLを確認します。

そうすると、今回入手するデータは<table>タグであることが分かります。
この場合は、pandasの「read_html」を使用することで簡単にレース結果を入手できます。
df = pd.read_html(url)[0] #・・・・・・・・・・・・・・・・・・・・・・・・・・・ (※3)
「日付」「開催場所」等のID情報を追加する(※4)
入手したデータを機械学習で使用する際には、数値以外が使えないケースがあります。
なので本処理では、「日付」「開催場所」「レース名」「騎手」「勝ち馬(2着馬)」のID情報を取得します。
ここで「日付」のHTMLを確認してみると、
ということが分かります。

他項目についても同様の特徴が見られため、この情報をもとにID情報を取得しています。
この箇所は長いので、処理の流れを簡単に紹介しておきます。
- 1. 「urllib」でWebデータを取得
- 2. 「BeautifulSoup」で、全ての<a>タグの情報を抽出
- 3. 「href属性」の特徴(含まれる文字列、文字列の長さ)から、IDを抽出
#WEBデータを解析・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・(※4)
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html, 'html.parser')
a_all = soup.find_all('a')
cnt = 0
for a in a_all:
try:
href = a.attrs['href']
text = a.text
href_split = href.split('/')
#「日付ID」を取得・・・・・・・・・・・・・・・・・・・・・・・・・(※4)
if 'race' in href and 'list' in href and len(href) == 20:
date_id_list.append(href_split[-2])
#「競馬場ID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・(※4)
elif 'race' in href and 'sum' in href and len(href) == 22:
area_id_list.append(href_split[-3])
#「レースID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・(※4)
elif 'race' in href and len(href) == 19:
race_id_list.append(href_split[-2])
#「騎手ID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・・(※4)
elif 'jockey' in href and len(href) == 14:
jockey_id_list.append(href_split[-2])
#「勝ち馬ID」を取得 ・・・・・・・・・・・・・・・・・・・・・・・・(※4)
if 'horse' in href and len(href) == 18:
cnt = cnt + 1
if cnt > 1:
win_horse_id = href_split[-2]
#テキストに「(」が含まれている場合は、win_horse_idに置換する
if '(' in text:
win_horse_id = horse_id
win_horse_id_list.append(win_horse_id)
実行結果

参考図書
本記事の内容は、以下の図書を参考にしています。
本書は、スクレイピング以外にも
等も内容に含まれています。
Python初心者にも理解しやすい内容になっているので、ぜひ参考にしてください。
次回の内容
次回は、「netkeiba.com」から競走馬の競争成績を取得する方法を紹介します。

コメント