前回ではダウンロードからHTML作成までトータルで実行できるプログラムにしました。今回はそれを改良していきます。
以前、[F1公式サイトのスクレイピング](アドレス)は以下から。
改良してみよう
今の状態ではどのレースまで終了した時点のランキングなのかがわからないので、それを表示するように変更。さらに、レース終了してあたらしいランキングになった場合には別名で保存されるように改良していきたいと思います。ファイル名については
- グランプリ名+_finished.html
というルールにします。さて、まずは2016年のF1スケジュールを公式サイトから抽出して、日時をデータ化しましょう。
2016 FIA Formula One World Championship® Race Calendar
上記のページを開いて、chromeの検証からコンソールから以下のスクリプトを実行します。
var a_list = document.getElementsByClassName('teaser-date'); var b_list = document.getElementsByClassName('teaser-info-title'); for(i=0; i<a_list.length; i++){ console.log(a_list[i].innerText); console.log(b_list[i].innerText); }
結果は
18 - 20 MAR 2016 FORMULA 1 ROLEX AUSTRALIAN GRAND PRIX 01 - 03 APR 2016 FORMULA 1 GULF AIR BAHRAIN GRAND PRIX 15 - 17 APR 2016 FORMULA 1 PIRELLI CHINESE GRAND PRIX 29 APR - 01 MAY 2016 FORMULA 1 RUSSIAN GRAND PRIX 13 - 15 MAY FORMULA 1 GRAN PREMIO DE ESPAÑA PIRELLI 2016 26 - 29 MAY FORMULA 1 GRAND PRIX DE MONACO 2016 10 - 12 JUN FORMULA 1 GRAND PRIX DU CANADA 2016 17 - 19 JUN 2016 FORMULA 1 GRAND PRIX OF EUROPE 01 - 03 JUL FORMULA 1 GROSSER PREIS VON ÖSTERREICH 2016 08 - 10 JUL 2016 FORMULA 1 BRITISH GRAND PRIX 22 - 24 JUL FORMULA 1 MAGYAR NAGYDÍJ 2016 29 - 31 JUL FORMULA 1 GROSSER PREIS VON DEUTSCHLAND 2016 26 - 28 AUG 2016 FORMULA 1 BELGIAN GRAND PRIX 02 - 04 SEP FORMULA 1 GRAN PREMIO HEINEKEN D'ITALIA 2016 16 - 18 SEP 2016 FORMULA 1 SINGAPORE AIRLINES SINGAPORE GRAND PRIX 30 SEP - 02 OCT 2016 FORMULA 1 PETRONAS MALAYSIA GRAND PRIX 07 - 09 OCT 2016 FORMULA 1 EMIRATES JAPANESE GRAND PRIX 21 - 23 OCT 2016 FORMULA 1 UNITED STATES GRAND PRIX 28 - 30 OCT FORMULA 1 GRAN PREMIO DE MÉXICO 2016 11 - 13 NOV FORMULA 1 GRANDE PRÊMIO DO BRASIL 2016 25 - 27 NOV 2016 FORMULA 1 ETIHAD AIRWAYS ABU DHABI GRAND PRIX
こんな感じに抽出できます。このデータを利用して以下のようなテキストを作成。
3/20,AUSTRALIAN GRAND PRIX 4/3,BAHRAIN GRAND PRIX 4/17,CHINESE GRAND PRIX 5/1,RUSSIAN GRAND PRIX 5/15,SPAIN GRAND PRIX 5/29,MONACO GRAND PRIX 6/12,CANADA GRAND PRIX 6/19,EUROPE GRAND PRIX 7/3,AUSTRIA GRAND PRIX 7/10,BRITISH GRAND PRIX 7/24,HUNGARY GRAND PRIX 7/31,GERMANY GRAND PRIX 8/28,BELGIAN GRAND PRIX 9/4,ITALIA GRAND PRIX 9/18,SINGAPORE GRAND PRIX 10/2,MALAYSIA GRAND PRIX 10/9,JAPANESE GRAND PRIX 10/23,USA GRAND PRIX 10/30,MEXICO GRAND PRIX 11/13,BRASIL GRAND PRIX 11/27,ABU DHABI GRAND PRIX
これをf1carendar.txtとして保存しておきます。
HSPでこれを読み込んで、現在の日時と比較してどのレース終了時点なのかを事前に格納していきましょう。コードは
// f1カレンダーチェック month = gettime(1) day = gettime(3) + month * 40 racename = "" notesel a noteload "f1calendar.txt" repeat notemax noteget text_line, cnt split text_line, ",", result split result(0), "/", chk_mm, chk_dd chkday = int(chk_dd) + int(chk_mm) * 40 if day > chkday { racename = result(1) } else { break } loop
こんな感じでしょうか。dayに今日の日付けと月×40を入れて、カレンダーの月日(chkday)も同じ計算式にして、両者を比較。chkdayが大きくなった時点より一つ前のレース名を取り出しています。
html内に終了時点の一文を追加する
これをダウンロード~html生成に組み込んでファイル名やhtml本体に表示させます。表示位置はランキングの下に※印入りで付け加えます。スクリプトの最後の方にある
html_text += "</ul>\n</body>\n</html>\n"
を
html_text += "</ul>\n<p>※" + racename + " 終了時点のランキングです</p></body>\n</html>\n"
に変更します。確認してみると
ちゃんと反映されていますね。
保存するhtmlファイル名を変更する
ファイル名はスクリプト最後の方の
notesave "driverspoint.html"
これを書き換えればOK。ルールは
- グランプリ名+_finished.html
だったので、これに沿ったコードに変更しましょう。
notesave racename+"_finished.html"
ちゃんとグランプリ名+_finished.htmlに変わってますね。これでレース終了ごとに違うファイル名になるのでシーズン通して終了時点でのランキングhtmlが生成できるようになりました。
まとめ
これで一応完成です。他にもいろいろな改良ができるかと思います。ドライバーポイントの折れ線グラフを表示するのも面白かもしれませんね。
全スクリプトを下記に公開しておきますので、お試しくださいませ。とはいっても2016シーズンのみ対応なので期限がありますが…。
//HSPモジュール SAKMISさんのを使用しています //命令→lfcc ファイルネーム //読み込み→改行置換→保存 #module #deffunc lfcc str filename ; mref filename,32 ; mref status,64 exist filename size=strsize if size=-1 : status=-1 : return sdim ss,size+1,1 bload filename,ss,size ii=0 code=0 sdim data,size<<1,1 repeat size tt = peek (ss,cnt) if tt=10 : code=10 : break if tt=13 { code=13 tt = peek (ss,cnt+1) if tt=10 : code=0 break } loop if code=0 : status=-1 : return repeat size tt = peek (ss,cnt) if tt=code : wpoke data,ii,2573 : ii+2 : continue poke data,ii,tt : ii++ loop bsave filename,data,ii status=ii return #global #include "hspinet.as" // ネット接続の確認 netinit if stat : dialog "ネット接続できません" : end // 初期設定 download_url = "https://www.formula1.com/en/results.html/2016/drivers.html" sdim firstname, 40, 40 sdim familyname, 40, 40 sdim country, 40, 40 sdim teamname, 40, 40 sdim getpoint, 40, 40 // f1カレンダーチェック(第6回作成部分) month = gettime(1) day = gettime(3) + month * 40 racename = "" notesel a noteload "f1calendar.txt" repeat notemax noteget text_line, cnt split text_line, ",", result split result(0), "/", chk_mm, chk_dd chkday = int(chk_dd) + int(chk_mm) * 40 if day > chkday { racename = result(1) } else { break } loop /* 第一回で作成したダウンロード部分 */ // URL分解 if (instr(download_url, 0, ".html") ! -1) or (instr(download_url, 0, ".php") ! -1) { //.html .phpが含まれているなら split download_url, "/", result url_pagename = result(stat-1) url_address = download_url strrep url_address, url_pagename, "" } else { // 含まれていない場合はindex.htmlにする url_address = download_url url_pagename = "index.html" } neturl url_address netrequest url_pagename *main //取得待ち確認 netexec res if res > 0 : goto *comp if res < 0 : goto *bad await 50 goto *main *bad //エラー neterror estr mes "ERROR "+estr stop *comp mes "DOWNLOAD 完了" //stop /*html生成部分(2~5回で作成)*/ lfcc "drivers.html" notesel htmlfile noteload "drivers.html" first_cnt = 0 : family_cnt = 0 : country_cnt = 0 : teamname_cnt = 0 repeat notemax noteget text_line, cnt // ファーストネーム if (instr(text_line, 0, "hide-for-tablet") ! -1) { strrep text_line, "<span class=\"hide-for-tablet\">", "" strrep text_line, "</span>", "" strrep text_line, " ", "" //split text_line, ">", buf //split buf(1), "<", result //text_line = result(0) firstname(first_cnt) = text_line first_cnt++ continue } // ファミリーネーム if (instr(text_line, 0, "hide-for-mobile") ! -1) { strrep text_line, "<span class=\"hide-for-mobile\">", "" strrep text_line, "</span>", "" strrep text_line, " ", "" familyname(family_cnt) = text_line family_cnt++ continue } // 国籍 if (instr(text_line, 0, "dark semi-bold uppercase") ! -1) { strrep text_line, "<td class=\"dark semi-bold uppercase\">", "" strrep text_line, "</td>", "" strrep text_line, " ", "" country(country_cnt) = text_line country_cnt++ continue } // 所属チーム if (instr(text_line, 0, "grey semi-bold uppercase ArchiveLink") ! -1) { split text_line, ">", buf split buf(1), "<", result teamname(teamname_cnt) = result(0) teamname_cnt++ continue } // 獲得ポイント if (instr(text_line, 0, "dark bold") ! -1) and (instr(text_line, 0, "</td>") ! -1) { strrep text_line, "<td class=\"dark bold\">", "" strrep text_line, "</td>", "" strrep text_line, " ", "" getpoint(point_cnt) = text_line point_cnt++ continue } loop noteunsel //make_html html_text = "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta http-equiv=\"content-language\" content=\"ja\">\n<title>2016ドライバーランキング</title>\n<style>\nbody {\ncounter-reset: drivername;\n}\nli {\ndisplay: flex;\n}\ndiv {\nmargin-right: 1rem;\n}\n.drivername, .team {\nwidth: 12rem;\n}\n.country {\nwidth: 6rem;\n}\n.drivername:before {\ncounter-increment:drivername;\ncontent:counter(drivername) \"位 \";\ndisplay: inline-flex;\nwidth: 3rem;\n}\n</style>\n</head>\n<body>\n<h1>2016ドライバーランキング</h1>\n<ul>" repeat 40 if firstname(cnt) = "" : break html_text += "<li>\n<div class=\"drivername\">" + firstname(cnt) + " " + familyname(cnt) + "</div>\n<div class=\"country\">" + country(cnt) + "</div>\n<div class=\"team\">" + teamname(cnt) + "</div>\n<div class=\"point\">" + getpoint(cnt) + "</div>\n</li>\n" loop //html_text += "</ul>\n</body>\n</html>\n" html_text += "</ul>\n<p>※" + racename + " 終了時点のランキングです</p></body>\n</html>\n" nkfcnv html_text,html_text,"Sw" notesel html_text //notesave "driverspoint.html" notesave racename+"_finished.html" noteunsel await 1 dialog "save html file" //mesbox html_text, 640, 400 end stop