【HSP】2017年版 F1ランキングページを生成してみる【その8】

mclaren2017

いよいよ今月末にF1が開幕します! ということで、この企画(?)もちゃんと形になるようにスパートをかけていかなければなりません。とはいえ、結局のところは自己満足でしかないんですけどねw

今のところ

  • ドライバーズポイントランキングの取得、ページ生成(2016年版の改良)
  • レースごとのリザルトページのURL取得、CSV出力
  • リザルトページから着順などのデータを取得、簡易ページ生成、CSV出力

といったことをやってきました。ここから、ドライバーズポイントのCSVなどを作成していこうかと思っていたんですが、少し思考を変えて

【全戦の結果をCSVで集計する】

にしてみたいと思います。これによって

  • 各レースでの簡易的な結果
  • ドライバーごとの順位変動
  • ドライバーのポイント順位

なとが取り出せるファイルになるはずです。もちろん、全戦の結果を集計するといっても基本的には

*リザルトページから取得したデータを用いる

という部分に変更はないので、あとはどういう風にデータを処理していくかを工夫していきたいと思います。

スポンサーリンク

CSVデータのイメージを考えてみる

先ほど出した項目を考慮してザックリとイメージしてみます。

ドライバー単位でレースの結果データからポイントとなるものをCSVに組み込んでいく形。内容は

  • 順位
  • ポイント
  • ラップ(タイム差)

の3項目としました。これによって簡易的な結果表示はこのCSVを確認すれば取り出せる仕様になるはずです。もちろんレース毎の詳細なデータは以前出力するようにしたCSVで保存しておけば問題ないですしね。

2016年の全戦をデータ化してみる

前回のプログラムを利用していきます。部分部分を取り出して書いていきますので、全コードを確認したい場合はページの一番下をみてみてください。

ダウンロード実行部分をサブルーチン化

まず、ダウンロード実行部分は何度か利用する場面がでてくると思われるので、これをサブルーチン化してしまいます。といっても、作業は実行部分をプログラムの最後に持っていって、ラベルとreturnを設定してあげるだけです。

/* ダウンロードサブルーチン化 */
* dl_start
// 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
dialog "ERROR "+estr
end
stop

*comp
mes "DOWNLOAD 完了"

return

また、このルーチンに飛ばす場合は、必ずdownload_urlにURLを入れてあげてから飛ぶ必要があります。また、ダウンロードされたファイル名はurl_pagenameに格納されています。

//レースリザルト一覧ページダウンロード
download_url = "https://www.formula1.com/en/results.html/2016/races.html"
gosub * dl_start

gpnameやurlを取り出す

CSVで保存されたurlを取り出してダウンドーロする処理を書いていきます。ひとまず、CSVを読み込み直しましょう。

notesel csv_text
noteload "Raceresulturl.csv"

読み込んだ内容からレース名とURLを取り出していきます。

repeat notemax
    noteget text_line, cnt
    split text_line, ",", gpname(cnt), geturl(cnt)
loop

一旦、note系の命令をリセットしておきます。

noteunsel
await 1

次に、取り出したURLを使ってダウンロードしていくのですが

  • 以前、ダウンロードしてデータ化している場合は除外
  • データ化していない場合はデータ化処理をしていく

という2点も追加していきます。

以前、ダウンロードしてデータ化している場合は除外

この判定ですが、

  • レースの詳細CSVファイルが存在しているか

を基準にしてみたいと思います。まず、CSVファイルが存在するかどうかの確認。以前、CSVファイルが存在しているかの確認でもつかったdirlist命令を使います。

dirlist chk, gpname+".csv"
if (stat ! 0) : (次のレースのチェックに)

これをrepeat~loopの中に入れ込み、そして、データ化していない場合の処理を追加しましょう。

データ化処理をサブルーチン化する

まず、先述の部分をコードにしておきます。

repeat 40, 1
    if gpname(cnt) = "" : break //レース名が空なら終了
    //レース結果のCSVファイルが存在してるかチェック
    dirlist chk, gpname(cnt)+".csv"
    if (stat ! 0) : continue
    //存在していない場合、ダウンロードする
    download_url = geturl(cnt)
    gosub *dl_start
    //データ化処理をする
    gpname_now = gpname(cnt)
    gosub *race_csv
loop

