見出し画像

アプリを作ろう──妙高市雪情報グラフ第4回:動作確認とデバッグ

アプリを作ろう──妙高市雪情報グラフ

第4回:動作確認とデバッグ

こんにちは。
前回は、動作確認の準備としてgitコマンドを整理しました。


今回はいよいよ、AIエージェントが作ってくれたコードを実際に動かしてみます
……が、当然のように動きません。そこからが本番です。

ちなみに、バイブコーディング(AIと対話しながらコードを書く手法)は、
別の記事「お誕生日お祝いアプリ」に続いて 2回目 です。
ただ、今回はHTMLから表データを取り出す テーブル処理 があるので、
前回より難しそうだな……と思いながらのスタートでした。
Cursor君、よろしくお願いします。

:::message
この連載は、Webアプリ開発初心者が、同じく初心者の方に向けて書いている記事です。
エラーや試行錯誤も隠さず共有しますので、一緒に「できた!」を目指しましょう。
:::


まずは動かしてみる

仮想環境を作って、依存パッケージをインストールしたら、さっそく実行です。

streamlit run main.py

10秒ほど待つと、アプリが立ち上がりました。

左側に年月選択のサイドバー、右側に3つのグラフ表示エリア……
仕様通りの構成です。

でも、グラフが表示されていません。

画面には、こんなエラーメッセージが出ています。

❌ 2026年11月 / 新井消防署 のデータ取得に失敗しました

ここからデバッグの旅が始まります。


問題① URLリストが正しくない

まず疑ったのは、URLリストが正しいかどうかです。

CSVファイルに書かれたURLをブラウザで開いてみると……

「お探しのページはありません」

URLが間違っていました。
第2回でAIが推測して作ったURLは、実際のページと異なっていたのです。


解決策:スクレイピングでURLを取得

妙高市のホームページを確認すると、年月ごとのURLは規則的ではなく、
`/docs/12345.html` のような 不規則なアドレス になっていました。

そこで、AIエージェントにお願いしてみました。

「積雪メニュー画面のURLを渡すから、そこからリンクを読み取ってURLリストを作って」

正直、無理なお願いかな……と思っていたのですが、
AIエージェントは、メニュー画面をスクレイピングしながらURLリストを作ってくれました

これには驚きました。
まずは何でもお願いしてみるものですね。


URLリストの完成

AIが作ったリストには、いくつか抜けがありました。
そこで私が実際にページの存在を確認して、手動で補完しました。

最終的な直近5年分の完成度は以下の通りです。

| 年度 | 揃い具合 |
|------|----------|
| 令和3年度 | 11月、12月、1月、2月、3月、4月 → 6ヶ月完備 ✅ |
| 令和4年度 | ~~11月(欠損)~~、12月、1月、2月、3月、4月 → 5ヶ月 |
| 令和5年度 | 11月、12月、1月、2月、3月、4月 → 6ヶ月完備 ✅ |
| 令和6年度 | 11月、12月、1月、2月、3月、4月 → 6ヶ月完備 ✅ |
| 令和7年度 | 11月、12月、4月 → 3ヶ月(1月〜3月は今後公開予定) |

令和4年度11月のデータだけは妙高市のサイトで見つかりませんでしたが、
それ以外はほぼ完璧。これで動作確認できる状態になりました。


問題② データが抽出できない

URLリストを修正して再実行。
今度こそ……と思いきや、また別のエラーが出ました。

WARNING:__main__:データが抽出できませんでした: https://www.city.myoko.niigata.jp/docs/75741.html

URLは正しいのに、データが取れない。
HTMLの表(table)の構造が、コードの想定と違っているようです。


AIエージェントによる自動デバッグ

ここで、AIエージェント(Cursor Agent)の真価が発揮されました。

AIに「このエラーの原因を特定して修正して」とお願いすると、
自分でデバッグを始めました

