開幕までになんとかしたいと思っているので、短期集中な感じになってしまいましたね。今回で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