ここでデータ化処理をするという部分に注目してください。gpname_nowという入れ物を用意して現在のgpname(cnt)の中身を入れています。これはサブルーチン先で使うための処理となっています。そして、race_csvというラベル先でデータ化処理をしていきます。

処理については以前作成したものを利用します。先程のサブルーチン化と同じでラベルとreturnを設置し、先程のgpname_nowを使ってファイル名を処理してあげます。

/* レース結果処理サブルーチン化 */
*race_csv
notesel htmlfile
noteload url_pagename
first_cnt = 0 : family_cnt = 0 : country_cnt = 0 : teamname_cnt = 0
position_cnt = 0 : carnumber_cnt = 0 : laps_cnt = 0 : times_cnt = 0
repeat notemax

(中略)

nkfcnv html_text,html_text,"Sw"

//HTML出力
notesel html_text
notesave gpname_now + ".html"
noteunsel
await 1
// csv出力
notesel csv_text
notesave gpname_now + ".csv"
noteunsel
await 1
mes "save html file"

return

これでサブルーチン化も完了。実行してみると

ちゃんとデータ化できているようです。さらに、もう一度実行してみても、上書きされずに終了しているのでファイルの存在確認部分もちゃんと機能していますね。

まとめ

コードも含めるとかなり長くなってしまいそうなので、ここで一旦区切ります。次回はこの続きからになります。いつものようにコードを載せておきますので、興味のある方は試してみてくださいね!

//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"

    // csv_check
    dirlist chk, "Raceresulturl.csv"
    await 1
    if (stat = 0) {
        csv_text = "GP Name,URL\n"
    } else {
        notesel csv_text
        noteload "Raceresulturl.csv"
        noteunsel
    }


    // ネット接続の確認
    netinit
    if stat : dialog "ネット接続できません" : end

    // 初期設定
