Web 擷取、媒體處理和儲存格式都受益於使用結構化表示,而不是將位元組視為不透明的文字。
查詢前先解析 HTML #
XPath 作用於文件樹,而不是原始 HTML 字串。使用 HTML 解析器解析 Web 內容,然後查詢產生的 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 等軸則從選取的節點開始導覽。類別運算式只比對一個 token,因此對於要求比對 product 的查詢,不會意外比對到 product-card。
除非結構已被契約固定,否則應避免使用 //div[7] 這類位置路徑。應錨定於語意元素、可存取名稱、標題、連結關係或穩定的資料屬性。將擷取出的相對 URL 解析為相對於文件基底的 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 可以在一次呼叫中接受多個 URL。輸出範本可以使用 #1、#2 以及後續預留位置表示 URL glob 元件:
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 將容器格式、串流、編解碼器和濾鏡分開處理。一個檔案可以包含視訊、音訊、字幕、資料和附件串流;檔名副檔名無法識別編解碼器設定。
選擇指令前先檢查輸入:
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 單位,可以跨越一個或多個磁區。現代磁碟提供 512 位元組邏輯磁區、4096 位元組邏輯磁區,或在 4 KiB 實體磁區上提供 512 位元組模擬。
柱面-磁頭-磁區(CHS)編址對磁碟幾何結構進行建模:
- 柱面在所有碟片表面上選取同一個半徑。
- 磁頭選取一個表面,從而得到該半徑處的一條磁軌。
- 磁區選取磁軌上的一個裝置區塊。
傳統 BIOS CHS 介面最多編碼 1024 個柱面、255 個磁頭和每磁軌 63 個磁區。每個磁區 512 位元組時,該限制為 8,422,686,720 位元組(約 7.84 GiB)。後來磁碟開始回報轉換後的幾何結構,因此 CHS 值不再描述實體碟片。區域位元記錄也確保外圈磁軌包含的實體磁區多於內圈磁軌。
邏輯區塊定址(LBA)以從零開始的線性磁區編號取代幾何結構。韌體在內部將 LBA 轉換為實體位置。工具應分別顯示磁區、位元組和對齊方式,因為基於舊式 CHS 柱面的分割區慣例無法表達現代裝置幾何結構。
選擇 MBR 或 GPT 分割區方式 #
主開機記錄佔用邏輯區塊 0。其最後兩個位元組是 0x55AA;前面的分割區表包含四個 16 位元組的主要項目。每個項目包含狀態位元組、舊式 CHS 欄位、類型位元組、起始 LBA 和磁區數。
MBR 的四項限制促成了延伸分割區慣例。一個主要項目指向 Extended Boot Record 鏈,每個 EBR 描述一個邏輯分割區以及指向下一個 EBR 的連結。該鏈是歷史性的配置慣例,而不是檔案系統功能。MBR 中的啟動程式碼會選取分割區的磁碟區啟動記錄,或將控制權轉移給它;它不定義檔案系統。
GUID 分割區表(GPT)使用 LBA,並移除四分割區限制:
| 位置 | GPT 結構 |
|---|---|
| LBA 0 | 保護性 MBR,防止僅支援 MBR 的工具將磁碟視為空磁碟 |
| LBA 1 | 主要 GPT 標頭 |
| 後續 LBA | 分割區項目陣列 |
| 最後 LBA | 備份分割區項目陣列和備份標頭 |
GPT 標頭記錄可用 LBA 範圍、磁碟 GUID、分割區項目配置和 CRC32 檢查碼。每個分割區項目包含類型 GUID、唯一 GUID、第一個和最後一個 LBA、屬性旗標以及 UTF-16LE 名稱。嘗試修復前,請驗證標頭和項目陣列的檢查碼。只有當磁碟末端的備份 GPT 與已知裝置大小一致且檢查碼有效時,它才支援復原。
除非平台指定其他要求,否則請將分割區對齊至 1 MiB 邊界。這種對齊方式相容於常見的實體磁區和 RAID 條帶配置,且不依賴過時的 CHS 邊界。
讀取 FAT 磁碟區結構 #
FAT12、FAT16 和 FAT32 儲存每個叢集的配置表。名稱表示 FAT 項目的寬度,而不是磁區大小。磁碟區的開機磁區包含 BIOS 參數區塊(BPB),其中包括每磁區位元組數、每叢集磁區數、保留磁區數、FAT 數量、根目錄資訊和總磁區數。
在 FAT12 和 FAT16 中,根目錄固定位於 FAT 之後。FAT32 將根目錄作為一般叢集鏈儲存,其初始叢集記錄在延伸 BPB 中。目錄項目將短 8.3 名稱、屬性、第一個叢集、大小和時間戳記對應至檔案。長檔名項目位於短項目前方,並使用檢查碼儲存 UTF-16 名稱片段。
檔案資料是一條叢集鏈:
- 從目錄項目定位第一個叢集。
- 讀取該叢集的資料。
- 讀取該叢集的 FAT 項目。
- 持續讀取,直到出現鏈結結束標記。
空閒、保留、不良和鏈結結束值取決於格式。在判斷磁碟區是 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,凹坑和平台被模壓在聚碳酸酯中;由於深度差異會在反射光斑的部分區域產生破壞性干涉,訊號會在轉換處發生變化。凹坑不會直接代表一個二進位值,轉換時序則透過游程長度受限的通道編碼和錯誤更正進行編碼。
CD 使用近紅外線雷射和 1.6 µm 的軌道間距。DVD 和 Blu-ray 使用較短的波長和較小的間距,從而提高容量。恆定線速度會在讀取頭向外移動時降低角速度,以維持穩定的資料速率;後來的格式可以使用其他旋轉策略。
壓製光碟是唯讀的。可記錄媒體會改變染料或無機記錄層,而可重寫媒體使用相變合金。CD、DVD 和 Blu-ray 規格涵蓋實體格式、調變、錯誤更正和邏輯格式;僅憑檔案映像格式無法指定光碟的實體記錄方式。
ISO 9660 是源自 High Sierra 格式的唯讀光碟檔案系統。它強調循序配置和跨平台交換。其原始命名和目錄限制促成了 Rock Ridge(用於 POSIX 中繼資料)和 Joliet(用於較長的 Unicode 導向名稱)等延伸。El Torito 為可開機光學媒體新增開機記錄。
UDF 在許多 DVD 和 Blu-ray 用途中取代 ISO 9660。其基於描述元的配置支援增量更新,也能更自然地表示可重寫和一次寫入媒體。.iso 檔案是磁區映像,可以包含 ISO 9660、UDF 或混合配置。
實用的檢查工具包括 util-linux 中的 isosize,以及 libcdio 的 iso-info 和 iso-read 等工具。掛載或檢查不受信任的映像時,請採取與處理不受信任封存檔相同的注意事項,因為檔名和中繼資料可能是惡意輸入。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)