Yahoo競馬から有馬記念の競走成績を、PHP+XPathでスクレイピングしてみた
競馬は、情報量多すぎ!どう考えてもデータベースに入れておいた方が楽だ。
スクレイピングはpathonが多いので、phpで書いてみた。
しかしHTMLソースが汚い…。大昔に作ったまんまだからしょうがないのか?
というかAPIくれ~。
とりあえず、有馬記念の払い戻し金と競走成績だけ取得してみた。
レース・馬・騎手・調教師あたりのテーブルを作って、MySQLに入れるか~。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
<?php // Yahoo競馬からデータ取得 $ch = curl_init(); curl_setopt_array($ch, [ // 2018年の有馬記念 CURLOPT_URL => "https://keiba.yahoo.co.jp/race/result/1806050811/", CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_AUTOREFERER => true, CURLOPT_USERAGENT => 'Mozilla/5.0', CURLOPT_ENCODING => 'gzip', CURLOPT_SSL_VERIFYPEER => false, ]); $html = curl_exec($ch); // エラーを出さずにDOMDocumentに読み込む $dom = new DOMDocument; @$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); // DOMDocumentからXPath式を実行するためのDOMXPathを生成 $xpath = new DOMXPath($dom); // 払い戻し金のテーブルを取得 foreach ($xpath->query('//table[contains(@class, "resultYen")]') as $resultYen) { //そのレースの着順で並んでいるので、1位~最大16位までの馬情報を取得。 foreach ($xpath->query('.//tr', $resultYen) as $td) { // rowspan対策。払い戻し種別が空欄なら、前の種別を使う if(!empty($xpath->evaluate('string(.//th)', $td))){ $kind = $xpath->evaluate('string(.//th)', $td); } echo "種別:".$kind ."<br>\n"; echo "当たり:".$xpath->evaluate('string(.//td[1])', $td) ."<br>\n"; echo "配当:".$xpath->evaluate('string(.//td[2])', $td) ."<br>\n"; echo "人気:".$xpath->evaluate('string(.//td[3])', $td) ."<br>\n"; echo "<br>\n"; } } // レース結果のテーブルを取得 foreach ($xpath->query('//table[contains(@id, "raceScore")]/tbody') as $tr) { //そのレースの着順で並んでいるので、1位~最大16位までの馬情報を取得。 foreach ($xpath->query('.//tr', $tr) as $td) { echo "着順:".$xpath->evaluate('string(.//td[1])', $td) ."<br>\n"; //着順 echo "枠番:".$xpath->evaluate('string(.//td[2])', $td) ."<br>\n"; //枠番 echo "馬番:".$xpath->evaluate('string(.//td[3])', $td) ."<br>\n"; //馬番 //馬名/性齢⁄馬体重⁄B $data = preg_split("/[\/\n]+/", $xpath->evaluate('string(.//td[4])', $td)); echo "名前:". $data[1] ."<br>\n"; //馬情報へのリンク echo "馬URL:" . $xpath->evaluate('string(.//td[4]/a/@href)', $td) ."<br>\n"; preg_match('/(牡|牝)/', $data[3], $match); echo "性別:". $match[1] ."<br>\n"; preg_match('/([0-9]+)/', $data[3], $match); echo "年齢:". $match[1] ."<br>\n"; preg_match('/^(.+)\(/', $data[4], $match); echo "体重:". $match[1] ."<br>\n"; preg_match('/\((.+)\)/', $data[4], $match); echo "増減:". $match[1] ."<br>\n"; // タイム $data = preg_split("/ /", $xpath->evaluate('string(.//td[5])', $td)); echo "タイム:". $data[0]."<br>\n"; echo "着差:". $data[1]."<br>\n"; echo "通過順位:". $xpath->evaluate("string(.//td[6]/text())", $td) ."<br>\n"; echo "上3Fタイム:". $xpath->evaluate("string(.//td[6]/*[contains(@class,'scdItem')])", $td) ."<br>\n"; // 騎手 $data = preg_split("/[\n]+/", $xpath->evaluate('string(.//td[7])', $td)); echo "騎手の名前:". $data[1] ."<br>\n"; echo "騎手URL:". $xpath->evaluate('string(.//td[7]/a/@href)', $td) ."<br>\n"; // ジョッキー情報 echo "騎手の体重:". $data[2] ."<br>\n"; // 人気&単勝オッズ preg_match('/[0-9]+/', $xpath->evaluate('string(.//td[8])', $td), $match); echo "人気:". $match[0] ."<br>\n"; preg_match('/\((.+)\)/', $xpath->evaluate('string(.//td[8])', $td), $match); echo "単勝オッズ:". $match[1] ."<br>\n"; echo "調教師:".$xpath->evaluate('string(.//td[9])', $td) ."<br>\n"; echo "調教師URL:". $xpath->evaluate('string(.//td[9]/a/@href)', $td) ."<br>\n"; echo "<br>\n"; } } |