ローイングファン version1
今まで試してきたコードを使ってボートレース(レガッタ)の情報を検索するアプリをつくる。
前につくったお試し版に改良をくわえ、一通りの機能は備わったのでversion1とする。
目次
ローイングファンver1のコード
コードを実行すると案内が表示されます。
案内にしたがってURLとボートクラブ名を入力するとターミナル/PowerShellに結果が表示され、エクセルで使えるCSVファイルが作成されます。
コードの説明は今までの記事を読んでください。
rowingfan_ver1.rb
#------------------------------------- # コードを実行するとクローリングが実行されます。 # URL先の注意事項を読んでから使用してください。 # https://rowingfan.hatenablog.jp/entry/2018/03/11/125951 # 対応しているボートレース(レガッタ)は次の4大会です。 # 全日本選手権、全日本軽量級選手権、全日本大学選手権、全日本新人選手権 # 実行するとターミナル/PowerShellに結果が表示されます。 # 実行するとCSVファイルが作られます(encoding: Shift_JIS) #------------------------------------- require 'open-uri' puts "\n検索したい種目のURLを入力して下さい。" print "URL: " url_entered = gets.chomp!.encode("utf-8") sleep(0.5) if url_entered == "" puts "\n\n<!> URLが入力されていません" sleep(0.5) puts "入力しなおす: 1\n終了する: 2" print "番号(半角)を入力: " choice_reurl = gets.to_i if choice_reurl == 1 puts "\n検索したいレースのURLを入力して下さい。" print "URL: " url_entered = gets.chomp!.encode("utf-8") sleep(0.5) else exit end end #URLチェック if /\Ahttps:\/\/www.jara.or.jp\/.+\d\d\d\d.+.html\z/ =~ url_entered url = url_entered else print "\n\nレース情報が見つからないので終了します...\n\n" exit end #-----URLをクローリング----- #例外処理つき begin #open-uriで開くデータはバイト列なのでr:utf-8をつける html = open("#{url}","r:utf-8") htmlcode = html.read html.close sleep(1) rescue print "\n\nURLが見つからないので終了します...\n\n" exit end #-----年代、大会名、種目名をスクレイピング----- #大会名をタグ付きキャプチャで取得 /<h1 class=\"title\">第\d+回(?<tag_tourname>.+)大会<\/h1>/ =~ htmlcode #年代をタグ付きキャプチャで取得 /<a href=\"(?<tag_year>\d\d\d\d).+><i class=\"glyphicon glyphicon-file\"><\/i>/ =~ htmlcode #種目名をタグ付きキャプチャで取得 /<div class=\"panel-heading\">(?<tag_event>.+)の組合せと結果<\/div>\n/ =~ htmlcode # //---年代、大会名、種目名をスクレイピング--- if tag_tourname && tag_year && tag_event puts "\n\n次のレースから検索します >>" puts "==========" puts "#{tag_year} #{tag_tourname}" puts "#{tag_event}" puts "==========" sleep(0.5) else print "\n\nURLがみつかりませんでした。\n\n" exit end puts "\n検索したいボートクラブ名を入力して下さい。" puts "(AやBなどの符号は不要です)" print "クラブ名: " clubname = gets.chomp!.encode("utf-8") if clubname == "" puts "\n\n<!> クラブ名が入力されていません <!>" sleep(0.5) puts "入力しなおす: 1\n終了する: 2" print "番号(半角)を入力: " choice_reclubname = gets.to_i if choice_reclubname == 1 puts "\n検索したいボートクラブ名を入力して下さい。" print "クラブ名: " clubname = gets.chomp!.encode("utf-8") sleep(0.5) else exit end end sleep(0.5) puts "\n\n次のレース情報を検索します >>" sleep(0.5) puts "===============" puts "大会: #{tag_year} #{tag_tourname}" puts "種目: #{tag_event}" puts "団体: #{clubname}" puts "===============" print "\n\n" puts "よければ 1\n中止する場合は 2" print "番号(半角)を入力: " choice_serch = gets.to_i puts "\n" if choice_serch == 1 #---レース情報をスクレイピング--- #シングルスカル種目のクルー名にある余計なタブを削除 htmlcode.gsub!(/<br.?\/><small>/,'') htmlcode.gsub!(/<\/small>/,'') #レース記号をタグ付きキャプチャ /\Ahttps:\/\/www.+\/(?<tag_urlyear>\d\d\d\d)(?<tag_urltour>.+)_(?<tag_urlevent>.+).html\z/ =~ url #Race Noを取得 acquired_racenos = htmlcode.scan(/Race No:\s(?<tag_receno>\d+)<\/div>/) #発艇日時を取得 acquired_starttimes = htmlcode.scan(/発艇時刻:<\/b>\s(?<tag_start>\d+\/\d+\s\d+:\d+)<\/div>/) #組別を取得 acquired_groups = htmlcode.scan(/<b>組別:<\/b> <a href=\"\d+.+_tt.html.day\d+_\d+_\d+\">(?<tag_group>.+)<\/a><\/div>/) #順位を取得 acquired_ranks = htmlcode.scan(/<tr>\n.*<td class=\"text-right\">(?<tag_rank>\d?)<\/td>/) #クルー名を取得 acquired_crews = htmlcode.scan(/<td class=\"crew\">(?<tag_crew>.*)<\/td>/) #500mタイムを取得 acquired_lap1qs = htmlcode.scan(/<td class=\"crew\">.*<\/td>\n.*<td class=\"text-center\">(?<tag_q1>\d*:?\d*.?\d*)<\/td>\n/) #1000mタイムを取得 acquired_lap2qs = htmlcode.scan(/<td class=\"crew\">.*<\/td>\n.+<\/td>\n.*<td class=\"text-center\">(?<tag_q2>\d*:?\d*.?\d*)<\/td>\n/) #1500mタイムを取得 acquired_lap3qs = htmlcode.scan(/<td class=\"text-center\">(?<tag_q3>\d*:?\d*.?\d*)<\/td>\n.*<td class=\"text-center\">.*<\/td>\n.*<td class=\"text-right\">\d*<\/td>\n/) #2000mタイムを取得 acquired_lap4qs = htmlcode.scan(/<td class=\"text-center\">(?<tag_q4>\d*:?\d*.?\d*)<\/td>\n.*<td class=\"text-right\">\d*<\/td>\n/) #レーンNoを取得 acquired_lanenos = htmlcode.scan(/<td class=\"text-right\">(?<tag_lane>\d?)<\/td>\n.*<td class=\"qualify\">.*<\/td>\n/) #備考を取得 acquired_qualifys = htmlcode.scan(/<td class=\"qualify\">(?<tag_qualify>.*)<\/td>\n/) #//---レース情報をスクレイピング--- #順位別情報の行と列を入れ替える infos_by_rank = acquired_ranks.zip(acquired_crews,acquired_lap1qs,acquired_lap2qs,acquired_lap3qs,acquired_lap4qs,acquired_lanenos,acquired_qualifys) #id情報(レースNo,日時など)の行と列を入れ替える identifiers = acquired_racenos.zip(acquired_starttimes,acquired_groups) #id情報に種目名を格納する identifiers.each do |identifier| identifier.insert(1,tag_event) end #全レース結果が入る配列を作成 raceinfos_all = [] #1レース単位の結果が入る配列を作成 raceinfo_by_race = [] count = 0 infos_by_rank.each do |infobyrank| count += 1 infobyrank.flatten! #剰余を使った条件判断(1着から6着で区切った次で配列を初期化する) raceinfo_by_race = [] if count % 6 == 1 raceinfo_by_race << infobyrank #1着から6着を1セットとして全レース結果の配列に格納する raceinfos_all << raceinfo_by_race if count % 6 == 0 end #id情報(RaceNo、日時など)と順位別レース結果の行と列を入れ替える all_in_raceinfos = identifiers.zip(raceinfos_all) #不要な配列を平坦化 all_in_raceinfos.each do |info_by_race| info_by_race[0].flatten! end puts "----------" puts "#{tag_year}#{tag_tourname}" puts "----------" sleep(1.5) count_serch = 0 all_in_raceinfos.each do |info_by_race| if /.*#{clubname}[A-Z]?\)?\z/i =~ info_by_race[1][0][1] || /.*#{clubname}[A-Z]?\)?\z/i =~ info_by_race[1][1][1] || /.*#{clubname}[A-Z]?\)?\z/i =~ info_by_race[1][2][1] || /.*#{clubname}[A-Z]?\)?\z/i =~ info_by_race[1][3][1] || /.*#{clubname}[A-Z]?\)?\z/i =~ info_by_race[1][4][1] || /.*#{clubname}[A-Z]?\)?\z/i =~ info_by_race[1][5][1] count_serch += 1 #---ターミナル/PowerShellに出力--- #id情報の出力 puts "RaceNo #{info_by_race[0][0]} #{info_by_race[0][1]} #{info_by_race[0][3]}\n#{info_by_race[0][2]}" #順位別情報の出力 info_by_race[1].each do |rankinginfos| puts "#{rankinginfos[0]}着 #{rankinginfos[1]} #{rankinginfos[5]} #{rankinginfos[7]}" if rankinginfos[1] != "" end puts "---------------" #---CSVファイル作成--- File.open("#{tag_urlyear}_#{tag_urltour}_#{tag_urlevent}.csv","a:shift_jis") do |csv| csv.write "#{info_by_race[0][0]}\n#{info_by_race[0][1]} #{info_by_race[0][3]}\n#{info_by_race[0][2]}\n" csv.write "rank,crew,500m,1000m,1500m,2000m,lane,remarks\n" info_by_race[1].each do |rankinginfos| csv.write "#{rankinginfos[0]},#{rankinginfos[1]},#{rankinginfos[2]},#{rankinginfos[3]},#{rankinginfos[4]},#{rankinginfos[5]},#{rankinginfos[6]},#{rankinginfos[7]}, #{rankinginfos[8]}\n" end csv.write "\n" end end #// if /.*#{clubname}[A-Z]?\)?\z/i end #// all_in_raceinfos.each if count_serch == 0 print "クラブが見つかりませんでした。\n" else print "\n合計#{count_serch}レース見つかりました。\n" end end #//.if choice_serch == 1
更新履歴
ローイングファンの更新履歴。
ver1.1
手続き型のコードをオブジェクト指向型のコードに書きかえる - ローイングファンの日記
Webアプリ ローイングファンのURL
https://rowingfan.herokuapp.com/
今回の動作確認環境
macOS 10.13.4
Ruby 2.4.3p205
ターミナル 2.8.2
Windows10 1709
Ruby 2.4.4p296
Windows PowerShell 5.1