スクレイピング後のデータ保存、データ処理の効率を行うためにデータベースに保存することにしようと思います。
今回はデータベースのDDLとpythonスクリプトの作成、そして実際にデータベースを立ち上げて保存するまでを行います。
内容的には以下の記事の続きです。
保存するデータ
- レースID
- レース情報
- レース結果
- レースの払い戻しデータ
生データとしていったん文字列のままで入れてしまいます
データ構造
一旦こんな感じにします。不都合があれば後で変える
テーブル定義
下記sqlの通り
運用方法
複数回同じページへのリクエストが発生してしまうのを防ぐため、以下のような3段階にします。
- レースIDテーブルにレースIDをポンポン入れていく
- レースIDテーブルから未処理のレースIDを取得し、一個一個スクレイピングしDB保存。
- DB保存まで終わったらスクレイピング済フラグを立てる
ソースコード
全部乗せると多いので以下のリポジトリに現状のコードをアップロードしました。少しだれたのでエラー制御とか甘いですが、許してください...
結果
レースIDテーブル
処理済みのレコードだけscraped_atが登録されます。
mysql> select * from raw_races limit 100,10; +-----+------------------+---------------+---------------+ | id | netkeiba_race_id | scraped_at | created_at | +-----+------------------+---------------+---------------+ | 115 | 202404030101 | 1724596983971 | 1724580995896 | | 116 | 202407020305 | 1724596985399 | 1724580995897 | | 117 | 202407020102 | 1724596986607 | 1724580995898 | | 118 | 202404020407 | 1724596987931 | 1724580995898 | | 119 | 202407020402 | NULL | 1724580995899 | | 120 | 202404030312 | NULL | 1724580995900 | | 121 | 202401020111 | NULL | 1724580995901 | | 122 | 202407020412 | NULL | 1724580995902 | | 123 | 202401020406 | NULL | 1724580995903 | | 124 | 202407020209 | NULL | 1724580995903 | +-----+------------------+---------------+---------------+
レース情報テーブル
mysql> select * from raw_race_informations LIMIT 10; +----+-------------+-------------+-----------------+--------------+--------------------+----------------+------------------+-------------------+-------------------------+--------------------------+ | id | raw_race_id | race_number | race_condition | weather | track_condition | starting_time | race_date | event_name | race_class | race_type | +----+-------------+-------------+-----------------+--------------+--------------------+----------------+------------------+-------------------+-------------------------+--------------------------+ | 1 | 15 | 8R | 芝左2200m | 天候 : 晴 | 芝 : 良 | 発走 : 16:20 | 2024年8月4日 | 2回新潟4日目 | 3歳以上1勝クラス | (混)(特指)(定量) | | 2 | 16 | 12R | 芝左1200m | 天候 : 晴 | 芝 : 良 | 発走 : 16:15 | 2024年8月11日 | 2回中京2日目 | 3歳以上2勝クラス | (混)[指](定量) | | 3 | 17 | 3R | 芝右1200m | 天候 : 曇 | 芝 : 良 | 発走 : 10:55 | 2024年8月17日 | 2回札幌3日目 | 3歳未勝利 | (混)[指](馬齢) | | 4 | 18 | 8R | 芝右2600m | 天候 : 晴 | 芝 : 良 | 発走 : 13:45 | 2024年8月10日 | 2回札幌1日目 | 3歳以上1勝クラス | (特指)(定量) | | 5 | 19 | 10R | ダ右1700m | 天候 : 曇 | ダート : 良 | 発走 : 15:01 | 2024年8月3日 | 1回札幌5日目 | 3歳以上2勝クラス | (混)[指](ハンデ) | | 6 | 20 | 7R | ダ右1000m | 天候 : 晴 | ダート : 良 | 発走 : 13:15 | 2024年8月3日 | 1回札幌5日目 | 3歳以上1勝クラス | (混)[指](定量) | | 7 | 21 | 11R | 芝左 外1600m | 天候 : 晴 | 芝 : 良 | 発走 : 15:45 | 2024年8月11日 | 3回新潟2日目 | 3歳以上オープン | (国際)(特指)(別定) | | 8 | 22 | 11R | ダ右1700m | 天候 : 曇 | ダート : 稍重 | 発走 : 15:35 | 2024年8月4日 | 1回札幌6日目 | 3歳以上オープン | (国際)(指)(別定) | | 9 | 23 | 2R | ダ右1700m | 天候 : 曇 | ダート : 良 | 発走 : 10:25 | 2024年8月17日 | 2回札幌3日目 | 2歳未勝利 | [指](馬齢) | | 10 | 24 | 2R | ダ右1700m | 天候 : 曇 | ダート : 良 | 発走 : 10:20 | 2024年8月3日 | 1回札幌5日目 | 3歳未勝利 | [指](馬齢) | +----+-------------+-------------+-----------------+--------------+--------------------+----------------+------------------+-------------------+-------------------------+--------------------------+
レース結果テーブル
人名とかのため載せません
レース払い戻しテーブル
mysql> select * from raw_race_payouts LIMIT 10; +----+-------------+-------------+---------------------+-------------+----------+ | id | raw_race_id | payout_type | horse_number | payout | favorite | +----+-------------+-------------+---------------------+-------------+----------+ | 1 | 15 | 単勝 | 4 | 170 | 1 | | 2 | 15 | 複勝 | 4;3;12 | 110;160;130 | 1;3;2 | | 3 | 15 | 枠連 | 3 - 3 | 490 | 2 | | 4 | 15 | 馬連 | 3 - 4 | 480 | 2 | | 5 | 15 | ワイド | 3 - 4;4 - 12;3 - 12 | 220;170;490 | 2;1;7 | | 6 | 15 | 馬単 | 4 → 3 | 650 | 2 | | 7 | 15 | 三連複 | 3 - 4 - 12 | 670 | 1 | | 8 | 15 | 三連単 | 4 → 3 → 12 | 2,530 | 3 | | 9 | 16 | 単勝 | 2 | 440 | 2 | | 10 | 16 | 複勝 | 2;1;9 | 150;180;140 | 2;4;1 | +----+-------------+-------------+---------------------+-------------+----------+
最後に
今回はスクレイピングしてきた生データをデータベースに保存するところまで作業してみました。
TODO
- レース結果に紐づくウマデータ、騎手データのスクレイピング
- データベースに保存した生データに前処理を加えて学習しやすい形に成形する