驚いたのは、AIが自分でコードを書いて、自分で実行して、自分で結果を確認していた ことです。

やってくれたこと:

  1. HTMLページを取得してテーブル構造を解析する デバッグ用コードを自動作成

  2. 不足パッケージを自動インストール

  3. デバッグコードを 自分で実行 して、実際のテーブル構造を確認

  4. 「ヘッダーが2行ある」「列の順序が想定と違う」などの問題点を特定

  5. コードを修正

  6. 修正結果の動作確認用コードを作成 して、データテーブルを出力

  7. 出力結果を見て、正しくデータが取れているか 自分で検証

人間がやるデバッグの流れを、AIが全部やってくれたのです。
「確認用コード作って→実行→結果見て→直す」のサイクルを、自動で回していました。

もしAIエージェントがなかったら、
何度も何度も何度も print文を仕込んで確認していた ことでしょう。
それを全部やってくれるとは……。

話には聞いていましたが、実際に見ると感動すら覚えます。


問題③ 日付のパースエラー

修正後に再実行しても、またエラー。

AIに調べてもらうと、今度は 日付の解析(パース)に問題がある ことが判明。

妙高市のページでは、日付が「1日」「2日」のように
「日」という文字が含まれる形式 になっていました。

AIは「今度こそ確実に動くようにします」と宣言して、修正を実行。
数回のエラーを繰り返しながら、動作確認と修正を自動で繰り返してくれました。


ついに動いた!

そして、完成宣言が出ました。

streamlit run main.py


おおー!
グラフが描画されています!

  • 降雪量は 赤い折れ線グラフ

  • 積雪量は 水色の棒グラフ

要件定義で書いた通りの表示になっています。


AIエージェントからのメッセージ

お礼を言ったら、AIエージェントがこんな返事をくれました。

 🎉 おめでとうございます!グラフが表示されたとのこと、本当に良かったです!
 長い道のりでしたが、以下の問題を解決しました:
1. ✅ 新しいURL形式(/docs/xxxxx.html)への対応
2. ✅ ヘッダー行が2行ある構造への対応
3. ✅ 列の順序が交互になっている構造への対応
4. ✅ 日付に「日」という文字が含まれる問題への対応
5. ✅ --(ダブルハイフン)の欠損値処理

振り返ると、5つもの問題を解決していた んですね。
AIと一緒に歩んだデバッグの道のりでした。


感じたこと:バイブコーディングの威力

「バイブコーディング」(AIと対話しながらコードを書く手法)の威力は
色々なところで見聞きしていましたが、実際に自分で体験すると、
その能力を肌で実感できます

ちょっと感動しました。(満員の新幹線の中でなかったら、「おーっ!」と叫んでいたはず)


正直、ちょっと怖かった

一方で、正直な気持ちも書いておきます。

要所要所でAIが「確認してください」と言ってくるのですが、
その合間に、勝手にテストコードを作って、パッケージをインストールして、ターミナルで実行して…… という動きを見ていると、

「こいつ、何やってるんだ……?」

という気持ちになりました。

問題が起きるんじゃないか、という不安。
これはすぐに慣れるのだろうけど、最初は少し怖かったです。


今後の改善メモ

動作確認中に気づいたことをメモしておきます。

改善案:データのキャッシュ保存
毎回5年分のデータを読み込むと時間がかかる。
前年度分までは保存しておいて、今年度分だけ読み込んで合体する仕組みにしたい。

これは、全ての動作確認を終えてから実装します。


次回予告

今回は、アプリを動かしてグラフが表示されるところまで確認しました。

次回は、左のサイドバーで年月や地点を切り替える動作 を確認していきます。

お楽しみに。


今回のまとめ

  • 最初の実行ではエラーが出て当たり前(そこからがスタート)

  • URLリストはAIがスクレイピングで作ってくれた

  • テーブル構造の違いはAIが自動でデバッグしてくれた

  • 5つの問題を解決して、ついにグラフが表示された

  • AIエージェントの自動デバッグは、感動と少しの怖さがある


学びポイント 💡

「動かないのは当然。そこからAIと一緒にデバッグする」

AIが書いたコードは、最初から完璧には動きません。
でも、エラーが出たら AIと一緒に原因を探って直していける のが、
バイブコーディングの強みです。

「エラー=失敗」ではなく、「エラー=学びのチャンス」。
そう思えると、開発がもっと楽しくなります。


補足:AIエージェントによる主な修正箇所

このセクションでは、AIエージェントが自動で行った具体的なコード修正を記録します。

修正① ヘッダー行のスキップ(70行目付近)

新しいURL形式ではヘッダーが2行存在することが判明。

# 修正前
for row in rows[1:]:  # 最初の行はヘッダーと仮定

# 修正後
for row in rows[2:]:  # ヘッダーは2行あるためスキップ

理由: HTMLテーブルの1行目が観測所名、2行目が「降雪/積雪」の見出しになっていた。


修正② 日付パース(80行目)

日付列に「日」という文字が含まれていることが判明。

# 修正前
day = int(cols_text[0])

# 修正後
day = int(cols_text[0].replace("日", ""))

理由: `"1日"`, `"2日"` のような文字列を `int()` に直接変換できないため、`"日"` を除去してから変換。


修正③ 列インデックスの計算(87-91行目)

列の順序が想定と異なることが判明。

# 修正前(想定していた列順)
# [日, 降雪1, 降雪2, 降雪3, 積雪1, 積雪2, 積雪3]
snowfall_idx = i + 1        # 降雪量(インデックス 1, 2, 3)
snowdepth_idx = i + 4       # 積雪量(インデックス 4, 5, 6)

# 修正後(実際の列順)
# [日, 降雪1, 積雪1, 降雪2, 積雪2, 降雪3, 積雪3]
snowfall_idx = i * 2 + 1    # 降雪量(インデックス 1, 3, 5)
snowdepth_idx = i * 2 + 2   # 積雪量(インデックス 2, 4, 6)

理由: 実際のHTMLテーブルは、降雪と積雪が交互に配置されていた。


修正④ 欠損値パターンの追加(96-97行目)

`"--"` (ダブルハイフン) も欠損値として扱う必要があることが判明。

# 修正前
snowfall_cm = None if snowfall == "-" or snowfall == "" else float(snowfall)
snowdepth_cm = None if snowdepth == "-" or snowdepth == "" else float(snowdepth)

# 修正後
snowfall_cm = None if snowfall in ["-", "--", ""] else float(snowfall)
snowdepth_cm = None if snowdepth in ["-", "--", ""] else float(snowdepth)

理由: 妙高市のサイトでは、欠損値を `"-"` だけでなく `"--"` でも表現していた。


デバッグの流れ

  1. HTMLを直接確認 → テーブル構造を把握

  2. デバッグスクリプト作成 → 実際のデータを確認

  3. 問題点を特定 → 上記4つの修正を実施

  4. テスト実行 → データ抽出成功(93行取得)

  5. Streamlit起動 → グラフ表示成功 🎉


学んだこと

  • HTMLの構造は目視で確認するまでわからない

  • エラーメッセージから原因を推測する力が重要

  • 小さなテストスクリプトで素早く検証

  • AIは仮定が間違っていても、データを見せれば修正してくれる


続く


書いている人について

投稿者の紹介です。
noteでは、次の3つを軸に、日々の学びや記録を残しています。

  • Python・AI
    趣味の開発で試したこと、つまずいた点、学びの記録

  • 健康・からだ
    自分自身の不調や気づきをもとにした、学びと養生の記録

  • 生まれ故郷への想い
    新潟・妙高(小局)にまつわる歴史や記憶を残すための記録

👉 マイペースで続けている記録はこちら

👉アプリ開発に関するマガジン

いいなと思ったら応援しよう!