はじめに
10月になってもまだまだ暑い鹿児島ですが日出が6時台や日の入りが17時台になり、季節が進んでいるの感じます。そこで日の出入り時刻をのMachiKaniaで表示できないかといろいろと試し、正規表現を扱うクラスREGEXPを使ってできるようになったのでそれをまとめました。
検証環境
以下の環境でプログラムの作成と検証を行ないました。
の
- macOS : Tahoe 26.0.1
- PicoCalc : Raspberry Pi Pico 2 W
- MachiKania : Phyllosoma 1.6.0
日の出入りデータの取得と加工
データをWebから取得する
日の出入りデータは国立天文台のWebサイトの暦計算室の各地のこよみで都道府県ごと(北海道だけは2つ)に、月を選択するとホールページとして表示されます。
このページのURLは鹿児島の2025年10月の場合、次のようになり、西暦の2025、月の10がそのまま含まれ、鹿児島を示す番号47が含まれているのが分かります。
https://eco.mtk.nao.ac.jp/koyomi/dni/2025/s4710.html
このページをWGETクラスのFORSTRING$()メソッドで取得し、変数に格納します。URLに西暦年、月の値が含まれているのでRTCから現在の日付の値を読み取りURLの文字列に組み込みます。
USECLASS WGET
REM RTCから年月日を取得、それぞれを変数に格納
Y$ = STRFTIME$("%Y")
M$ = STRFTIME$("%m")
D$ = STRFTIME$("%d")
REM 国立天文台から日の出入りデータをHTMLで取得
U$ = "https://eco.mtk.nao.ac.jp/koyomi/dni/" + Y$ + "/s47" + M$ + ".html"
S$ = WGET::FORSTRING$(U$)
データ検索用の正規表現
日の出入りデータはWebサイトでは表として表示されます。変数S$にはページ全体のHTMLソースが格納されているのでこの中かからプログラムを実行した日の日の出入りデータだけを取り出すために正規表現検索します。
日の出入りのデータは次に示す1行のHTMLに埋め込まれています。これは鹿児島の2025年10月の日の出入りのデータの冒頭部です。
<略>
<tr><th scope="col">日</th> <th scope="col">出</th> <th scope="col">方位[°]</th> <th scope="col">南中</th> <th scope="col">高度[°]</th> <th scope="col">入り</th> <th scope="col">方位[°]</th></tr> <tr><td id="m1001"> 1</td><td> 6:11</td> <td> 93.2</td> <td>12:08</td> <td> 55.2</td> <td>18:03</td> <td>266.6</td></tr> <tr><td> 2</td> <td> 6:12</td> <td> 93.6</td> <td>12:07</td> <td> 54.8</td> <td>18:02</td> <td>266.1</td></tr>
<略>
このソースを見るとところどころにタグとタグの間に空白文字があるのでSTRINGクラスのREPLC$()メソッドで削除しておきます。文字列> <を検索し、空白文字を取り除いた文字列><に置換します。
文字列変数S$(HTMLソース)に対するSTRINGクラスのオブジェクトVを生成し、文字列置換で空白文字を削除します。コードは次のとおりです。
USECLASS STRING
V = NEW(STRING, S$)
S$ = V.REPLC$("> <","><")
タグ間の空白文字を削除した文字列(HTMLソース)から特定の日付のデータを検索して取り出すために正規表現クラスREGEXPを使用します。
取り出すデータは日付、日出時刻、方位、南中時刻、高度、日の入り時刻、方位の順で表のセルに当てはめられています。
これから検索用の正規表現を次のように考えました。
| 項目 | 内容 | 正規表現 |
|---|---|---|
| タグ | <th>や<td> | タグの文字列のまま |
id属性 |
m4けたの10進数 |
( id="m\d{4}")? |
| 日付 | 1や12 | [ 123]\d |
| 時刻 | 5:16や19:27 | [ 1]\d:[0-5]\d |
| 方位と高度 | 62.0や298.0 | [ 12]\d{2}.\d |
時刻と方位あるいは高度のペアが3つ連続する。
これらから正規表現文字列は次のように定義される。
<tr><td( id="m\d{4}")?>[ 123]\d</td>(<td>[ 1]\d:「0−5\d</td><td>[ 12]\d{2}\.\d</td>){3}"
この正規表現はすべての日付に対応しているのがプログラムでは特定の日のみに限定するため、日付の部分はプログラム実行時の日付に置き換えます。
Webサイトでは日にちが一桁の場合の10の位は空白文字でRTCから取得した値は0と異なるため、HTMLの表記に合わせての変換し、変数X$に格納するようにします。コードは次のとおりです。
REM 日にちの10の位が0の場合、空白文字に
IF STRNCMP(D$, "0" ,1) = 0 THEN
X$ = " " + D$(1, 1)
ELSE
X$ = D$
ENDIF
id属性の値をダブルコーテーション(”)で囲んでいますがMachiKaniaではダブルコーテーションを文字列に含める場合にはエスケープした\x22を使用します。
日付の部分の正規表現のコードを次のように定義しました。
F$ = "( id=\x22m" + M$ + D$ + "\x22)?"
E$ = "<tr><td" + F$ + ">" + X$ + "</td>"
次に、時刻と方位あるいは高度のペアが3回繰り返しや一桁の10進数のパターン\dを含むコードを実行するとエラーにはならないがメモリ不足や実行が終わらないなど正常に動作しないので次のコードの用に変更しました。正規表現の文字列が最終的に変数E$に格納されています。
J$ = "(<td>[ 1][0-9]:[0-5][0-9]</td><td>[ 12][0-9][0-9]\.[0-9]</td>)+"
E$ = E$ + J$
データの検索
作成した正規表現のオブジェクトを生成し、REGEXEC()メソッドを使って検索を実行します。次に最初にマッチした文字列をMATCH$()メソッドで取得し、変数T$に格納します。
R = NEW(REGEXP,E$)
R.REGEXEC(S$)
T$ = R.MATCH$(0)
なお、正規表現オブジェクトの生成をWGET::FORSTRING$()のあとで実行するとHEXファイルがロードできない症状が出てプログラムの実行が止まってしまいます。
検索結果の文字列に含まれる可能性のあるid属性をSTRINGクラスのREPLC$メソッドで削除します。削除することで出力に取り出す文字列の位置指定を固定できます。
V = NEW(STRING,T$)
T$ = V.REPLC$(" id=\x22m"+m$+D$+"\x22", "")
データの表示
正規表現検索し、不要な文字列を削除した文字列は次に示す文字列になります。
<tr><td>10</td><td> 6:17</td><td> 97.2</td><td>12:05</td><td> 51.7</td><td>17:52</td><td>262.5</td></tr>
ここから日出時刻(20文字目から5文字)、南中時刻(48文字目から5文字)、日の入り時刻(76文字目から5文字)を取り出して日本語で表示します。
USEGRAPHIC
USECLASS CKNJ16
K = NEW(CKNJ16, "UTF-8")
POINT 0, 0 : K.GPRT(Y$+"年"+M$+"月"+D$+"日、鹿児島の日の出入り",7,0)
POINT 16, 18 : K.GPRT("日の出:" + T$(19,5), 7, 0)
POINT 16, 36 : K.GPRT("南 中:" + T$(47,5), 7, 0)
POINT 16, 54 : K.GPRT("日の入:" + T$(75,5), 7, 0)
ソースコード
以下が実際に動作するソースコードです。上記の説明時と一部のコードの位置が異なります。
USECLASS WGET,REGEXP,STRING,CKNJ16
USEGRAPHIC
Y$ = STRFTIME$("%Y")
M$ = STRFTIME$("%m")
D$ = STRFTIME$("%d")
U$ = "https://eco.mtk.nao.ac.jp/koyomi/dni/" + Y$ + "/s47" + M$ + ".html"
K = NEW(CKNJ16, "UTF-8")
POINT 0, 0
K.GPRT(Y$+"年"+M$+"月"+D$+"日、鹿児島の日の出入り",7,0)
IF STRNCMP(D$, "0" ,1) = 0 THEN
X$ = " " + D$(1, 1)
ELSE
X$ = D$
ENDIF
F$ = "( id=\x22m" + M$ + D$ + "\x22)?"
E$ = "<tr><td" + F$+">" + X$ + "</td>"
J$ = "(<td>[ 1][0-9]:[0-5][0-9]</td><td>[ 12][0-9][0-9]\.[0-9]</td>)+"
E$ = E$ + J$
R = NEW(REGEXP,E$)
S$ = WGET::FORSTRING$(U$)
V = NEW(STRING, S$)
S$ = V.REPLC$("> <","><")
R.REGEXEC(S$)
T$ = R.MATCH$(0)
V = NEW(STRING,T$)
T$ = V.REPLC$(" id=\x22m"+m$+D$+"\x22", "")
POINT 16, 18 : K.GPRT("日の出:" + T$(19,5), 7, 0)
POINT 16, 36 : K.GPRT("南 中:" + T$(47,5), 7, 0)
POINT 16, 54 : K.GPRT("日の入:" + T$(75,5), 7, 0)
WHILE INKEY() = 0 :WEND
END
実行結果
実際の動作の様子は下記から見られます。正規表現検索に時間がかかっているようです。
さいごに
MachiKaniaで国立天文台から日の出入りデータを取得し、データを取り出して表示できました。
MachiKaniaのREGEXPクラスを使っての文字列検索で繰り返しや特殊シーケンスが使えなかったのは残念でした。Raspberry Pi Pico 2 Wで実行しましたが文字列検索にはそれなりの時間がかかることがわかります。Raspberry Pi Picoだともう少しかかることが想像できます。正規表現検索にはそれなりのリソースが必要ですね。
