制限付き環境で巨大リモートデータを取り切る回避術

制限付き環境で巨大リモートデータを取り切る回避術

リモートにある大きなデータを、サンドボックス越しに取りに行く。

たったそれだけのことが、どうしても最後まで通らない。

CSVを叩けば「binary」と返って中身が読めず、ソースを変えれば文字化けし、ようやく素直なCSVを見つけても途中でぷつりと途切れる。

私も先日、ある公開データの頻度集計をする下ごしらえで、この「取得が全部詰まる」状況に正面からぶつかりました。

同じように、外部データを集めようとして取得サイズや文字コードの壁に何度も跳ね返された経験は、あなたにもないでしょうか。

前提(最小限):制限付きサンドボックスでの外部取得とは

はじめに、今回の作業環境を一度だけ整理しておきます。

私が動いていたのは、シェルが許可ドメイン以外へ出られないサンドボックスでした。

pip install(PyPI)なら通るのに、任意サイトへの curl はことごとくHTTP 000で接続不能。

外部へ出られる手段は、実質「Web取得ツール一本」だけに絞られていました。

やっかいなのは、このツールが二つの癖を抱えている点です。

ひとつは、応答が約51,742字を超えると、中身がまるごとファイルへ自動保存されるという挙動。

もうひとつは、きれいな数値CSVでも約1,284行(およそ4〜5万字)で、先頭から機械的に切り捨てられる制約です。

この「頭から切る」性質が、のちのちボディブローのように効いてきました。

詰まりポイント:content-type・文字コード・行数上限の三重苦

最初にぶつかったのは、「読める形で返ってこない」という壁でした。

公式CSVが「binary」に化ける

素直に考えれば、公式が配布しているCSVを取れば済む話です。

ところが、その公式CSVはcharset=Shift_JISかつ表示用に整形されていて、取得すると文字化けし、肝心の数値を機械抽出できませんでした。

ならばと別ソースの生CSVに切り替えると、今度はcontent-typeが application/octet-stream で返ってきます。

この瞬間、取得ツールは中身を「binary data」と判断し、テキストとして開いてくれないのです。

つまり、ファイルの中身ではなく、サーバーが付けたcontent-typeひとつで読める・読めないが決まってしまう

ここが、最初の落とし穴でした。

行数上限という見えない天井

content-typeを乗り越えても、それで終わりではありません。

ようやくUTF-8のきれいなCSVにたどり着いても、常に先頭のおよそ1,284行しか返らず、中盤から最新のデータがまるごと欠けてしまう

全部で二千件を超える履歴のうち、頭の一部しか手に入らないわけです。

「データはそこにあるのに、手が届かない」と、もどかしさばかりが募りました。

効いた回避策:CDN・GitHub API・保存ファイル化

制限付き環境での取得の壁(content-typeによるbinary扱い・取得サイズ上限)と、CDN化・APIのbase64・保存ファイル化という3つの回避策の図解

ここからが、実際に効いた三つの「逃がし方」です。

CDNで content-type を「化けさせる」

最初のブレイクスルーは、jsDelivr というGitHub向けCDNでした。

同じCSVでも、raw.githubusercontent.com 経由だと octet-stream で返るのに、CDN経由なら拡張子から text/csv を付けて返してくれる。

jsDelivr は /gh/ユーザー名/リポジトリ名/ファイルパス の形式で、GitHub上のファイルをそのまま配信します(jsDelivr 公式ドキュメント)。

Documentation - jsDelivr

つまり、中身に一切手を触れず、URLを差し替えるだけで「読める形」に化けさせられたわけです。

小さいファイルは API の base64 で丸ごと取る

二つ目は、GitHub の contents API を使う手でした。

このAPIは、1MB以下のファイルなら content フィールドに base64 で中身をまるごと返す仕様です(GitHub REST API(リポジトリコンテンツ))。

REST API endpoints for repository contents - GitHub Docs

2.2KBほどの小さな設定ファイルは、これで完全に取り切れました。

ただし、ここにも小さな罠がひそんでいます。

73KBのCSVをbase64にすると約10万字へ膨らみ、今度はGitHubではなく取得ツール側の文字数上限に引っかかって、頭で切られてしまいました。

base64は元データをおよそ1.33倍に太らせるので、「APIの制限」より先に「取得側の制限」に当たる場合がある、と覚えておくと安全でしょう。

大容量は「保存ファイル化」に逃がす

三つ目は、上限を逆手に取る発想でした。

前提で触れたとおり、取得ツールは応答が大きすぎると中身をファイルへ自動保存します。

これは一見デメリットに見えますが、保存さえされてしまえば、あとはローカルのシェルで全文を落ち着いて処理できる

だからこそ、あえて情報密度の高いJSONを取りにいって保存ファイル化させ、そこからローカルで料理する段取りに切り替えました。

さらに、降順(新しい順)に並んだソースを選ぶと、「頭から切る」性質が逆に「最新から取れる」利点へ反転します。

制約は、見る角度を変えれば味方になる。

教訓:再利用できる判断フロー

三度も壁にぶつかって、ようやく再利用できる「型」が見えてきました。

一番の学びは、手を出す順番でした。

まず content-type と取得上限を疑い、CDN化・APIのbase64・保存ファイル化という三手で切り分ける

読めないときは、中身より先にサーバーが付けたcontent-typeを確認し、化けていればCDNやプロキシでテキスト化する。

全部が入りきらないときは、原因が行数なのか、文字数なのか、トークン数なのかを見極める。

小さいファイルはAPIのbase64、大きいファイルは保存ファイル化、最新だけ要るなら降順ソース、と手札を対応づけておくと迷いません。

そしてもうひとつ、地味だけれど大事な割り切りがあります。

最終的に欲しいのが集計値だけなら、連続したブロックが多少欠けても、取れた範囲の標本で目的を果たせることが多い

完璧に全部を取ることと、目的を果たすことは、必ずしも同じではないのです。

最後に

今回は、ある公開データの集計という具体例で書きましたが、起きていたことはもっと一般的でした。

リモートの大きなデータが途中で切れる、あるいは読めない。

そんなときは、まず content-type と「何の上限に当たっているのか」を疑うところから始めると、ぐっと打ち手が見えてきます。

中身をいじらずにCDNで化けさせる、APIのbase64で丸ごと取る、大きすぎるものは保存ファイルに逃がす

この三つの引き出しは、サンドボックスに限らず、ブラウザからローカルAPIを叩くときにも、CIの中で外部データを取るときにも効いてくるはずです。

制約にぶつかったら、力技で押し通す前に「どの壁に当たっているか」を見極める。

その一手間が、遠回りに見えて一番の近道だと、私はあらためて感じています。

以上です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA