ボートレース競走結果 収集クローラ作成③ ~スクレイピング~

概要

ここでは、RubyのNokogiriを用いたボートレース競走結果のスクレイピングについて説明する。
クローラの全体、開発環境について:

Nokogiriのインストール

Nokogiriのインストールは、別途ブログを書いているので、そちらを参照してほしい。

スクレイピングで得るデータ

最初に、どのwebページからどの情報を持ってくるかとその実装に手をつけた。
競走データと言ってもボートレースには、様々な情報があるが今回は、レースの結果に関係する情報を集めた。 レースの結果ページから

  • 開催情報(場所、ラウンド、日時)
  • 進入コース
  • 着順
  • 選手の登録番号
  • レースタイム
  • スタートタイミング
  • 気象水面状況
  • 払い戻し金額

以上の情報を

結果|BOAT RACE オフィシャルウェブサイト

のようなページから取得することにした。

ソースコード説明

XPathCSSセレクタで、指定した情報を取り出すことができる。
XPathは、少し触ったことがあったので、そっちでやった。
adjust_data は、XPathとdoc(Nokogiri::HTML::Document)から 取得した情報をString配列にして返す関数。 後は、適切なXPathを使って、必要なデータを取得する。

#スペース、改行、タブ、全角を半角にして返す。スペース改行、複数タブ区切りで配列にする
def mtrim(text)
        text.gsub!(/\\n|\\r|\\t/," ")
        text.gsub!(/[[:space:]]/," ")
        text.tr!(" "," ")
        text.tr!('0-9a-zA-Z', '0-9a-zA-Z')
        text.gsub!(/\s+/,SEPALATER)
        text.gsub!(/^\t/,"")
        text.gsub!("\"","\'")
        text = text.split(SEPALATER)
        return text
end

#データを整える
def adjust_data(xpath,doc) 
  boat = doc.xpath(xpath)
  if boat.text != "" then
    boat.each do |boat|
      xpath = mtrim(boat.text)
    end
  else
    xpath = Array.new
  end
  return xpath
end

boat1 = adjust_data("//html/body/main/div/div/div/div[2]/div[4]/div[1]/div/table/tbody[1]",doc)

今回は、tbodyタグがいい感じにあったので、それを使った。

.
.
.
<tbody>
    <tr>
        <td class="is-fs14"></td>
        <td class="is-fs14 is-fBold is-boatColor5">5</td>
        <td class="is-p20-0">
            <span class="is-fs12">4237</span> 
            <span class="is-fs18 is-fBold">大峯   豊</span>
        </td>
        <td>1&#39;50&quot;9</td>
    </tr>
</tbody>

<tbody>
    <tr>
        <td class="is-fs14"></td>
        <td class="is-fs14 is-fBold is-boatColor4">4</td>
        <td class="is-p20-0">
            <span class="is-fs12">4150</span> 
            <span class="is-fs18 is-fBold">山田  雄太</span>
        </td>
        <td>1&#39;52&quot;1</td>
    </tr>
</tbody>

.
.
.

また開催情報(日付、場所、ラウンド)は、URLのクエリから取得した。

require 'uri'
#urlから場、ラウンド、日時を抜き出す。
query = get_url.query #URI::Generic#query
query.tr!('a-z',"")
query.tr!("=","")
query = query.split("&")

#ラウンド数の先頭に0(ex.02,12,09)
query[0] = format("%02d", query[0])

はじめは、rubyからshellのコマンドを呼び出し、その日の日付をえていたが、それでは、shell依存になってしまうので、Dateクラスを用いて、その日の日付を取得するように改良した。

#シェルver
=begin
#今
date = `date "+%Y%m%d"`
#適当に時間いじる
date = `env TZ=JST-30 date "+%Y%m%d"`
#puts mdate.class
mdate = date.to_i
puts mdate
=end

#ruby_ver
today = Date.today
date =  today.iso8601
date.tr!("-","")
mdate = date.to_i
puts date

Rubyコーディング規約について

 今回、開発をすすめるなかで、友人からRubyに目安となる標準のコーディング規約があることを初めて聞いた。
 コーディング規約は、実際のプロジェクトごとに決められそのプロジェクト内で守られる物と考えていた私には衝撃だった。
 今後は、その標準的なコーディング規約を意識して、コーディングしていきたいと思う。