ID

InitDataExtractor

Scratch.INIT_DATA を自動抽出して Scratch ブロックで扱えるようにする拡張機能の開発者向けドキュメント。

概要

InitDataExtractorは、指定したウェブページのHTMLからScratchがページに埋め込む Scratch.INIT_DATA(PROFILE / CLASSROOM 等)を抽出し、Scratch拡張のブロックでアクセスできるようにします。
従来の「scriptタグ全文を手入力」方式をやめ、URLを渡すだけで /html/head/script[7](7番目の<script>)を自動抽出して解析します。

主な特徴
  • URLを指定するだけでHTMLを取得して解析します。
  • 抽出対象はデフォルトで /html/head/script[7](7番目の<script>)です。変更可能。
  • 取得したデータは PROFILE / CLASSROOM として保存され、ブロックから参照できます。
  • JSONパスはドット区切りではなく、スラッシュ区切り(例: model/username)を採用。配列インデックスは1ベース表記から0ベースへ自動変換されます(例: array[1]array/0)。

導入方法

拡張機能ファイル(例: initdata-extractor.js)を用意し、Scratch拡張の読み込み方法に従って登録してください。開発時はブラウザのコンソールで動作確認してください。

// 例: 拡張の登録(簡略)
Scratch.extensions.register(new InitDataExtractor());

ブロック一覧

ブロック種類説明
URL [URL] からINIT_DATAを読み込むコマンド指定したURLをfetchして、/html/head/script[7] を抽出、解析して内部ストアに保存します。
[SECTION] 全体をJSONで取得レポーターPROFILE または CLASSROOM の全データをJSON文字列で返します。
[SECTION] の [PATH] を取得レポータースラッシュ区切りパスで指定したフィールドを返します(例: model/username)。配列は0ベースでアクセスされます。

使い方(例)

以下は典型的な手順です。

  1. ブロックで URL を指定して読み込む。
  2. PROFILE 全体をJSONで取得するか、個別フィールドを参照する。
例: Griffpatch のプロフィール(仮)を取得する流れ
// Scratch ブロック的な擬似コード
URL に "https://scratch.mit.edu/users/griffpatch/" を指定して実行
PROFILE 全体をJSONで取得 -> { model: {...}, related_counts: {...}, featuredProject: {...} }
PROFILE の model/username を取得 -> "griffpatch"

HTML生データの例(解析対象のスクリプト断片):

<script>
Scratch.INIT_DATA.PROFILE = {
  model: { username: 'griffpatch', id: 12345 },
  related_counts: { followers: 10000 },
  featuredProject: { id: 999, title: 'Cool' },
  featuredProjectLabel: 'Featured Project'
};
</script>

JSONPath(スラッシュ記法)

当拡張ではドット区切りではなく、以下のような スラッシュ区切り を使用します。

  • model/usernamemodel.username と同じ
  • 配列の指定は元のHTMLが array[1] のように1ベースで表記されている場合、内部参照は0ベースへ自動変換されます。例: test.array[1].idtest/array/0/id
変換ルール(例)
// 元のドット表記(HTML内表記)
test.array[1].id

// 当拡張でのスラッシュ表記
test/array/0/id

注意: スラッシュ区切りのパーツに角括弧 [n] を含める必要はありません。配列を指定する場合は、変換後の数値インデックスを直接書きます。

スクリプト選択ルール

デフォルトでは、HTMLドキュメントから全ての<script>タグを順に列挙し、7番目(XPath 的には /html/head/script[7]を抽出対象とします。

実装上は正規表現で<script>タグを列挙し、インデックス 6(0始まり)を使います。見つからない場合はエラーになります。

例外とカスタマイズ:

  • ページ構造が変わる可能性があるため、拡張側で"スクリプト番号"を指定できるオプションを提供することを推奨します。
  • 将来的には、特定のスクリプト内にある Scratch.INIT_DATA を検出するためのより堅牢なロジック(例: 正規表現で Scratch\.INIT_DATA の有無を確認)が望ましいです。

エラーハンドリング

主なエラーと対処法:

エラー原因対処
7番目の<script>が見つからないページにスクリプトが少ないか構造が違うスクリプト番号を変更する、もしくはより一般的な検出ロジックを使う
Scratch.INIT_DATA.SECTION が見つからない対象ページに当該セクションが無い対象ページを確認、SECTION名を誤っていないかチェック
fetch による取得失敗ネットワークエラー、CORS制限などCORS対策が必要。開発はローカルプロキシかサーバー経由で行うと良い

拡張方法・設定

改良ポイントと実装メモ:

  • スクリプト番号をブロック引数で指定できるようにする(推奨)。
  • 抽出対象の検出を、Scratch.INIT_DATA の存在でフィルタする。正規表現 /Scratch\.INIT_DATA\./ を使う。
  • より厳密にJavaScriptオブジェクトをパースしたい場合は、安全な JS パーサ(AST)を導入することを検討する。純正の eval はセキュリティリスクがあるため避ける。
// 例: スクリプト番号を指定するブロック
// setSourceFromUrl(url, scriptIndex = 7)

FAQ

Q. なぜ script[7] を使うの?
A. 実装当初の観察で、ScratchサイトのINIT_DATAは7番目のスクリプトに配置されることが多かったため。だがこれは確約ではなく、将来的な壊れやすさがあるため設定可能にするのが望ましい。

Q. CORSの問題が出る場合は?
A. ブラウザの直接fetchではCORSでブロックされる可能性が高い。開発時は自前のプロキシを使うか、サーバーサイドで取得してからクライアントに渡す形が現実的。