傾向とデータ

#2 netkeibaのスクレイピングに挑んでみた

前回のポストは過去のレース結果を取得に関するものでした。
今回は、当週のレース情報を取得するコードです。既に取得済のレース結果を(レースIDをキーに)スクレイピングしないようにしているので、前回のコードを実行してから本スクリプトを実行した方が効率がいいです。というか、当週以外のレースまで取得してしまいます。
本スクリプト(参考に改変したコードを含む)を実行した事物が何らかの不利益を被った場合、当方は一切の責任を負いませんので予めご了承下さい。

環境_ macOS, Python(3.9.0), SQLite

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import re
import sqlite3
import json
from bikou import bikou
import math
import datetime
import traceback
import sys


def numStr(num):
    if num >= 10:
        return str(num)
    else:
        return '0' + str(num)


# 開催年
for year in range(2021, 2022):
    #     # レース場コード
    for placeCode in range(1, 11):
        #         # 開催
        for kaisai in range(1, 11):
            #             # 日目
            for nitime in range(1, 13):  # 念のため毎年13-15日のレンジがないか回すこと
                # レース番号
                for raceNum in range(1, 13):
                    raceId = str(year) + numStr(placeCode) + \
                        numStr(kaisai) + numStr(nitime) + \
                        numStr(raceNum)

                    # レース情報テーブル(過去のレース結果)のレースIDがある場合は取得しない
                    # sqlite3に接続
                    con = sqlite3.connect('horse.db')
                    cur = con.cursor()

                    raceIdTmp = raceId
                    sql1 = 'SELECT raceId FROM race_infos where raceId = ' + raceIdTmp
                    cur.execute(sql1)

                    query_results = cur.fetchone()

                    if query_results is None:
                        Base = 'https://race.netkeiba.com/race/shutuba.html?race_id='  # 出走表ページのベースURL
                        url = Base + raceId  # 出走表ページのURL
                        # time.sleep(1)  # 1秒間隔でスクレイピング
                        html = requests.get(url)
                        soup = BeautifulSoup(html.content, 'html.parser')
                        # レース名取得
                        raceName = soup.find(class_="RaceName")

                        if raceName is None:  # レース結果テーブル取得した出来なかった場合break
                            break
                        else:
                            raceName = raceName.text.strip()
                            print(raceName)

                            # 開催日取得
                            try:
                                raceDateStr = soup.find(
                                    class_="Refundlink").a.get('href')
                                raceDate = re.search(
                                    r'\d+', raceDateStr).group()
                                raceDateYear = raceDate[0:4]
                                raceDateMonth = raceDate[4:6]
                                raceDateDay = raceDate[6:]
                                raceDateStr = raceDateYear + '-' + raceDateMonth + '-' + raceDateDay
                            except AttributeError:
                                pass

                            print(raceDateStr)

                            # レース情報(芝・ダート・障害・距離)取得
                            raceData = soup.find(
                                class_="RaceData01")  # 芝・ダート・障害/距離取得
                            baba_distance = raceData.span.text.strip()
                            # 芝・ダート・障害 取得
                            baba = baba_distance[0]
                            # 距離取得
                            distance = baba_distance.replace(
                                baba, '').replace('m', '')
                            print(distance)
                            print(baba)

                            # 天気取得
                            weather = raceData.text[raceData.text.find(
                                '天候:')+3:raceData.text.find('天候:')+4]
                            print(weather)

                            # レースグレード取得
                            raceData = soup.find(class_="RaceData02")
                            raceDataList = raceData.text.splitlines()
                            place = raceDataList[2]  # レース場
                            grade = raceDataList[5]  # レースグレード
                            kinryoCondition = raceDataList[8]  # 斤量条件

                            print(place)
                            print(grade)
                            print(kinryoCondition)

                            # 馬場状態取得
                            if soup.find(class_="Item04"):
                                babaCondition = soup.find(
                                    class_="Item04").text[5:]
                            elif soup.find(class_="Item03"):
                                babaCondition = soup.find(
                                    class_="Item03").text[5:]
                            else:
                                pass

                            print(babaCondition)

                            # 馬情報取得
                            horse_element = soup.select("span.HorseName")

                            # tagリストを文字列リストに変換
                            horse_list_str = []
                            for x in horse_element:
                                horse_list_str.append(str(x))

                            # 馬IDリストを作成
                            horseIdList = []  # 馬IDリスト
                            for horse_list in horse_list_str:
                                horseIdList.append(
                                    re.sub(r"\D", "", horse_list))

                            del horseIdList[0]

                            horseIdList = [int(horseId[0:10])
                                           for horseId in horseIdList]
                            print(horseIdList)

                            # 騎手情報取得
                            jockey_element = soup.select("td.Jockey")
                            # tagリストを文字列リストに変換
                            jockey_list_str = []
                            for x in jockey_element:
                                jockey_list_str.append(str(x))

                            jockeyIdList = []  # 騎手IDリスト
                            for jockey_list in jockey_list_str:
                                jockeyIdList.append(
                                    re.sub(r"\D", "", jockey_list))

                            # jockey_elementで無駄にジョッキーIDを取得してくる可能性あるので正確なジョッキー数分にスライス
                            jockeyIdList = jockeyIdList[0: len(
                                horseIdList)]

                            print(jockeyIdList)

                            # レース結果テーブル取得
                            df_raceResult = pd.read_html(url, header=0)

                            # カラム名を物理名に変更
                            df_raceResult[0] = df_raceResult[0].rename(columns={'枠': 'Waku', '馬番': 'Num', '馬名': 'Horse_Name', '性齢': 'Age', '斤量': 'Kinryo',
                                                                                '騎手': 'Jockey', '厩舎': 'Kyusya', '馬体重(増減)': 'Weight'})

                            # ジョッキー名の前に付いている記号を削除
                            jockeyList = []
                            for jockey in df_raceResult[0]['Jockey']:
                                if '▲' in jockey:
                                    jockeyList.append(jockey[1:])
                                elif '△' in jockey:
                                    jockeyList.append(jockey[1:])
                                elif '☆' in jockey:
                                    jockeyList.append(jockey[1:])
                                elif '★' in jockey:
                                    jockeyList.append(jockey[1:])
                                elif '◇' in jockey:
                                    jockeyList.append(jockey[1:])
                                else:
                                    jockeyList.append(jockey)

                            del jockeyList[0]

                            # 性別・年齢分割
                            sexList = [sex[0:1]
                                       for sex in df_raceResult[0]['Age'].values]
                            ageList = [age[1:]
                                       for age in df_raceResult[0]['Age'].values]

                            # 馬体重・増減分割
                            weightList = [str(weight)[:str(weight).find('(')]
                                          for weight in df_raceResult[0]['Weight']]
                            weightChageList = [str(weight)[str(weight).find('(') + 1: str(weight).find(')')]
                                               for weight in df_raceResult[0]['Weight']]

                            print(weightList)
                            print(weightChageList)

                            df_raceResult[0] = df_raceResult[0].drop(
                                'Age', axis=1)

                            df_raceResult[0] = df_raceResult[0].drop(
                                '印', axis=1)

                            df_raceResult[0] = df_raceResult[0].drop(
                                '人気', axis=1)

                            df_raceResult[0] = df_raceResult[0].drop(
                                'Unnamed: 9', axis=1)

                            df_raceResult[0] = df_raceResult[0].drop(
                                'お気に入り馬.1', axis=1)

                            df_raceResult[0] = df_raceResult[0].drop(
                                'お気に入り馬', axis=1)

                            df_raceResult[0] = df_raceResult[0].drop([0])

                            del weightList[0]
                            del weightChageList[0]
                            del sexList[0]
                            del ageList[0]

                            df_raceResult[0]['Jockey'] = jockeyList
                            df_raceResult[0]['Weight'] = weightList
                            df_raceResult[0]['WeightChange'] = weightChageList
                            df_raceResult[0]['sex'] = sexList  # 性別
                            df_raceResult[0]['age'] = ageList  # 年齢
                            df_raceResult[0]['raceId'] = [
                                int(raceId)] * len(df_raceResult[0])  # レース番号を付加
                            # 馬IDを付加
                            df_raceResult[0]['horseID'] = horseIdList
                            # 騎手IDを付加
                            df_raceResult[0]['jockeyID'] = jockeyIdList
                            df_raceResult[0]['raceName'] = [raceName] * \
                                len(df_raceResult[0])  # レース名を付加
                            df_raceResult[0]['baba'] = [baba] * \
                                len(df_raceResult[0])  # 馬場を付加
                            df_raceResult[0]['distance'] = [distance] * \
                                len(df_raceResult[0])  # 距離を付加
                            df_raceResult[0]['babacondition'] = [
                                babaCondition] * len(df_raceResult[0])  # 馬場状態を付加
                            df_raceResult[0]['place'] = [place] * \
                                len(df_raceResult[0])  # レース場所を付加
                            df_raceResult[0]['grade'] = [grade] * \
                                len(df_raceResult[0])  # グレードを付加
                            df_raceResult[0]['kinryoCondition'] = [
                                kinryoCondition] * len(df_raceResult[0])  # 斤量条件を付加
                            df_raceResult[0]['raceDate'] = [raceDateStr] * \
                                len(df_raceResult[0])  # 開催日を付加
                            df_raceResult.append

                            print(df_raceResult[0])

                            # レース情報フレーム作成
                            df_raceInfo = pd.DataFrame([[raceId, raceName, raceDateStr, weather, place, baba, grade, distance, babaCondition, kinryoCondition]], columns=[
                                'raceId', 'raceName', 'raceDate', 'weather', 'place', 'baba', 'grade', 'distance', 'babaCondition', 'kinryoCondition'])

                            # sqlite3に接続
                            con = sqlite3.connect('horse.db')
                            cur = con.cursor()

                            # レース最新情報挿入
                            try:  # raceIDの衝突が起きたとき例外発生
                                # レース結果情報挿入
                                df_raceResult[0].to_sql('shutuba', con,
                                                        if_exists='append', index=None)

                            except sqlite3.IntegrityError:
                                pass

                            try:
                                # レース情報挿入
                                df_raceInfo.to_sql('shutuba_infos', con,
                                                   if_exists='append', index=None)
                            except sqlite3.IntegrityError:
                                pass

                            con.commit()
                            con.close()
この画像を押すとブログランキングに飛びます!そこの本ブログの紹介欄で印を回した馬が確認出来るのでポチッとお願いします!↓↓↓
中央競馬ランキング
↑↑↑

-傾向とデータ
-