//  download_url = "https://www.formula1.com/en/results.html/2017/drivers.html"
//  download_url = "https://www.formula1.com/en/results.html/2016/races/938/australia/race-result.html"
    sdim firstname,  40, 40
    sdim familyname, 40, 40
    sdim country,    40, 40
    sdim teamname,   40, 40
    sdim getpoint,   40, 40
    // 追加したもの
    sdim position,   40, 40
    sdim carnumber,  40, 40
    sdim laps,       40, 40
    sdim times,      40, 40
    sdim geturl,     200, 40
    sdim gpname,     200, 40

    //レースリザルト一覧ページダウンロード
    download_url = "https://www.formula1.com/en/results.html/2016/races.html"
    gosub *dl_start


    /*url抽出部分*/
    *skippoint //チェック用ラベル
    notesel htmlfile
    noteload url_pagename
    url_cnt = 0
    repeat notemax
        noteget text_line, cnt
        // RACE_URL
        if (instr(text_line, 0, "dark bold ArchiveLink") ! -1) {
            split text_line, "\"", buf
            // csv_text check
            if (instr(csv_text, 0, buf(1)) ! -1) : continue
            // geturl
            geturl(url_cnt) = buf(1)
            noteget gpname(url_cnt), cnt+1
            strrep gpname(url_cnt), " ", ""
            gpname(url_cnt) += " GP result"
            url_cnt++
        }
    loop
    //test
    //dialog geturl(0)
    //dialog gpname(0)
    noteunsel

    //make_csv
    //csv_text = "GP Name,URL\n"
    repeat 40
        if gpname(cnt) = "" : break
        csv_text += gpname(cnt) + ",https://www.formula1.com" + geturl(cnt) + "\n"
    loop

    // csv出力
    if (gpname(0) ! "") {
        notesel csv_text
        notesave "Raceresulturl.csv"
        noteunsel
        await 1
        dialog "save new csv file"
    }




    // url→raceresultダウンロード

    notesel csv_text
    noteload "Raceresulturl.csv"
    repeat notemax
        noteget text_line, cnt
        split text_line, ",", gpname(cnt), geturl(cnt)
    loop
    noteunsel
    await 1

    repeat 40, 1
        if gpname(cnt) = "" : break //レース名が空なら終了
        //レース結果のCSVファイルが存在してるかチェック
        dirlist chk, gpname(cnt)+".csv"
        if (stat ! 0) : continue
        //存在していない場合、ダウンロードする
        download_url = geturl(cnt)
        gosub *dl_start
        //データ化処理をする
        gpname_now = gpname(cnt)
        gosub *race_csv
    loop

    end
    stop



    /* ダウンロードサブルーチン化 */
    *dl_start
    // 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
    dialog "ERROR "+estr
    end
    stop

    *comp
    mes "DOWNLOAD 完了"
    lfcc url_pagename

    return


    /* レース結果処理サブルーチン化 */
    *race_csv
    notesel htmlfile
    noteload url_pagename
    first_cnt = 0 : family_cnt = 0 : country_cnt = 0 : teamname_cnt = 0
    position_cnt = 0 : carnumber_cnt = 0 : laps_cnt = 0 : times_cnt = 0
    repeat notemax
        noteget text_line, cnt
        // 着順
        if (instr(text_line, 0, "<td class=\"dark\">") ! -1) {
            strrep text_line, "<td class=\"dark\">", ""
            strrep text_line, "</td>", ""
            strrep text_line, " ", ""
            position(position_cnt) = text_line
            position_cnt++
            continue
        }
        // カーナンバー
        if (instr(text_line, 0, "<td class=\"dark hide-for-mobile\">") ! -1) {
            strrep text_line, "<td class=\"dark hide-for-mobile\">", ""
            strrep text_line, "</td>", ""
            strrep text_line, " ", ""
            carnumber(carnumber_cnt) = text_line
            carnumber_cnt++
            continue
        }
        // ファーストネーム
        if (instr(text_line, 0, "<span class=\"hide-for-tablet\">") ! -1) {
            strrep text_line, "<span class=\"hide-for-tablet\">", ""
            strrep text_line, "</span>", ""
            strrep text_line, " ", ""
            firstname(first_cnt) = text_line
            first_cnt++
            continue
        }
        // ファミリーネーム
        if (instr(text_line, 0, "<span class=\"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, "semi-bold uppercase hide-for-tablet") ! -1) {
            split text_line, ">", buf
            split buf(1), "<", result
            teamname(teamname_cnt) = result(0)
            teamname_cnt++
            continue
        }
        // ラップ
        if (instr(text_line, 0, "<td class=\"bold hide-for-mobile\">") ! -1) {
            strrep text_line, "<td class=\"bold hide-for-mobile\">", ""
            strrep text_line, "</td>", ""
            strrep text_line, " ", ""
            laps(laps_cnt) = text_line
            laps_cnt++
            continue
        }
        // タイム
        if (instr(text_line, 0, "<td class=\"dark bold\">") ! -1) and (instr(text_line, 0, "</td>") ! -1) {
            split text_line, ">", buf
            split buf(1), "<", result
            times(times_cnt) = result(0)
            times_cnt++
            continue
        }
        // 獲得ポイント
        if (instr(text_line, 0, "<td class=\"bold\">") ! -1) {
            strrep text_line, "<td class=\"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>2017レースリザルト</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>2017レースリザルト</h1>\n<ul>"
    csv_text = "position,firstname,familyname,carnumber,teamname,point,laps,times\n"
    repeat 40
        if firstname(cnt) = "" : break
        html_text += "<li>\n<div class=\"position\">[" + position(cnt) + "]</div>\n<div class=\"drivername\">" + firstname(cnt) + " " + familyname(cnt) + "</div>\n<div class=\"country\">" + carnumber(cnt) + "</div>\n<div class=\"team\">" + teamname(cnt) + "</div>\n<div class=\"point\">" + getpoint(cnt) + "pt</div>\n<div class=\"times\">" + laps(cnt) + "(" + times(cnt) + ")</div>\n</li>\n"
        csv_text += position(cnt) + "," + firstname(cnt) + "," + familyname(cnt) + "," + carnumber(cnt) + "," + teamname(cnt) + "," + getpoint(cnt) + "," + laps(cnt) + "," + times(cnt) + "\n"
    loop
    html_text += "</ul>\n</body>\n</html>\n"


    nkfcnv html_text,html_text,"Sw"

    //HTML出力
    notesel html_text
    notesave gpname_now + ".html"
    noteunsel
    await 1
    // csv出力
    notesel csv_text
    notesave gpname_now + ".csv"
    noteunsel
    await 1
    mes "save html file"

    return

stop
スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする