ここまで、取得の作法から具体的なデータ源まで扱ってきました。振り返ると、個別の技術より、いくつかの判断のほうが結果を左右していたと感じます。この回では、繰り返し出てきた考え方をまとめます。
1. 受け取ったものは、そのまま残す
最も何度も出てきたのがこれです。を持ち、整形は別の工程にする。要件が変わっても取り直さずに済み、解釈を間違えてもやり直せます。
判断の基準は「取り直せるか」の一点でした。在庫、順位、板情報、構成銘柄。その時点の値しか返さないものは、残さなければ永久に失われます。保存の費用より、取り直せない損失のほうが高くつきます。
2. 例外が出ない失敗こそ危ない
取得が壊れるとき、たいてい例外は出ません。で少しだけ取りこぼす。文字コードを取り違えて化ける。がずれて日付が1日動く。どれも「成功」として通過します。
だから検算を入れます。件数を数え、前回と比べ、合計と突き合わせる。取得の直後に数行を足すだけで、静かな失敗のほとんどは捕まえられます。
| 症状 | 原因 | 気づき方 |
|---|---|---|
| 件数が少し足りない | ページングのずれ | 総数と突き合わせる |
| 日付が1日ずれる | タイムゾーン | 最初と最後の時刻を見る |
| 先頭ゼロが消える | CSV で往復させた | 型を明示するか Parquet を使う |
| ある列だけ全部空 | 配信元の仕様変更 | 欠損率を前回と比べる |
| 数字が後から変わる | 速報値から確報値へ | 公表時点を一緒に残す |
def fetch_once(job, target_date): """取得 1 回ぶんの骨格。要点は「残す」「確かめる」「再開できる」の 3 つ。""" # 1. 取得(タイムアウト・リトライ・名乗りは呼び出し先で担保) payload = job.fetch(target_date)
# 2. 受け取ったものをそのまま残す(整形前) raw_path = save_raw(job.name, target_date, payload)
# 3. 形を確かめてから整形する(違えばここで止まる) records = job.parse(payload)
# 4. 冪等に書く(同じ日を 2 回処理しても結果は同じ) job.store(records, target_date)
# 5. 検算する(件数・期間・欠損率を前回と比べる) stats = job.verify(target_date)
# 6. 成功した記録を残す(動いた形跡) mark_success(job.name) return raw_path, stats3. 相手がいることを忘れない
取得の相手は、無償で公開している配信元だったり、業務で使われている社内の仕組みだったりします。速く取ることより、取り続けられることのほうが大事でした。
を守り、間隔を空け、名乗りを書く。遮断されれば取得そのものができなくなりますし、社内であれば業務が止まります。遠慮する側に倒すのが結局は近道でした。
4. 始めた時点で運用が始まる
取得は書いて終わりではありません。定期実行に載せた瞬間から、壊れたときに誰かが直す対象になります。だから、再開できること、失敗に気づけること、何がどこから来ているかが分かることが要ります。
そして、増やすだけでなく止めることも運用のうちです。使われていない取得は、放っておくと必ず溜まります。
そのために必要なものも、振り返ると多くありません。を持ち、のある書き方をして、の口を用意しておく。これだけで、失敗しても「もう一度実行する」で片が付くようになります。
5. 取らないという選択肢
何度か触れましたが、取得しないと決めるのも判断のひとつです。手作業で月に一度ダウンロードするほうが、壊れ続ける自動化より安く済むことがあります。過去にさかのぼれないと分かった時点で、その分析をやらないと決めるほうが誠実なこともあります。
自動化の目的は手間を減らすことであって、自動化そのものではありません。作る前に、作らない場合と比べてください。
取らない判断をした場合も、判断した記録は残してください。「この理由で自動化しないと決めた」が残っていないと、半年後に別の誰かが同じ検討を最初からやり直します。
QUESTIONS = [ "取り直せるデータか(取り直せないなら、生のまま残す設計が要る)", "壊れたときに誰が困るか(分からないなら、そもそも要るのか)", "更新の頻度はどれくらいか(相手の更新より速く取りに行っても無駄)", "止めるときにどうするか(止め方が無いものは、いずれ放置される)", "手作業と比べて本当に安いか(月1回なら手作業のほうが安いこともある)",]
def ready_to_build(answers: dict[str, str]) -> list[str]: """答えが埋まっていない項目を返す。空なら着手してよい。""" return [q for q in QUESTIONS if not answers.get(q, "").strip()]ここから先
扱えていない題材はまだ多く残っています。ストリーミングでの受信、大量データの並列取得、有償データの契約まわり、社内の権限設計との兼ね合い。どれも実務では出てくる話です。
この連載は、読者のリアクションに応じて随時追加していきます。「ここが分からない」「この題材を扱ってほしい」があれば、記事末尾のボタンから知らせてください。実際に困っている箇所から書くほうが、役に立つものになります。
取得したデータをどう整えるかは 前処理の現場、どこに置いてどう配るかは 壊れないデータ基盤の作り方 で扱っています。あわせて読んでいただければと思います。
ここまで扱ってきた内容は、どれも派手さのないものばかりです。ただ、取得が壊れる場面を思い返すと、原因はたいていこの範囲に収まっていました。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。