本記事の目的
開催レース一覧【地方競馬】

作業概要
本サイトでは、下記の手順で「netkeiba.com」からレースデータを取得します。
- ①開催レースのURL一覧を取得
・①-1:中央競馬
・①-2:地方競馬 ←このページ

このページでは、「①-2:開催レースのURL一覧 (地方競馬) を取得」を解説するよ
①開催レースのURL一覧を取得

ソースコード
""" メソッド: 【地方競馬】レース結果のURL一覧取得 """
# ライブラリ
import datetime
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import time
import pandas as pd
def get_url_local(start_str, end_str):
# 初期値
driver_path = 'C:/Users/kouhe/OneDrive/01_Documents/02_機械学習/スクレイピング/chromedriver.exe'
url = 'https://nar.netkeiba.com/top/?rf=navi'
target_flg = False
interval = 30
ret_df = pd.DataFrame(columns=['date', 'url'])
url_list = []
# 文字列を日付型に変換
start_target = datetime.datetime.strptime(start_str, '%Y%m%d')
end_target = datetime.datetime.strptime(end_str, '%Y%m%d')
# Google Chromeで「レース結果一覧」を開く ---------------------- (※1)
browser = webdriver.Chrome(executable_path=driver_path)
browser.implicitly_wait(interval)
browser.get(url)
wait = WebDriverWait(browser, interval)
while not target_flg:
# 画面に表示されている開催日を取得 ---------------------- (※2)
date_list = []
div_tag = browser.find_element_by_css_selector('div#RaceTopRace.RaceList_Date_Top')
li_tag_list = div_tag.find_elements_by_css_selector('li.ui-tabs-tab.ui-corner-top.ui-state-default.ui-tab')
for li_tag in li_tag_list:
date = li_tag.get_attribute('date')
if date is None:
continue
else:
date_list.insert(0, date)
# 取得対象データの場合、レース結果ページのurlを取得
for date_str in date_list:
print('日付 : ', date_str)
# 取得対象データであるかをチェック
date_target = datetime.datetime.strptime(date_str, '%Y%m%d')
if date_target > end_target:
pass
elif date_target < start_target:
# 重複するURLを削除
ret_df = ret_df.drop_duplicates(subset='url')
# インデックスを振りなおす
ret_df = ret_df.reset_index(drop=True)
# ブラウザを閉じる
browser.close()
return ret_df
else:
# 月と日を取得
month_str = date_str[4:6]
day_str = date_str[6:8]
# 曜日を取得
week = date_target.strftime('%a')
if week == 'Sun':
week_str = '日'
elif week == 'Mon':
week_str = '月'
elif week == 'Tue':
week_str = '火'
elif week == 'Wed':
week_str = '水'
elif week == 'Thu':
week_str = '木'
elif week == 'Fri':
week_str = '金'
elif week == 'Sat':
week_str = '土'
# 開催日をMM月YY日(Z)に変換 ---------------------- (※3)
date_str_mod = month_str + '/' + day_str + '(' + week_str + ')'
# 日付タブをクリック ---------------------- (※4)
text = div_tag.find_element_by_partial_link_text(date_str_mod)
browser.execute_script('arguments[0].scrollIntoView(true);', text)
text.click()
# 画面に表示されている競馬場を取得
ul_tag = div_tag.find_element_by_css_selector('ul.RaceList_ProvinceSelect')
a_tag = ul_tag.find_elements_by_tag_name('a')
for a in a_tag:
# 競馬場タブをクリック
if a.text == '':
continue
area_text = ul_tag.find_element_by_partial_link_text(a.text)
browser.execute_script('arguments[0].scrollIntoView(true);', area_text)
area_text.click()
# レース結果ページのURLを取得 ---------------------- (※5)
class_list = div_tag.find_elements_by_css_selector('li.RaceList_DataItem ')
url_list = []
for element in class_list:
a_tag_list = element.find_elements_by_tag_name('a')
for a_tag in a_tag_list:
try:
url = a_tag.get_attribute('href')
if 'race/result' in url:
url_list.append(url)
except Exception:
continue
# 戻り値のデータフレームに取得結果を格納
ret_date_list = [date_str] * len(url_list)
ret_list = list(zip(ret_date_list, url_list))
df = pd.DataFrame(ret_list, columns=['date', 'url'])
ret_df = ret_df.append(df)
# 画面に表示されているURLを取得後、 「前」ボタンを1回クリックする ---------------------- (※6)
try:
text = browser.find_element_by_partial_link_text('前')
browser.execute_script('arguments[0].scrollIntoView(true);', text)
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'Active')))
text.click()
time.sleep(1)
except Exception as e:
print('例外が発生しました。')
print(e)
# URLが重複する行を削除する
ret_df = ret_df.drop_duplicates(subset='url')
# インデックスを振りなおす
ret_df = ret_df.reset_index(drop=True)
# ブラウザを閉じる
browser.close()
return ret_df
◆メソッドの引数と戻り値◆
カテゴリ | 変数名 | 型 | 説明 |
引数 | start_str | str | 取得開始日 |
end_str | str | 取得終了日 | |
戻り値 | ret_df | DataFrame | レース結果のUR一覧 |
解説
Google Chromeで「レース結果一覧」を開く(※1)
「開催レース一覧」ページは、上部の「日付ボタン」や「競馬場ボタン」、「前ボタン」、「後ボタン」をクリックしないと、画面に表示されていない開催日のレース結果URLを取得できません。

