前回はデータを取り出しが完了しました。今回はページの作成部分に取り掛かりたいと思います。
以前、[F1公式サイトのスクレイピング](アドレス)は以下から。
取り出したデータと格納先
ここまでで取り出せたデータとその格納先です
- 【ドライバー名】
- ファーストネーム→firstname(数字)
- ファミリーネーム→familyname(数字)
- 【国籍】
- country(数字)
- 【所属チーム】
- teamname(数字)
- 【獲得ポイント】
- getpoint(数字)
という感じ。数字の部分はそれぞれの格納先共通で、たとえばルイス・ハミルトンならこの時点でランキングトップなので0、ニコ・ロズベルグなら1という風になってます。
ページの雛形を用意する
実際にポイントライキングのページを作成していきたいと思います。まず、雛形になるhtmlを考えていきましょう。大枠は以下のような感じでしょうか。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="content-language" content="ja"> <title></title> </head> <body> </body> </html>
この雛形に必要なものを書き込んでhtmlファイルとして保存してあげるのが最終目標になります。とはいえ、いきなり追加要素をプログラミングするわけにもいかないので、まずは実際に完成目標のhtmlファイルを作ってみることにしましょう。
htmlを作成する
イメージは上のようなシンプルなもので考えてます。あとからスタイルシートなどで装飾すればいいですしね。これをhtmlで書いてみると
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="content-language" content="ja"> <title>2016ドライバーランキング</title> <style> body { counter-reset: drivername; } li { display: flex; } div { margin-right: 1rem; } .drivername, .team { width: 9rem; } .country { width: 6rem; } .drivername:before { counter-increment:drivername; content:counter(drivername) "位 "; } </style> </head> <body> <h1>2016ドライバーランキング</h1> <ul> <li> <div class="drivername">Louis Hamilton</div> <div class="country">GBR</div> <div class="team">Mercedes</div> <div class="point">250</div> </li> <li> <div class="drivername">Louis Hamilton</div> <div class="country">GBR</div> <div class="team">Mercedes</div> <div class="point">250</div> </li> <li> <div class="drivername">Louis Hamilton</div> <div class="country">GBR</div> <div class="team">Mercedes</div> <div class="point">250</div> </li> <li> <div class="drivername">Louis Hamilton</div> <div class="country">GBR</div> <div class="team">Mercedes</div> <div class="point">250</div> </li> <li> <div class="drivername">Louis Hamilton</div> <div class="country">GBR</div> <div class="team">Mercedes</div> <div class="point">250</div> </li> </ul> </body> </html>
こういう感じになりました。ちなみに、順位の部分はCSSにて対応してるのでhtml上には該当部分がない状態です(その方がシンプルに処理できそうなので)。また、ダミーなので5位までですが、これがドライバー人数分になるイメージですね。みてもらえばわかるのですが、繰り返し出てくる
<li> <div class="drivername">Louis Hamilton</div> <div class="country">GBR</div> <div class="team">Mercedes</div> <div class="point">250</div> </li>
この部分をHSPで作ることになります。ドライバー名、国籍、チーム名、ポイントなので取り出したデータをそのまま使う形で大丈夫そうですね。
HSPでhtmlを成形していく
htmlをプログラミングで生成するというとなんだか難しそうな感じですが、実はテキスト(文章)を作っていくのと同じだったりします。なので上の例をそのまま書くと
html_text = "<li>\n <div class=\"drivername\">Louis Hamilton</div>\n <div class=\"country\">GBR</div>\n <div class=\"team\">Mercedes</div>\n <div class=\"point\">250</div>\n </li>"
となります(みやすくするために改行してます)。そして、この内容をファイル保存する際にhtmlの拡張子にしてあげればOK。これならそんなに難しくないですよね。ちなみに改行は「¥n」、ダブルクォーテーションを出力するためには「¥”」としてあげる必要があるので注意してください(表示上全角で書いてますが、スクリプト上では半角です)。
ところで前回までで内容確認のために表示させていた部分があったかと思います。
//debug chk = "" repeat 40 if firstname(cnt) = "" : break chk += firstname(cnt) + " " + familyname(cnt) + "\t(" + country(cnt) + ") \t【" + teamname(cnt) + "】 " + getpoint(cnt) + "p\n" loop mesbox chk, 640, 400 stop
ここで全ドライバー文の確認を賄っていたとなれば…これを改造すればhtml用のテキストが成型できそうですよね。なので、これを改造していきたいと思います。ここでもう一度格納変数を確認。
- 【ドライバー名】
- ファーストネーム→firstname(数字)
- ファミリーネーム→familyname(数字)
- 【国籍】
- country(数字)
- 【所属チーム】
- teamname(数字)
- 【獲得ポイント】
- getpoint(数字)
今回、ドライバー名は分けずに処理、他はそれぞれdivで括っているのでイメージとしては
<li> <div class="drivername">firstname(cnt) familyname(cnt)</div> <div class="country">country(cnt)</div> <div class="team">teamname(cnt)</div> <div class="point">getpoint(cnt)</div> </li>
という感じですかね。ちゃんとHSPで処理できるように整えてみると
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"
こんな感じですね。実際には改行をしないで一文にしてしまうので
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"
となります。さらにhtmlとしてファイルを保存するために
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="content-language" content="ja"> <title>2016ドライバーランキング</title> (中略) </head> <body> <h1>2016ドライバーランキング</h1> <ul>
という前半部分と
</ul> </body> </html>
の締めの部分を追加しておきたいところです。これらを考慮してスクリプトを書いてみると…
//debug 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: 9rem;\n}\n.country {\nwidth: 6rem;\n}\n.drivername:before {\ncounter-increment:drivername;\ncontent:counter(drivername) \"位 \";\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" mesbox html_text, 640, 400 stop
となります。これを組み込んで実行してみると
ちゃんとテキストが整形されてますね。あとはこれをhtml形式で出力してあげればほぼ完成。次回はダウンロードからHTML出力まで一発で実行できるスクリプトを完成させましょう。今回はここまで。
まとめ
だいぶん完成に近づいてきました。毎度おなじみですが、今回の全コードを以下に載せておきますので、ぜひ試してみてくださいね。
//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 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 //debug 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: 9rem;\n}\n.country {\nwidth: 6rem;\n}\n.drivername:before {\ncounter-increment:drivername;\ncontent:counter(drivername) \"位 \";\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" mesbox html_text, 640, 400 stop