競馬成績表データベースを作る(データ取得編)
1.概要
競馬成績表データベースを作るの第二弾は、競馬成績表データの一括自動取得を行います。事前準備編で取得済みの
各レース毎のレース成績表リンクリストを使います。そのリストのリンクを順次読み込み、サイトを自動巡回して
成績表データを取得します。取得できるデータ項目は、日付、コード、R番号、競馬場、開催、発走時間、天気、馬場、レース名、コース、距離、単勝、枠連、馬連、馬単、3連単、1着、2着、3着、頭数の
計20項目となります。プログラムは、Excel VBAで作成します。
2.データの取得手順 成績表データ取得手順は、次の手順で行います。 (1)Yahoo競馬レース結果取得.xlsmを起動します。(ダウンロードは、本連載記事の最終回で提供)
(2)成績表データ取得ボタンをクリックします。
(3)ファイル選択ダイアログが開くので、事前取得済みのレース成績表リンクリストを選択します。
(4)データ取得が開始されますので完了するまで待ちます。
(5)レース成績表リンクリストは分割して準備されていると思うので、続いて取得の場合は、
手順(2)から繰り返し実行します。
データベース作成時は、分割取得されたデータを全てマージして利用します。 コード体系は、以下のような体系で構成されています。データ取得時は、このコード番号が キーとしてURLのパラメータとなります。
今回の記事で紹介してるプログラムは、本シリーズの連載最後にまとめてダウンロード提供する予定としています。 少しずつ記事をアップしていきますので、しばらくお付き合いください。
■関連記事
・Excelでデータベース(SQLite3)を扱う
・複数のファイルをマージする
・競馬成績表データベースを作る(事前準備編)
・競馬成績表データベースを作る(データベース編)
・競馬成績表データベースを作る(ツール-Excel編)
・競馬成績表データベースを作る(ツール-HSP編)
2.データの取得手順 成績表データ取得手順は、次の手順で行います。 (1)Yahoo競馬レース結果取得.xlsmを起動します。(ダウンロードは、本連載記事の最終回で提供)
(2)成績表データ取得ボタンをクリックします。
(3)ファイル選択ダイアログが開くので、事前取得済みのレース成績表リンクリストを選択します。
(4)データ取得が開始されますので完了するまで待ちます。
(5)レース成績表リンクリストは分割して準備されていると思うので、続いて取得の場合は、
手順(2)から繰り返し実行します。
データベース作成時は、分割取得されたデータを全てマージして利用します。 コード体系は、以下のような体系で構成されています。データ取得時は、このコード番号が キーとしてURLのパラメータとなります。
-
(例)2002020806
https://keiba.yahoo.co.jp/race/result/2005020806/
20 ⇒ 西暦年 YY
05 ⇒ 競馬場コード (東京)
02 ⇒ 開催回 (02回)
08 ⇒ 開催日目(08日目)
06 ⇒ レース番号 (06R)
●パラメータ
yy : 開催年
xx : 競馬場コード
yy : 開催回[第N回]
zz : 開催日目[N日目]
rr : レース番号
●競馬場コード
01 : 札幌競馬場
02 : 函館競馬場
03 : 福島競馬場
04 : 新潟競馬場
05 : 東京競馬場
06 : 中山競馬場
07 : 中京競馬場
08 : 京都競馬場
09 : 阪神競馬場
10 : 小倉競馬場
'**** 処理開始 **** Private Sub IENavi_Click() Call GetOpenFilename End Sub '***** 成績表データ消去 ***** Private Sub NaviDel_Click() If Sheets("成績表").Range("B6") <> "" Then Range("B6:U6000").SpecialCells(xlConstants, 23).ClearContents End If End Sub標準モジュール(Seiseki)に、リンクリストを元に順次サイトを巡回させて、 成績表データを取得してシート上に書き出します。ソースコードは冗長ですが、天気や馬場状態が画像ファイルで表示させているため、 テキストデータとして取得するので、画像ファイルのクラス名より翻訳処理をしています。 レース結果の払い戻し番号取得する部分では、複勝の位置が変動するので、枠番の位置から馬番を求めるように処理しています。 頭数がデータとして取得できないので、競走成績一覧の表からカウントして頭数を算出しています。 取得が完了したら、カレントディレクリに日付時刻形式のファイル名として、CSV形式で出力します。
'********************************************************************************* '* '* 競馬成績表データ一括取得処理 '* '* - IEによるインターネットサイト自動巡回 (Yahooスポーツ : 競馬) - '* https://keiba.yahoo.co.jp/race/result/ '* '* ●成績表の日程ファイルから取得した過去の成績表リンクファイルを利用 '* '* '********************************************************************************* '* ☆Yahoo!スポーツ競馬 URL コード体系 '********************************************************************************* '* '* ●出走表の場合 '* https://keiba.yahoo.co.jp/race/denma/1205020806/ '* '* ●成績表の場合 '* https://keiba.yahoo.co.jp/race/result/1205020806/ '* '* ●開催日程の場合 '* https://keiba.yahoo.co.jp/schedule/list/2012/?month=1 '* '* (例) '* 12 ⇒ 西暦年 YY '* 05 ⇒ 競馬場コード (東京) '* 02 ⇒ 開催回 (02回) '* 08 ⇒ 開催日目(08日目) '* 06 ⇒ レース番号 (06R) '* '* ●パラメータ '* yy : 開催年 '* xx : 競馬場コード '* yy : 開催回[第N回] '* zz : 開催日目[N日目] '* rr : レース番号 '* '* ●競馬場コード '* 01 : 札幌競馬場 '* 02 : 函館競馬場 '* 03 : 福島競馬場 '* 04 : 新潟競馬場 '* 05 : 東京競馬場 '* 06 : 中山競馬場 '* 07 : 中京競馬場 '* 08 : 京都競馬場 '* 09 : 阪神競馬場 '* 10 : 小倉競馬場 '* '* ●過去データ(成績表)の場合 '* 2000年1月29日(土) 10:00 1回東京1日 '* https://keiba.yahoo.co.jp/race/result/0005010101/ '* '********************************************************************************* '32bit版Excelの場合は、ptrsafe部分を削除して下さい。 ' sleep関数(API)の宣言 Public Declare ptrsafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) ' ShowWindow(API)の宣言 Public Declare ptrsafe Function ShowWindow Lib "user32" (ByVal hwindow As Long, ByVal cmdshow As Long) As Long Dim objIE As Object Dim obj As Object '***** 自動巡回リストファイル選択ダイアログ ***** Public Sub GetOpenFilename() Dim FileName As Variant Dim PathName As String Worksheets("成績表").Activate Sheets("成績表").Select Application.DefaultFilePath = ThisWorkbook.Path PathName = ThisWorkbook.Path & "¥result¥" ChDir PathName 'ファイルを開くダイアログ FileName = _ Application.GetOpenFilename( _ FileFilter:="テキストファイル(*.txt),*.txt" & _ ",CSVファイル(*.csv),*.csv" _ , FilterIndex:=1 _ , Title:="ファイルの選択" _ , MultiSelect:=False _ ) If FileName <> False Then If Sheets("成績表").Range("B6") <> "" Then Range("B6:U6000").SpecialCells(xlConstants, 23).ClearContents End If Call IE_open(FileName) End If End Sub '***** 競馬成績表(Yahooスポーツ : 競馬) サイト自動巡回処理 ***** Private Sub IE_open(ByVal FileName As String) Dim URL As String Dim Path As String Dim i As Integer Dim p As Integer Dim strText As String Dim strArray() As String Dim houseStr As String On Error Resume Next Worksheets("成績表").Activate Sheets("成績表").Select Set objIE = CreateObject("InternetExplorer.Application") objIE.Visible = False '***** 初期起動ページ表示 ***** URL = "https://keiba.yahoo.co.jp/" objIE.Navigate URL Do While objIE.ReadyState <> 4 Do While objIE.Busy = True DoEvents Loop Loop '***** ウィンドウ制御 (Max : 3, Min : 2) ***** ret = ShowWindow(objIE.Hwnd, 2) objIE.Visible = True '***** ファイル名を保存 ***** If FileName = "" Then MsgBox "リストファイルが選択されていません。" objIE.Quit Set objIE = Nothing Exit Sub End If '***** 選択されたファイルの有無を確認 ***** 'With CreateObject("Scripting.FileSystemObject") ' If FileExists(FileName) = False Then ' MsgBox "ファイルが存在しません。" ' objIE.Quit ' Set objIE = Nothing ' Exit Sub 'End With '***** ファイル名を退避 ***** Path = FileName '***** ファイルを開く ***** Open Path For Input As #1 '▼▼▼▼▼ ここから繰り返し処理の開始 ▼▼▼▼▼ p = 6 ' 行の開始位置 'Application.ScreenUpdating = False Do Until EOF(1) ' ファイルを1行読み込み Line Input #1, URL If URL = "" Then Exit Do If Mid(URL, 1, 5) <> "https" Then MsgBox "リストファイルにURLが含まれていません。" objIE.Quit Set objIE = Nothing Exit Sub End If ' 空行がある場合は処理を終了 If URL = "" Then Exit Do ' ナビゲート開始 objIE.Navigate URL ' ページが完全に表示されるまで待つ Do While objIE.ReadyState <> 4 Do While objIE.Busy = True DoEvents Loop Loop 'Sleep (100) Application.StatusBar = objIE.Document.Title '▼▼▼▼ データ取得処理 ▼▼▼▼ '***** レースコード ***** Cells(p, 3) = Replace(Right(URL, 11), "/", "") '***** レース番号を取得 (1R etc) ***** For Each obj In objIE.Document.getElementsByTagName("td") If obj.ID = "raceNo" Then strText = obj.innerText Cells(p, 4) = strText Exit For End If Next '***** 開催日、開催場所、発走時間を取得 ***** For Each obj In objIE.Document.getElementsByTagName("p") If obj.ID = "raceTitDay" Then houseStr = obj.innerText ' 取得内容を分解 strArray = Split(houseStr, "|") '● 開催日を編集 (yyyy/mm/dd 形式) strText = strArray(0) strText = Mid(strText, 1, InStr(strText, "(") - 1) strText = Replace(strText, "年", "/") strText = Replace(strText, "月", "/") strText = Replace(strText, "日", "") Cells(p, 2) = strText '● 開催場所を編集 (XX回中山XX日) strText = Trim(strArray(1)) Cells(p, 6) = strText '● 競馬場 strText = Mid(strText, InStr(strText, "回") + 1, 2) Cells(p, 5) = strText '● 発走時間 strText = Trim(strArray(2)) strText = Mid(strText, 1, InStr(strText, "発") - 1) Cells(p, 7) = strText Exit For End If Next '***** 天気 (画像ファイルのクラス名より判定) ***** For Each obj In objIE.Document.getElementsByTagName("img") Select Case obj.className Case "spBg hare" Cells(p, 8) = "晴" Exit For Case "spBg kumori" Cells(p, 8) = "曇" Exit For Case "spBg ame" Cells(p, 8) = "雨" Exit For Case "spBg yuki" Cells(p, 8) = "雪" Exit For Case "spBg koyuki" Cells(p, 8) = "小雪" Exit For Case "spBg kosame" Cells(p, 8) = "小雨" Exit For End Select Next '***** 馬場 (画像ファイルのクラス名より判定) ***** For Each obj In objIE.Document.getElementsByTagName("img") Select Case obj.className Case "spBg ryou" Cells(p, 9) = "良" Exit For Case "spBg yayaomo" Cells(p, 9) = "稍重" Exit For Case "spBg omo" Cells(p, 9) = "重" Exit For Case "spBg furyou" Cells(p, 9) = "不良" Exit For End Select Next '***** レース名 ***** For Each obj In objIE.Document.getElementsByTagName("h1") If obj.className = "fntB" Then strText = obj.innerText Cells(p, 10) = strText Exit For End If Next '***** コース、距離を取得 ***** For Each obj In objIE.Document.getElementsByTagName("p") If obj.ID = "raceTitMeta" Then houseStr = obj.innerText ' 取得内容を分解 strArray = Split(houseStr, "|") strText = Trim(strArray(0)) '● コース (芝、ダート) strText = Mid(strText, 1, InStr(strText, " ") - 1) Cells(p, 11) = strText '● 距離 strText = Trim(strArray(0)) strText = Mid(strText, InStr(strText, " ") + 1, 4) Cells(p, 12) = strText Exit For End If Next '***** レース結果の払い戻し番号取得 - 1 ***** ' ▼複勝の位置が変動するので、枠番の位置から馬番を求める i = 0 j = 0 For Each obj In objIE.Document.all Select Case obj.tagName Case "TR", "TD", "TH" If obj.offsetparent.className = "resultYen" Then Select Case obj.tagName Case "TR" Case "TD", "TH" '***** 単勝,枠連,馬連 ***** If obj.className = "txC resultNo" Then i = i + 1 '● 単勝 If i = 1 Then Cells(p, 13) = obj.innerText End If '● 枠連 If i > 2 And j = 0 And InStr(obj.innerText, "-") <> 0 Then Cells(p, 14) = Replace(obj.innerText, "-", "-") j = i j = j + 1 End If '● 馬連 If i = j And InStr(obj.innerText, "-") <> 0 Then Cells(p, 15) = Replace(obj.innerText, "-", "-") Exit For End If End If End Select End If End Select Next '***** レース結果の払い戻し番号取得 - 2 ***** i = 0 For Each obj In objIE.Document.all Select Case obj.tagName Case "TR", "TD", "TH" If obj.offsetparent.className = "resultYen noMgn" Then Select Case obj.tagName Case "TR" Case "TD", "TH" '***** 馬単,3連単 ***** If obj.className = "txC resultNo" Then i = i + 1 '● 馬単 If i = 4 Then houseStr = obj.innerText If houseStr <> "" Then Cells(p, 16) = Replace(houseStr, "-", "-") End If End If '● 3連単 If i = 6 Then houseStr = obj.innerText If houseStr <> "" Then Cells(p, 17) = Replace(houseStr, "-", "-") '*********************************************************** ' 3連単の結果から、1着,2着,3着の馬番を取得 ' 過去のレースではデータなしのため、別途取得とする ' 2004年 9月11日の開催レースから ' 第4回中山競馬・第4回阪神競馬・第2回札幌競馬初日 '*********************************************************** '***** 取得内容を分解 ***** strArray = Split(Cells(p, 17).Value, "-") Cells(p, 18) = Cells(p, 13).Value '●1着馬番号 Cells(p, 19) = strArray(1) '●2着馬番号 Cells(p, 20) = strArray(2) '●3着馬番号 End If Exit For End If End If End Select End If End Select Next '***** 頭数をカウントして求める ***** i = 0 ' ※ 頭数をカウントして算出 For Each obj In objIE.Document.all Select Case obj.tagName Case "TR", "TD", "TH" If obj.offsetparent.className = "dataLs mgnBS" Then Select Case obj.tagName Case "TR" ' 空ループ i = i + 1 Case "TD", "TH" End Select End If End Select Next '● 頭数 Cells(p, 21) = i - 1 '***** 行をインクリメント ***** p = p + 1 Loop '***** ファイルを閉じる ***** Close #1 objIE.Quit Set objIE = Nothing Set obj = Nothing '▼▼▼▼ ファイル名を作成 ファイル名は自分のパス+¥SyyyymmddHHMMSS.csvとして自動生成 ▼▼▼▼ Dim FNAME As String '***** ファイル名を合成 (年月日時分秒) ***** FNAME = "S" & Year(Date) & Right("0" & Month(Date), 2) & Right("0" & Day(Date), 2) & _ Right("0" & Hour(Time), 2) & Right("0" & Minute(Time), 2) & Right("0" & Second(Time), 2) & ".csv" Dim strFNAME As String ' ファイル名保存用 strFNAME = ThisWorkbook.Path & "¥" & FNAME '***** テーブルデータからCSV形式ファイルを出力する ***** Call MAKE_CSV_FILE(strFNAME, Range(Cells(6, 2), Cells(p - 1, 21))) Application.ScreenUpdating = True Application.StatusBar = False Sheets("成績表").IENavi.Enabled = True Sheets("成績表").NaviDel.Enabled = True MsgBox "データ取得処理が完了しました" Range("B6").Select End Sub '***** ファイルを開きカンマ区切りのファイルを作成する ***** Sub MAKE_CSV_FILE(strFNAME As String, objHANI As Range) '***** ファイルをオープンする ***** Dim FNO As Integer ' ファイル番号 FNO = FreeFile ' 空いてるファイル番号を取出す Open strFNAME For Output As #FNO ' テキストファイルを新規作成 '***** 行、列でループを作る ***** Dim Y As Integer Dim x As Integer For Y = 1 To objHANI.Rows.Count ' 行のループ Print #FNO, Trim(objHANI.Cells(Y, 1).Value); ' 先頭項目の出力 For x = 2 To objHANI.Columns.Count ' 列のループ Print #FNO, Trim(","); Print #FNO, Trim(objHANI.Cells(Y, x).Value); Next x Print #FNO, Trim("") ' 改行のみ出力 Next Y '***** ファイルクローズ ***** Close #FNO End Sub4.ダウンロード 提供するソースコードのライセンスは、CC0 (クレジット表示不要、改変可、商用可) とします。自由に利用して頂いてかまいません。
今回の記事で紹介してるプログラムは、本シリーズの連載最後にまとめてダウンロード提供する予定としています。 少しずつ記事をアップしていきますので、しばらくお付き合いください。
■関連記事
・Excelでデータベース(SQLite3)を扱う
・複数のファイルをマージする
・競馬成績表データベースを作る(事前準備編)
・競馬成績表データベースを作る(データベース編)
・競馬成績表データベースを作る(ツール-Excel編)
・競馬成績表データベースを作る(ツール-HSP編)
コメント
コメントを投稿