什么是 iframe?
Scrapeless Agent Browser 为需要导航包含嵌入文档页面的工作流运行受管的浏览器会话。
iframe 是一个 HTML 元素,用于在一个页面内部嵌入一个独立文档。被嵌入的文档拥有自己的窗口、文档树、URL 和导航生命周期。iframe 元素属于父文档,而其中显示的内容则属于子浏览上下文。
这种边界解释了一个常见的自动化问题:控件在屏幕上可见,但在父文档中执行的选择器却找不到它。该选择器也许对子文档是正确的,但依然在错误的地方搜索。将框架标识、源规则和内容就绪情况视为工作流中的独立部分。
嵌入文档与页面元素有何不同
iframe 承载的是另一个文档,而不是把该文档的节点合并进父文档。 HTML 内联框架元素 建立了这一嵌入式浏览上下文。
普通容器元素是在同一文档内对节点进行分组。iframe 则提供了一个位置,用于加载并执行不同的文档。父文档控制嵌入元素的位置和尺寸,而子文档管理其自身的内部布局。
这种分离有助于嵌入独立维护的应用、媒体、地图或账号组件。但它也引入了额外依赖:父页面可以成功加载,而嵌入的应用仍然不可用或呈现其自身的错误状态。
在抽取系统中,在诊断信息里保留这种区分。父页面导航成功只能证明父页面到达了某个状态。在认定嵌入记录已准备好收集之前,请检查目标子文档。
源规则控制脚本访问
同源策略限制来自不同源的文档如何通过页面脚本访问彼此的数据。源由 scheme、host 和 port 决定,并受制于平台的具体规则。
这一 同源安全边界 允许跨源 iframe 被显示,却不会赋予父页面对其内部文档的不受限访问。可见性与脚本可读性是不同的权限。
因此,父页面脚本可以持有一个 iframe 元素,却无法读取子页面的 DOM。这是预期的浏览器安全行为,而不是子内容未加载的证据。
不要把跨源嵌入当作禁用浏览器安全性的理由。如果你同时控制两个应用且需要通信,请使用设计好的跨文档接口。如果你通过浏览器级工具自动化一个已授权工作流,请使用客户端已文档化的框架接口,并尊重应用的权限。
跨文档消息需要显式契约
跨文档消息传递允许窗口交换结构化消息,而无需向对方暴露整个文档。安全的集成会定义哪些源可以通信,以及允许哪些消息结构。
postMessage 通信机制 提供了一个在窗口上下文之间受控的通道。发送方应在可能的情况下定位到预期的目标源,而接收方在执行操作前应验证发送方及其消息。
对于嵌入的账号组件,一条消息可能用于声明某个被允许的交互已完成。父页面应验证预期的发送方与状态,而不是信任任何带有“看起来合适”事件名的消息。
消息是应用间的契约,而不是通用的 DOM 访问授权。子页面报告已就绪并不意味着会自动提供其全部内部数据。定义集成所需的最小消息负载,避免暴露无关的账号信息。
Sandbox 与嵌入策略解决的是不同问题
Iframe sandbox 限制嵌入文档的能力,而嵌入策略决定页面是否可以被特定的上级页面框架化。这些控制作用于不同的边界。
sandbox 属性可以限制脚本、表单、导航以及其他行为,并可通过若干令牌有选择地恢复某些能力。添加令牌会改变安全模型,因此只选择嵌入应用所必需的能力。
被框架化的页面还可以使用 CSP frame-ancestors 指令 来控制哪些上级页面可以嵌入它。因此,一个拒绝出现在框架中的页面,可能正按设计工作。
| 控制项 | 主要问题 | 典型症状 |
|---|---|---|
| 同源策略 | 一个文档是否可以读取另一个文档的数据? | 框架可见,但父页面对 DOM 的访问受限 |
| Iframe sandbox | 子文档可以使用哪些能力? | 子文档已加载,但其操作被限制 |
| 嵌入策略 | 该页面是否可以出现在这些上级页面下? | 浏览器拒绝进行嵌入 |
| 应用授权 | 该用户是否可以访问所请求的内容? | 子页面显示登录或权限界面 |
在修改嵌入方式前,请先诊断实际的边界。放宽无关的控制会增加风险,却未必能解决问题。
帧就绪与父级就绪相互独立
父文档达到就绪状态后,iframe 可以独立加载和导航。框架内的目标内容需要其自身的验收条件。
有些页面只有在用户操作之后才插入 iframe。其他页面会提前创建该元素,并在之后导航其子文档。第三方组件随后可能会在显示你的工作流所需的记录之前请求额外的数据。
将检查分离开来:嵌入元素是否存在、目标子上下文是否已识别,以及子应用是否已达到所需状态。空的初始文档并不能证明最终组件是空的。
使用与子内容相关的就绪条件。对于表单,在正确的框架中验证预期的标签或控件。对于嵌入的报告,验证报告的标识和必需字段。父页面标题无法确定任何一种结果。
在保持引用时要牢记导航。框架元素可以保持存在,而其中的文档会发生变化。在已知导航之后,重新评估子状态,而不是假定先前的文档引用仍然有效。
自动化应在选择元素之前先选择框架
框架感知自动化会在定位其内部元素之前先选择目标子上下文。父页面选择器不会自动搜索每个嵌入的文档。
通过实际页面中可用的稳定属性来识别框架,例如嵌入元素的可访问含义、名称或预期 URL。避免仅依赖索引,因为广告或可选的小部件会改变框架顺序。
嵌套框架需要通过多个上下文的路径。 在定位最终控件之前,确认每一层及其当前文档。 具有正确可见位置的框架仍可能包含错误的应用程序状态。
浏览器级自动化和父页面的 JavaScript 具有不同的能力。即使页面脚本无法读取跨源子框架,客户端仍可能通过浏览器控制接口公开框架检查功能。那并不会取消账户授权要求,也不会让所有受保护的应用程序都适合被自动化。
在执行操作后,在拥有结果的上下文中验证其效果。在子级中选择一个控件可能会更新子级、向父级发送消息,或导航到另一个上下文。工作流应遵循实际的应用程序契约。
性能与可访问性归于嵌入
iframe 会引入一个独立的文档和资源生命周期,因此它需要单独进行加载和可访问性方面的决策。嵌入页面并不会让其成本或交互需求消失。
为 iframe 提供一个有意义的标题,以帮助用户识别嵌入的内容。子文档仍然需要具有可访问的控件和良好的焦点行为。一个具有描述性的父级标题无法修复一个不可访问的子应用程序。
使用适合内容的加载行为。推迟加载屏幕外的嵌入内容可以减少初始工作量,但需要其数据的工作流必须考虑到其实际加载的时间。不要将延迟加载视为内容缺失。
还要考虑故障呈现。如果嵌入的报表无法加载,用户需要看到一个清晰的状态,而不是一个空白的矩形。自动化也可以利用同样的区分来分离空报表和不可用的组件。
在 Scrapeless Agent Browser 中处理框架
无痕代理浏览器 为包含嵌入文档的浏览器工作流提供托管运行时。其 Puppeteer 连接接口 提供浏览器连接;框架识别和页面级检查仍然是你自动化逻辑的一部分。
The iframe 提取工作流程 为使用浏览器客户端选择子文档提供相关上下文。托管环境不会合并框架 DOM,也不会消除等待目标子应用程序的必要性。
审查 无爬取定价 在规划渲染工作负载时,评估包含你的任务所依赖帧的具有代表性的页面,并测量成功的记录提取次数,而不是仅仅统计父页面加载次数。
结论
iframe 是嵌入在另一个页面中的独立文档。可靠的集成和自动化取决于理解来源边界、能力限制、框架身份以及子框架就绪状态。在正确的上下文中定位,验证其应用状态,并在该状态实际存在的位置对结果进行校验。
构建一个支持 Frame 的浏览器工作流
在保持子文档身份、就绪状态和输出验证明确的前提下探索 Scrapeless Agent 浏览器。
今天注册即可获得 5 美元的免费额度 — 无需信用卡.
领取您的 $5 额度 →常见问题解答
问:iframe 和 div 是一样的吗?
iframe 嵌入的是一个独立的文档,而 div 用于在当前文档中对内容进行分组。因此,它们的节点分别属于不同的文档结构。
问:为什么父页面无法读取可见 iframe 的 DOM?
可见的 iframe 可以具有不同的源,这会根据同源策略限制父页面脚本的访问。渲染子页面并不会授予不受限制的数据访问权限。
问:父级的 load 事件能证明 iframe 中的应用已经就绪了吗?
父级的加载事件并不能证明子应用已经达到所需状态。请在已识别的框架内验证目标内容。
问:为什么在选择框架时应避免使用数字索引?
数字框架索引在出现可选或动态嵌入内容时可能会改变。应优先使用稳定的框架标识,并在交互前验证当前子级的 URL 或内容。
问:sandboxing 和 frame-ancestors 能相互取代吗?
sandboxing 和 frame-ancestors 处理的是不同的控制点。sandboxing 限制子文档的能力,而 frame-ancestors 限制哪些上级页面可以嵌入该文档。