
開幕までになんとかしたいと思っているので、短期集中な感じになってしまいましたね。今回で10回目になります。さて、その今回は生成されるファイルをフォルダを用意しておいて、そこに入れるようにプログラムを改良していきたいと思います。主に生成されるファイルは
- レース単位のURLを格納してあるCSVファイル
- レース毎の簡易htmlファイル
- レース毎のCSVファイル
- 全レース結果CSVファイル
といったところです。ひとまずURLの格納してあるCSVは実行ファイルと同じ場所にある方がいいと思うのでそのままにします。他のファイルはそれぞれ「html」「csv」のフォルダを用意して、そこに保存するようにしていきたいと思います。しかも、プログラムでフォルダを有無を判断してなければ作成する、みたいな感じにしていきましょう。
フォルダの有無を確認、無ければ作成
フォルダの有無を確認するには「dirlist」を使用します。取得モードを設定することでフォルダ(ディレクトリ)のみを取得することもできちゃいます。
ディレクトリ一覧を取得
dirlist p1,”filemask”,p2
p1=変数 : ディレクトリ一覧を格納する文字列型変数
“filemask” : 一覧のためのファイルマスク
p2=0~(0) : ディレクトリ取得モード
取得モードは「5」にすることでフォルダのみを取り出せるようになります。ファイルマスクはワイルドカード「.」でOKなので、
dirlist chk, "*.*", 5 if instr(chk, 0, "html") = -1 : mkdir "html" if instr(chk, 0, "csv") = -1 : mkdir "csv"
という記述をプログラムの先頭に入れておけばフォルダチェック&生成は完了。実行してみると

↓