なので、今回はWebブラウザーを遠隔操作する「Selenium」というモジュールを使用して、スクレイピングを行います。
本ページでは「Google Chrome」を遠隔操作して、開催レースのURL一覧を取得する方法を解説します。
- ①Google Chromeを起動
- ②ドライバの初期化が完了するまで、最大3秒間待つ
- ③URLを読み込む
# Google Chromeで「レース結果一覧」を開く ------------------ (※1)
browser = webdriver.Chrome(executable_path=driver_path)
browser.implicitly_wait(interval)
browser.get(url)
画面に表示されている開催日を取得(※2)
スクレイピングする際には、まずは欲しい情報のHTMLを確認する必要があります。

「開催レース一覧」のHTMLを、↓の動画のように確認すると、
ということが分かります。
この情報をもとに、下記の処理で開催日を取得しています。
- ①開催日を格納する空リストを準備する
- 「ID属性」が”RaceTopRace”、かつ「class属性」が”RaceList_Date_Top”である、<div>タグを取得する
- ③取得した<div>タグの中から、<li>タグを取得する
- ④取得した<li>タグの中から、「date属性」を取得する
- ⑤「date情報」を取得できた場合は、①のリストに追加する
# 画面に表示されている開催日を取得 ---------------------- (※2)
date_list = []
div_tag = browser.find_element_by_css_selector('div#RaceTopRace.RaceList_Date_Top')
li_tag_list = div_tag.find_elements_by_css_selector('li.ui-tabs-tab.ui-corner-top.ui-state-default.ui-tab')
for li_tag in li_tag_list:
date = li_tag.get_attribute('date')
if date is None:
continue
else:
date_list.insert(0, date)
開催日をMM月YY日(Z)に変換(※3)

↑の赤枠の箇所をクリックするために、先ほど取得した開催日の変数「date_list」から、文字列「MM月YY日(Z)」を作成します。
- ①月と日を取得
- ②曜日を取得
- ③開催日をMM月YY日(Z)に変換
# 月と日を取得
month_str = date_str[5] if date_str[4] == '0' else date_str[4:6]
day_str = date_str[7] if date_str[6] == '0' else date_str[6:]
# 曜日を取得
week = date.strftime('%a')
if week == 'Sun':
week_str = '日'
elif week == 'Mon':
week_str = '月'
elif week == 'Tue':
week_str = '火'
elif week == 'Wed':
week_str = '水'
elif week == 'Tue':
week_str = '木'
elif week == 'Fri':
week_str = '金'
elif week == 'Sat':
week_str = '土'
# 開催日をMM月YY日(Z)に変換 ------------------------------- (※3)
date_str_mod = month_str + '月' + day_str + '日(' + week_str + ')'
日付タブをクリック(※4)
日付タブをクリックするためには、クリックする場所を特定する必要があります。
再び↓の動画の方法でHTMLを確認すると、

ことが分かります。
そこで本処理では、先ほど作成した文字列「MM月YY日(Z)」と一致するテキストを含む要素を
find_elements_by_patial_link_text(text)
で取得し、該当箇所をクリックします。
- ①文字列「MM月YY日(Z)」を含む要素を取得
- ②「title属性」を取得し「MM月YY日(Z)」と合致する場合は、該当箇所が表示されるようにスクロールする
- ③開催日をMM月YY日(Z)に変換
# 日付タブをクリック ---------------------------------------- (※4)
text_list = browser.find_elements_by_partial_link_text(date_str_mod)
for text in text_list:
title = text.get_attribute('title')
if title == date_str_mod:
print('日付 : ', date_str_mod)
# 要素を表示するようスクロール
browser.execute_script("arguments[0].scrollIntoView(true);", text)
text.click()
break
レース結果ページのURLを取得(※5)
レース結果ページのURLを取得するには、再びHTMLを確認してURLが記述されている場所を特定する必要があります。
またまた、↓の動画でHTMLを確認すると

ということが分かります。
上記の情報を基にして、レース結果ページのURL一覧を取得します。
- ①<dd>タグの「class属性」が「RaceList_Data」の要素を取得
- ②上記の要素の中で、<a>タグの「href属性」を取得
- ③取得したURLに文字列「race/result」を含む場合、変数「url_list」に追加
# レース結果ページのURLを取得 --------------------------- (※5)
class_list = browser.find_elements_by_css_selector('dd.RaceList_Data')
url_list = []
for element in class_list:
a_tag_list = element.find_elements_by_tag_name('a')
for a_tag in a_tag_list:
try:
url = a_tag.get_attribute('href')
if 'race/result' in url:
url_list.append(url)
except Exception:
continue
「前」ボタンをクリックする(※6)

画面に表示されているレースのレース結果URLを取得した後は、「前」ボタンをクリックして再度レース結果URLを取得します。
- ①「前」ボタンの場所までスクロール
- ②「前」ボタンをクリック
- ③1秒時間停止
# 画面に表示されているURLを取得後、 「前」ボタンをクリックする ---------------------- (※6)
text = browser.find_element_by_partial_link_text('前')
browser.execute_script('arguments[0].scrollIntoView(true);', text)
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'Active')))
text.click()
time.sleep(1)
参考図書
本記事の内容は、以下の図書を参考にしています。
本書は、下記のようにスクレイピングについてとても詳しく解説されています。

本書の内容は「ブラウザーを経由したスクレイピング」を参考にしているよ!
本書は、上記の他にも
等も内容に含まれています。
Python初心者にも理解しやすい内容になっているので、ぜひ参考にしてください。
次回の内容
次回は、今回取得したURL一覧を用いて、レースデータ(レース情報・レース結果)を取得します。
ぜひご覧になってください!

コメント