BeautifulSoupを用いて競馬データをスクレイピングする方法


目的

機械学習で競馬予想して回収率100%を目指す。

今回やること

前回の記事で、netkeiba.comから2019年の全レース結果のデータをスクレイピングした。

今回はこれに加えて、レースの日付の情報や馬場の状態などのデータをスクレイピングしたい。

ソースコード

前回同様、race_idのリストを入れたらそれぞれのレースについてスクレイピング結果を辞書型で返してくれる関数を作る。

import requests
from bs4 import BeautifulSoup
import time
from tqdm.notebook import tqdm
import re

def scrape_race_info(race_id_list):
    race_infos = {}
    for race_id in tqdm(race_id_list):
        try:
            url = "https://db.netkeiba.com/race/" + race_id
            html = requests.get(url)
            html.encoding = "EUC-JP"
            soup = BeautifulSoup(html.text, "html.parser")

            texts = (
                soup.find("div", attrs={"class": "data_intro"}).find_all("p")[0].text
                + soup.find("div", attrs={"class": "data_intro"}).find_all("p")[1].text
            )
            info = re.findall(r'\w+', texts) #Qiitaでバックスラッシュを打つとバグるので大文字にしてあります。
            info_dict = {}
            for text in info:
                if text in ["芝", "ダート"]:
                    info_dict["race_type"] = text
                if "障" in text:
                    info_dict["race_type"] = "障害"
                if "m" in text:
                    info_dict["course_len"] = int(re.findall(r"\d+", text)[0]) #ここも同様に大文字にしてます。
                if text in ["良", "稍重", "重", "不良"]:
                    info_dict["ground_state"] = text
                if text in ["曇", "晴", "雨", "小雨", "小雪", "雪"]:
                    info_dict["weather"] = text
                if "年" in text:
                    info_dict["date"] = text
            race_infos[race_id] = pd.DataFrame(info_dict)
            time.sleep(1)
        except IndexError:
            continue
        except Exception as e:
            print(e)
            break
    return race_infos

前回スクレイピングしたデータからrace_id_listを作り、前回同様にDataFrame型にして元々のデータにmergeする。

race_id_list = results.index.unique()
race_infos = scrape_race_info(race_id_list)
for key in race_infos:
    race_infos[key].index = [key] * len(race_infos[key])
race_infos = pd.concat([pd.DataFrame(race_infos[key], index=[key]) for key in race_infos])
results = results.merge(race_infos, left_index=True, right_index=True, how='left')

完成したデータはこんな感じ。

動画で詳しい解説をしています!
競馬予想で始めるデータ分析・機械学習