ちゃんとフォルダが作成されてますね!
それぞれのフォルダにファイルを生成するようにする
htmlはhtmlフォルダに、csvはcsvフォルダに格納するようにプログラムを改良していきたいと思います。
フォルダの場所を保存しておく
文字で書くとちょっぴり意味不明な感じですが、要するに
- 実行ファイルのあるアドレス(パス)を取得しておく
というのがポイントになります。これを中心にしてhtmlフォルダなら「\html」を追加してあげればいいですし、CSVも同様に「\CSV」を追加する形になります。ちなみにhspでは、実行ファイルのある場所(カレントディレクトリ)は
dir_cur
という変数に格納されています。なので、これを用いてhtmlとCSVの保存先のパスを作成しておきます。また、home_posという名前でカレントディレクトリも格納しておきましょう。
home_pos = dir_cur html_pos = dir_cur + "\\html" csv_pos = dir_cur + "\\csv"
※hspでは\がエスケープ文字になっているので、2つ続けて書く必要があります。
CSVが存在するかチェックする部分の改修
// 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
}
dirlist chk, "allresult.csv"
await 1
if (stat = 0) {
allresult_csv = "driver Name"
} else {
notesel allresult_csv
noteload "allresult.csv"
noteunsel
}
この部分、上はURLの抽出なのでそのままでOKなのですが、保存場所を切り替える作業をする上で、現在どのディレクトリで作業をしているかを明確にしておく方が安全だと思われます。なので、URLのCSVの有無をチェックする前に作業場所のフォルダに移動しておきましょう。フォルダ(ディレクトリ)の移動は「chdir」を使います。
// csv_check
chdir home_dir
dirlist chk, "Raceresulturl.csv"
await 1
if (stat = 0) {
(略)
で、全戦結果のCSVはCSVフォルダに格納するので、有無の確認もCSVフォルダに移動しておく必要があります。
(略)
}
chdir csv_dir
dirlist chk, "allresult.csv"
await 1
if (stat = 0) {
allresult_csv = "driver Name"
} else {
(略)
これでOK。
ダウンロードの前にもフォルダ場所の指定
フォルダの現在地を把握しておけばいいのですが、プログラムを改良していくと複雑になっていくのは必至なので、常に指定する形にしてリスクヘッジしておきます。まずはダウンロードする前に場所指定。
//レースリザルト一覧ページダウンロード chdir home_pos download_url = "https://www.formula1.com/en/results.html/2016/races.html" gosub *dl_start
レースリザルト一覧のダウンロード(URL抽出前)と
repeat 40, 1
if gpname(cnt) = "" : break //レース名が空なら終了
//レース結果のCSVファイルが存在してるかチェック
dirlist chk, gpname(cnt)+".csv"
if (stat ! 0) : continue
//存在していない場合、ダウンロードする
chdir home_pos
download_url = geturl(cnt)
gosub *dl_start
//データ化処理をする
gpname_now = gpname(cnt)
gosub *race_csv
loop
URLからレース毎のページダウンロード前に「chdir home_pos」を設置。
csvを読み込むときにも設置
せっかく作ったcsvファイルを読み込む時に作業しているフォルダが違っていたらエラーになってしまいます。なので、その前にも設置。
// url→raceresultダウンロード
chdir home_pos
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ファイルが存在してるかチェック
chdir csv_pos
dirlist chk, gpname(cnt)+".csv"
if (stat ! 0) : continue
//存在していない場合、ダウンロードする
chdir home_pos
download_url = geturl(cnt)
gosub *dl_start
//データ化処理をする
gpname_now = gpname(cnt)
gosub *race_csv
loop
ファイル出力時にも設置
で。ようやく今回のポイントとなる部分。ファイル出力する時に対応するフォルダに生成したいので、当然ここにも「chdir」を設置します。まずはURL一覧の出力先は「home_pos」
// csv出力
chdir home_pos
if (gpname(0) ! "") {
notesel csv_text
notesave "Raceresulturl.csv"
noteunsel
await 1
dialog "save new csv file"
}
htmlは「html_pos」
//HTML出力 chdir html_pos notesel html_text notesave gpname_now + ".html" noteunsel await 1
csvは「csv_pos」に
// csv出力 chdir csv_pos notesel csv_text notesave gpname_now + ".csv" noteunsel await 1 // allresult出力 chdir csv_pos notesel allresult_csv notesave "allresult.csv" noteunsel await 1
それぞれ抜粋しているので、わかりにくい場合は全コードは最後に載っているのでそちらで確認してみてください(chdirで検索するといいかも)。
すべて整ったら実行!
さっそく実行してみます!

しばらくするとウィンドウが消えれば実行完了! フォルダをみてみると

無事フォルダわけできてました。もう一度起動してみると、上書きも起こることなく終了…完璧です!!
まとめ
今回はファイルの保存先を分けるように改良しました。これでどこにどのファイルが存在するのかがわかりやすくなったんじゃないでしょうか? 最後に全コードを載せておきますので、実行してみてくださいね!
//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"
//#include "hspext.as"
// into_pos
home_pos = dir_cur
html_pos = dir_cur + "\\html"
csv_pos = dir_cur + "\\csv"
// folder_check
dirlist chk, "*.*", 5
if instr(chk, 0, "html") = -1 : mkdir "html"
if instr(chk, 0, "csv") = -1 : mkdir "csv"
// csv_check
chdir home_pos
dirlist chk, "Raceresulturl.csv"
await 1
if (stat = 0) {
csv_text = "GP Name,URL\n"
} else {
notesel csv_text
noteload "Raceresulturl.csv"
noteunsel
}
chdir csv_pos
dirlist chk, "allresult.csv"
await 1
if (stat = 0) {
allresult_csv = "driver Name"
} else {
notesel allresult_csv
noteload "allresult.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
//レースリザルト一覧ページダウンロード
chdir home_pos
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出力
chdir home_pos
if (gpname(0) ! "") {
notesel csv_text
notesave "Raceresulturl.csv"
noteunsel
await 1
mes "save new urlcsv file"
}
// url→raceresultダウンロード
chdir home_pos
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ファイルが存在してるかチェック
chdir csv_pos
dirlist chk, gpname(cnt)+".csv"
if (stat ! 0) : continue
//存在していない場合、ダウンロードする
chdir home_pos
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_area
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"
/* 項目部分取り出し・追加 */
notesel allresult_csv
noteget text_line, 0
split text_line, ",", buf
comma = stat
text_line += "," + gpname_now + ":pos,pts,laps"
noteadd text_line, 0, 1
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"
/* データの格納しなおし */
drivername = firstname(cnt) + " " + familyname(cnt) : title gpname_now + ":" + drivername
data_box = position(cnt) + "," + getpoint(cnt) + "," + laps(cnt) +"(" + times(cnt) + ")"
/* ドライバーデータの追加 */
if (instr(allresult_csv, 0, drivername) = -1) {
addcomma = "" : repeat comma: addcomma += "," : loop
allresult_csv += drivername + addcomma + data_box + "\n"
} else {
repeat notemax
noteget text_line, cnt
if (instr(text_line, 0, drivername) ! -1) {
split text_line, ",", buf
dirver_comma = comma - stat + 1
addcomma = "" : repeat dirver_comma : addcomma += "," : loop
text_line += addcomma + data_box
noteadd text_line, cnt, 1
}
loop
}
loop
noteunsel
html_text += "</ul>\n</body>\n</html>\n"
nkfcnv html_text,html_text,"Sw"
//HTML出力
chdir html_pos
notesel html_text
notesave gpname_now + ".html"
noteunsel
await 1
// csv出力
chdir csv_pos
notesel csv_text
notesave gpname_now + ".csv"
noteunsel
await 1
// allresult出力
chdir csv_pos
notesel allresult_csv
notesave "allresult.csv"
noteunsel
await 1
mes "save html file"
return
stop