HSPでF1ポイントのランキングページを生成してみる~その2~【HSP活用術】

hsp code2

前回は公式ページのダウンロードが完了したので、今回はそれを使って解析してデータを取り出していきたいと思います。

HSPでF1ポイントのランキングページを生成してみる~その1~【HSP活用術】
以前、(アドレス)でも取り扱ったんですが、今回はもっと手軽に情報を取得できるようにHSPを使って、最終的にはローカルで見られるランキ...

以前、[F1公式サイトのスクレイピング](アドレス)は以下から。

formula1公式サイトのドライバーズランキングをスクレイピングしてみよう その4
おなじみになりつつありますが、まずはそれぞれのクラス名やタグの整理、コードを再確認しておきましょう。 クラス名、タグ 【...
formula1公式サイトのドライバーズランキングをスクレイピングしてみよう その3
それぞれのクラス名やタグの整理、コードを再確認しておきましょう。 まずはクラス名、タグ 【ドライバー名】 ファ...
formula1公式サイトのドライバーズランキングをスクレイピングしてみよう その2
前回(その1)で、それぞれのクラス名やタグの整理をしました。あらためて、確認してみましょう。 【ドライバー名】 ...
formula1公式サイトのドライバーズランキングをスクレイピングしてみよう その1
ニッチ過ぎて需要があるかどうかわかりませんが。。。javascriptで組んで、最終的にはブックマークレットにしてお手軽に実行できる...
スポンサーリンク

以前、スクレイピングの際に調べたやつ

以前、スクレイピングで調べた際の情報です。

  • 【ドライバー名】
    • ファーストネーム→クラス名(hide-for-tablet)、タグ(span)
    • ファミリーネーム→クラス名(hide-for-mobile)、タグ(span)
  • 【国籍】
    • クラス名(dark semi-bold uppercase)、タグ(td)
  • 【所属チーム】
    • クラス名(grey semi-bold uppercase ArchiveLink)、タグ(a)
  • 【獲得ポイント】
    • クラス名(dark bold)、タグ(td)

という感じでした。

ダウンロードしたファイルの読み込み

まず、前回ダウンロードしたファイルの読み込みをしてみましょう。HSPで文章などのファイルを扱う場合はnote系の命令が便利です。詳細はリファレンスを参照してもらうとして主に使うのは

  • notesel (ロードしたデータを入れる入れ物をセットする)
  • noteload (ファイルをロードする)
  • notesave (ファイルをセーブする)
  • noteunsel (セットした状態を解除する)
  • notemax (入れ物に入っているファイルの行数が格納される)
  • noteget (一行ずつ文章を取り出す)

簡単な説明もつけましたが、見てもらってわかるようにこれらはワンセットで使うことが多いですね。HSPでcsvやtxt、htmlファイルもこれらの命令で扱えるので本当に便利ですよ。
ということで、ざっくりとファイル読み込みのスクリプトを書いてみたいと思います。

#include "hspinet.as"

notesel htmlfile
noteload "drivers.html"
mesbox htmlfile, 640, 400
noteunsel
stop

mesboxを使って、読み込んだファイルを表示させてみたのですが。。。

改行コードがうまく反映されていないようです。ここでは手軽に進めるために、HSPモジュールのでSAKMISさんが作成されたものを使用させていただきました(今はページが存在していないようです)。以下のコードを文頭に追加しておきます。使い方はlfcc “filename”とすごく簡単で便利ですよ。

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

これを追加した後に

lfcc "drivers.html"

これをnotesel htmlfileの前に追加して実行してみると

無事改行が反映されました。これで読み込み完了!

hide-for-tabletを探しだしてみる

hide-for-tabletはドライバーのファーストネームを調べるのに見当を付けていたクラス名でした(この記事の冒頭参照)。これをHSPで探し出してみるスクリプトを考えます。さきほど出てきていたnote系の命令でnotegetという1行ずつ取り出す命令を使っていきましょう。で、その行の中にhide-for-tabletが含まれているかどうかをチェックして、含まれていたらダイアログで表示するようにしてみたいと思います。読み込み部分をそのまま活用して…

lfcc "drivers.html"
notesel htmlfile
noteload "drivers.html"
// mesbox htmlfile, 640, 400
repeat notemax
    noteget text_line, cnt
    if (instr(text_line, 0, "hide-for-tablet") ! -1) : dialog text_line
