Python プログラミング

netkeibaのレース結果から払い戻し情報を取得するサンプルプログラム,BeautifulSoup,正規表現

概要

競馬予想プログラムの一部。情報のスクレイピングの一部です。
レースの払い戻し情報。以下の部分の情報を取得してDataFrame化して返却します。


実は、このプログラムにはバグがあります。
同着を考慮していないのです。
競馬には同着があり得る。業務仕様、レア考慮漏れの良い例と思い反省もこめて
敢えてこの段階のソースを投稿しようと考えました。

サンプルソースコード

2023年のAJCCを取得している例です。
単独でnetkeibaログイン無しでも動作するようサンプルプログラムにしました。

#  netkeibaのレース結果から払い戻し情報を取得するサンプルプログラム,BeautifulSoup,正規表現
import requests
from bs4 import BeautifulSoup
import pandas as pd
import re


def get_race_refund(raceid_str: str, result_url: str) -> pd.DataFrame:
    #レース払い戻し情報の取得

    keibasession = requests.session()
    html = keibasession.get(result_url)
    html.encoding = "EUC-JP"
    soup = BeautifulSoup(html.text, "html.parser")

    #払い戻し結果を取得
    tables = soup.find_all('table', attrs={"class": "Payout_Detail_Table"})

    for tbl in tables:
        #2つのテーブルに分割取得されるので、順次取得
        rows = tbl.find_all('tr')
        #リストに展開(リスト内包表記)
        data = [[col.text.replace('\n', '') for col in row.findAll(
            ['td', 'th'])] for row in rows]

        #枠連は無い場合があるから、初期設定する。
        frame_win = 0
        #枠連が2頭しか無いバターンがあるから、初期設定する。(2頭の場合、諦める)
        multiple_wins1 = 0
        multiple_wins2 = 0
        multiple_wins3 = 0

        for refundkind in data:
            if refundkind[0] == "単勝":
                win = int(str(refundkind[2]).replace('円', '').replace(',', ''))
            elif refundkind[0] == "複勝":
                pattern = r'([,\d]+)円([,\d]+)円([,[\d]+)円.*'
                result = re.match(pattern, refundkind[2])
                if result:  # none以外の場合
                    # group()で全文字を
                    multiple_wins1 = int(result.group(1).replace(',', ''))
                    multiple_wins2 = int(result.group(2).replace(',', ''))
                    multiple_wins3 = int(result.group(3).replace(',', ''))
            elif refundkind[0] == "枠連":
                frame_win = int(str(refundkind[2]).replace('円', '').replace(',', ''))
            elif refundkind[0] == "馬連":
                horse_win = int(str(refundkind[2]).replace('円', '').replace(',', ''))
            elif refundkind[0] == "ワイド":
                pattern = r'([,\d]+)円([,\d]+)円([,[\d]+)円.*'
                result = re.match(pattern, refundkind[2])
                if result:  # none以外の場合
                    # group()で全文字を
                    wide_win1 = int(result.group(1).replace(',', ''))
                    wide_win2 = int(result.group(2).replace(',', ''))
                    wide_win3 = int(result.group(3).replace(',', ''))
            elif refundkind[0] == "馬単":
                horse_single = int(str(refundkind[2]).replace('円', '').replace(',', ''))
            elif refundkind[0] == "3連複":
                triple_muliti = int(str(refundkind[2]).replace('円', '').replace(',', ''))
            elif refundkind[0] == "3連単":
                triple_single = int(str(refundkind[2]).replace('円', '').replace(',', ''))


    #refundと同じ列名のDataFremeの作成と返却
    ret_refund_ds = pd.DataFrame({
            'race_id': [raceid_str],
            'win': [win],
            'multiple_wins1': [multiple_wins1],
            'multiple_wins2': [multiple_wins2],
            'multiple_wins3': [multiple_wins3],
            'frame_win': [frame_win],
            'horse_win': [horse_win],
            'wide_win1': [wide_win1],
            'wide_win2': [wide_win2],
            'wide_win3': [wide_win3],
            'horse_single': [horse_single],
            'triple_muliti': [triple_muliti],
            'triple_single': [triple_single]
                    })

    return ret_refund_ds


if __name__ == '__main__':
    race_id_str = "202306010811"
    url = "https://race.netkeiba.com/race/result.html?race_id=202306010811"
    # 払戻情報の取得
    refund_ds = get_race_refund(race_id_str, url)

    print(refund_ds)

-Python, プログラミング
-, ,