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 等轴则从选定节点开始导航。类名表达式匹配单个标记,因此对于要求匹配 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 的四项限制促成了扩展分区约定。一个主分区项指向扩展引导记录链,每个 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 为可启动光学介质添加引导记录。
对于许多 DVD 和 Blu-ray 用途,UDF 取代了 ISO 9660。基于描述符的布局支持增量更新,也能更自然地表示可重写介质和一次写入介质。.iso 文件是扇区镜像,可以包含 ISO 9660、UDF 或混合布局。
有用的检查工具包括 util-linux 中的 isosize,以及 libcdio 中的 iso-info 和 iso-read 等实用程序。挂载或检查不可信镜像时,应采取与处理不可信归档相同的谨慎措施,因为文件名和元数据可能是恶意输入。
评论
在 GitHub 上阅读或评论(发表评论需要登录)