loop
noteunsel
stop

文章で説明すると「mesboxをコメントアウト、repeat~loopをnotemax(行数)繰り返す。notegetで1行ずつ取り出して”hide-for-tablet”が含まれていたら、dialogでその内容を表示」という流れ。実際に実行してみると

と該当する部分が取り出せているのがわかります。

ほしい部分だけを取り出す

では、その一文を分解して、欲しいデータだけを取り出してみましょう。取り出していた部分で共通しているのは

<span class="hide-for-tablet">driver名</span>

というspanタグの部分。これを

  • 不必要な部分(タグ)を取り除く
  • >や<で切り分けて取り出す

の2パターンのやり方がありそうです。すべてが綺麗に間違えなくタグが書かれているのであれば

<span class="hide-for-tablet">
</span>

のふたつをstrrep命令を使って取り除いてしまってもいいかもしれません。その場合は

strrep text_line, "<span class=\"hide-for-tablet\">", ""
strrep text_line, "</span>", ""
strrep text_line, " ", ""

こんな感じで書いていくといい感じになるかと思います。試しに実行してみると

という感じです。大丈夫そうですね。もうひとつの方法はsplitを使って切り分ける方法

split text_line, ">", buf
split buf(1), "<", result
text_line = result(0)

タグの部分で切り分けて中身を取りだす作戦。こちらも実行してみると

問題なさそうです。どちらでもいいとは思いますが、こういうアプローチもあることを覚えておくいいかもですね。

ファーストネームを格納していく

取り出せたら、前回用意した入れ物に格納していきましょう。ファーストネームは

  • firstname

の入れ物でした。配列宣言してあるので「firstname(0)」など0~39番まで入れ物が用意してある状態です。なので、1個入れたら数字を増やして次の箱に入れるような流れで進めていきたいと思います。これを踏まえてコードを書くと

lfcc "drivers.html"
notesel htmlfile
noteload "drivers.html"
fname_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, " ", ""
        firstname(fname_cnt) = text_line
        fname_cnt++
    }
loop
noteunsel
stop

実際にちゃんと代入されているかを確認するためにチェック表示させましょう。chkという入れ物を用意して、そこに結果を入れ込みます。

chk = ""

lfcc "drivers.html"
notesel htmlfile
noteload "drivers.html"
first_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, " ", ""
        firstname(first_cnt) = text_line
        chk += "fistname("+first_cnt+") = " + firstname(first_cnt) + "\n"
        first_cnt++
    }
loop
noteunsel
mesbox chk, 640, 400
stop

無事に取り出せていますね。このパターンでファミリーネームのデータも取り出してみましょう。

hide-for-mobileを探し出し、ファミリーネームを取り出す

さきほどまでのファーストネームの復習ですね。こんどは「hide-for-mobile」のクラス名を探し出して、余分なものを消してファミリーネームだけを取り出す流れです。さきほどのrepeat~loop文の中に加えて書いていきます。格納するのはfamilynameです。カウントはfamily_cntとしました。

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
}

また、chkについてはわかりやすい処理にするために別枠で記述するようにしました。

chk = ""
repeat 40
    if firstname(cnt) = "" : break
    chk += "fistname("+cnt+"):familyname("+cnt+") = " + firstname(cnt) + ":" + familyname(cnt) + "\n"
loop

実行結果をみてみると

うーん、キミライコネンの部分だけ&aumlや&ouml表記になってしまってますが、それ以外は大丈夫そうですね。これでドライバー名の取得は完了です。次回は引き続きデータ取り出しの処理を書いていきたいと思います。

まとめ

データの取り出しは順調に進んできましたね。これを格納しおわったら、HSPでhtmlの作成に取り掛かる予定です。こうご期待!

以下は今回の全コードになります。試してみてくださいね!(前回のプログラムでダウンロードしたdrivers.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
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, " ", ""
        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
    }
loop
noteunsel

//debug
chk = ""
repeat 40
    if firstname(cnt) = "" : break
    chk += "fistname("+cnt+"):familyname("+cnt+") = " + firstname(cnt) + ":" + familyname(cnt) + "\n"
loop
mesbox chk, 640, 400

stop
スポンサーリンク

シェアする

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

フォローする