Web からの抽出、メディア処理、ストレージ形式は、バイト列を不透明なテキストとして扱うのではなく、構造化された表現を扱うことで、いずれも利点を得られます。
クエリの前に HTML を解析する #
XPath は生の HTML 文字列ではなく、ドキュメントツリーに対して動作します。Web コンテンツを HTML パーサーで解析してから、生成された DOM に対してクエリを実行してください。ブラウザーの DOM、HTML パーサー、XML パーサーは不正なマークアップを異なる方法で修復する可能性があるため、テストと本番では同じ種類のパーサーを使用してください。
ドキュメントの作成者が安定した ID やクラスを管理している場合、CSS セレクターは簡潔です。XPath はテキストを検索し、マッチしたノードを基準に移動できるため、ドキュメント分析やクローラーに適しています。
//article//h2
//a[@rel='next']/@href
//table//tr[td]
//*[contains(concat(' ', normalize-space(@class), ' '), ' product ')]
//h2[normalize-space(.)='Specifications']/following-sibling::ul[1]/li// は子孫を検索し、@name は属性を選択し、述語はノード集合をフィルタリングします。また、following-sibling のような軸は、選択したノードを起点に移動します。クラス式は 1 つのトークンにマッチするため、product を必要とするクエリで product-card に誤ってマッチすることを防げます。
構造が契約として保証されていない限り、//div[7] のような位置ベースのパスは避けてください。意味的な要素、アクセシブルな名前、見出し、リンク関係、または安定したデータ属性を基準にしてください。抽出した相対 URL はドキュメントのベースに対して解決し、robots ポリシーと利用規約を尊重し、リクエストをレート制限し、抽出したコンテンツを信頼できない入力として扱ってください。
ブラウザーコードで XPath を評価する #
ブラウザーは document.evaluate を通じて XPath を公開します。明示的なコンテキストノードを指定し、呼び出し元に必要な結果形式を要求してください。
const result = document.evaluate(
".//a[normalize-space(.)='Download']/@href",
container,
null,
XPathResult.STRING_TYPE,
null,
);
const href = result.stringValue;複数のノードには、順序付きスナップショットまたはイテレーターを使用します。
const result = document.evaluate(
".//tr[td]",
table,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null,
);
for (let index = 0; index < result.snapshotLength; index += 1) {
const row = result.snapshotItem(index);
// DOM が安定している間に row を処理する。
}関連する DOM が変更されると、イテレーターは無効になります。作成者が管理し、テスト可能なアプリケーションではロケーター API の方が適しています。XPath は、自動化タスクからドキュメント構造に影響を与えられない場合に有用です。
Curl で複数のリソースを取得する #
curl は 1 回の呼び出しで複数の URL を受け付けます。出力テンプレートでは、URL の glob コンポーネントに対して #1、#2 以降のプレースホルダーを使用できます。
curl --fail --location --remote-name \
'https://example.test/images/page-[001-010].jpg'--fail は HTTP ステータスによる失敗を非成功として扱い、--location は HTTP リダイレクトに従い、--remote-name はリモートのファイル名を使用します。サーバーのファイル名が適切でない場合は、明示的な --output テンプレートを設定してください。
curl --fail --location \
'https://example.test/page/[0001-0217].jp2' \
--output 'page-#1.jp2'SOCKS プロキシ経由で DNS を解決する必要がある場合は、--proxy socks5h://localhost:1080 を使用します。h には意味があります。socks5 はターゲットをローカルで解決しますが、socks5h はホスト名をプロキシに送信します。
--insecure で証明書名の不一致を回避しないでください。不一致は、要求したホスト名が証明書の Subject Alternative Names に含まれていないことを意味します。URL またはサーバー設定を修正してから再試行してください。curl -v は TLS と HTTP の交換を診断用に表示します。出力を共有する前に、認証ヘッダーと Cookie を削除してください。
FFmpeg でメディアを処理する #
FFmpeg はコンテナ形式、ストリーム、コーデック、フィルターを分離して扱います。1 つのファイルには、映像、音声、字幕、データ、添付ファイルのストリームを含められます。ファイル名の拡張子だけでは、コーデック設定を特定できません。
コマンドを選ぶ前に入力を調べてください。
ffprobe -hide_banner -show_format -show_streams input.mkv互換性のあるストリームを再エンコードせずにコピーします。
ffmpeg -i input.mkv -map 0:v:0 -map 0:a? -c copy output.mkv-map はストリームを明示的に選択します。末尾の ? により、音声ストリームが任意になり、存在しなくてもエラーになりません。ストリームコピーはエンコード済みパケットを保持するため、解像度、フレームレート、音声サンプリング、コーデックを変更できません。
変換または互換性変換が必要な場合は再エンコードします。
ffmpeg -i input.mov \
-vf 'scale=1920:-2:flags=lanczos,format=yuv420p' \
-c:v libx264 -crf 20 -preset medium \
-c:a aac -b:a 192k \
output.mp4-2 は、スケールフィルターに偶数の寸法を選択させます。これは、多くのサブサンプリングされたピクセル形式で必要です。-crf は固定品質エンコーダーの品質を制御します。値を小さくすると、より高い品質と大きな出力が要求されます。コーデックオプションの意味はエンコーダーごとに異なるため、再現可能なメディアパイプラインではコマンドとエンコーダーのバージョンを記録してください。
フィルターグラフは音声と映像の操作を組み合わせます。
ffmpeg -i video.mp4 -i narration.wav \
-filter_complex '[0:a][1:a]amix=inputs=2:duration=first[a]' \
-map 0:v:0 -map '[a]' -c:v copy -c:a aac mixed.mp4影響を与える -i より前に入力オプションを置き、影響を与える入力の後に出力オプションを置いてください。タイムスタンプは意図を持って保持します。-i より前の -ss は近くのキーフレームへ高速にシークし、-i より後の -ss は正確な位置までデコードします。代表的な入力でシーク動作をテストしてください。
磁気ディスクのブロックをアドレス指定する #
セクターはアドレス指定可能なデバイス単位です。ファイルシステムブロックはファイルシステムの割り当て単位または I/O 単位であり、1 つ以上のセクターにまたがる場合があります。現代のドライブは、512 バイトの論理セクター、4096 バイトの論理セクター、または 4 KiB の物理セクター上での 512 バイトエミュレーションを公開します。
シリンダー・ヘッド・セクター(CHS)アドレス指定は、ディスクのジオメトリをモデル化していました。
- シリンダーは、すべてのプラッター面を横断する 1 つの半径を選択しました。
- ヘッドは面を選択し、その半径にあるトラックを指定しました。
- セクターは、トラック上のデバイスブロックを選択しました。
従来の BIOS CHS インターフェースは、最大 1024 シリンダー、255 ヘッド、1 トラックあたり 63 セクターをエンコードしました。セクターあたり 512 バイトでは、この制限は 8,422,686,720 バイト(約 7.84 GiB)です。後にドライブは変換後のジオメトリを報告するようになり、CHS 値は物理プラッターを表さなくなりました。さらに、ゾーンビット記録により、外周トラックには内周トラックより多くの物理セクターが含まれます。
論理ブロックアドレス指定(LBA)は、ジオメトリを 0 から始まる線形セクター番号に置き換えます。ファームウェアは内部で LBA を物理位置に変換します。古い CHS シリンダーに基づくパーティション方式では現代のデバイスジオメトリを表現できないため、ツールはセクター、バイト、アライメントを別々に表示すべきです。
MBR と GPT のパーティション方式を選択する #
マスターブートレコードは論理ブロック 0 を占有します。最後の 2 バイトは 0x55AA で、その直前にあるパーティションテーブルには 16 バイトのプライマリエントリが 4 つあります。エントリには、ステータスバイト、従来の CHS フィールド、タイプバイト、開始 LBA、セクター数が含まれます。
MBR の 4 エントリ制限から、拡張パーティション方式が生まれました。1 つのプライマリエントリが Extended Boot Record のチェーンを指し、各 EBR は 1 つの論理パーティションと次の EBR へのリンクを記述します。このチェーンは歴史的なレイアウト方式であり、ファイルシステムの機能ではありません。MBR のブートストラップコードは、パーティションのボリュームブートレコードを選択するか、そこへ制御を移します。ファイルシステムを定義するわけではありません。
GUID パーティションテーブル(GPT)は LBA を使用し、4 パーティション制限を取り除きます。
| 位置 | GPT 構造 |
|---|---|
| LBA 0 | 保護 MBR。MBR 専用ツールがディスクを空として扱うことを防ぐ |
| LBA 1 | プライマリ GPT ヘッダー |
| 後続の LBA | パーティションエントリ配列 |
| 最終 LBA | バックアップパーティションエントリ配列とバックアップヘッダー |
GPT ヘッダーには、使用可能な LBA 範囲、ディスク GUID、パーティションエントリのレイアウト、CRC32 チェックサムが記録されます。各パーティションエントリには、タイプ GUID、固有 GUID、最初と最後の LBA、属性フラグ、UTF-16LE 名が含まれます。修復を試みる前に、ヘッダーとエントリ配列の両方のチェックサムを検証してください。ディスク末尾のバックアップ GPT は、既知のデバイスサイズと有効なチェックサムに一致する場合にのみ復旧を支援します。
プラットフォームが別の要件を指定していない限り、パーティションは 1 MiB 境界にアラインしてください。このアラインメントは、旧式の CHS 境界に依存せず、一般的な物理セクターおよび RAID ストライプのレイアウトと整合します。
FAT ボリューム構造を読む #
FAT12、FAT16、FAT32 は、クラスタごとの割り当てテーブルを格納します。名前が示すのは FAT エントリの幅であり、セクターサイズではありません。ボリュームのブートセクターには BIOS パラメータブロック(BPB)が含まれ、セクターあたりのバイト数、クラスタあたりのセクター数、予約セクター数、FAT 数、ルートディレクトリ情報、総セクター数などが記録されます。
FAT12 と FAT16 では、ルートディレクトリは FAT の直後に固定配置されます。FAT32 では、ルートは通常のクラスタチェーンとして格納され、初期クラスタは拡張 BPB に記録されます。ディレクトリエントリは、短い 8.3 名、属性、最初のクラスタ、サイズ、タイムスタンプをファイルに対応付けます。長いファイル名のエントリは短いエントリの前に置かれ、チェックサム付きの UTF-16 名の断片を格納します。
ファイルデータはクラスタチェーンです。
- ディレクトリエントリから最初のクラスタを特定します。
- クラスタのデータを読み取ります。
- そのクラスタの FAT エントリを読み取ります。
- end-of-chain マーカーが現れるまで続けます。
空き、予約済み、不良、end-of-chain の値は形式ごとに異なります。ボリュームが FAT12、FAT16、FAT32 のいずれであるかを判断する前に、BPB から導出したクラスタ数を検証してください。ブートセクター内のテキストラベルは信頼できる根拠ではありません。FAT にはジャーナルがないため、中断されたメタデータ更新によって、修復ユーティリティが調整すべき失われたチェーンや相互リンクされたクラスタが残る可能性があります。
ストレージスタック内で ATA を位置付ける #
IDE は ATA ディスクインターフェースを PC に統合するための名称でした。パラレル ATA(PATA)は 40 または 80 芯のリボンケーブルで ATA コマンドを伝送し、プライマリおよびセカンダリチャネルとデバイス選択方式を公開しました。シリアル ATA(SATA)は ATA コマンドモデルを維持しながら、物理トランスポートをポイントツーポイントのシリアルリンクに置き換えました。
ATA は IDENTIFY DEVICE コマンドによってドライブと容量を識別します。コマンドはタスクファイルレジスターまたは DMA エンジンを介して論理セクターを転送し、転送モードとエラー処理はコントローラー、ケーブル、ホストアダプター、デバイスによって決まります。ATAPI は光学ドライブなどのデバイス向けに ATA トランスポート上でパケットコマンドを使用しました。一方、他の多くのストレージトランスポートでは SCSI コマンドセットが主流です。
ドライブが報告する論理 CHS フィールドを物理ジオメトリとして解釈しないでください。デバイスとオペレーティングシステムが報告する LBA 容量および論理/物理セクターサイズ情報を使用してください。
光学メディアを保存・読み取る #
光学メディアは螺旋状のトラックを記録します。集束レーザーとフォトダイオードが反射光の変化を測定します。プレス CD では、ピットとランドがポリカーボネートに成形されます。深さの違いにより、反射スポットの一部で破壊的干渉が生じるため、信号は遷移時に変化します。ピットは直接 1 つのバイナリ値に対応するわけではなく、遷移タイミングはランレングス制限付きチャネル符号化と誤り訂正によって符号化されます。
CD は近赤外レーザーと 1.6 µm のトラックピッチを使用します。DVD と Blu-ray はより短い波長と小さいピッチを使用し、容量を増やします。線速度一定方式では、ピックアップが外側へ移動するにつれて角速度を下げることでデータレートを一定に保ちます。後発の形式では別の回転方式を使用できます。
プレスディスクは読み取り専用です。記録可能メディアは色素または無機記録層を変化させ、書き換え可能メディアは相変化合金を使用します。CD、DVD、Blu-ray の仕様は物理形式、変調、誤り訂正、論理形式を規定します。ファイルイメージ形式だけでは、ディスクの物理的な記録方法は規定されません。
ISO 9660 は High Sierra 形式から派生した読み取り専用光ディスクファイルシステムです。順次レイアウトとクロスプラットフォーム交換を重視します。元の命名規則とディレクトリ制約から、POSIX メタデータ向けの Rock Ridge や、より長い Unicode 指向の名前向けの Joliet などの拡張が生まれました。El Torito は起動可能な光学メディア向けのブートレコードを追加します。
UDF は、多くの DVD および Blu-ray 用途で ISO 9660 に取って代わります。記述子ベースのレイアウトは増分更新をサポートし、書き換え可能メディアや一度だけ書き込めるメディアをより自然に表現できます。.iso ファイルはセクターイメージであり、ISO 9660、UDF、またはハイブリッドレイアウトを含められます。
有用な検査ツールには、util-linux の isosize、および iso-info や iso-read などの libcdio ユーティリティがあります。信頼できないイメージをマウントまたは検査する際は、信頼できないアーカイブと同じ注意を払ってください。ファイル名やメタデータは悪意のある入力になり得るためです。
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)