Python + Playwright(23):处理 iframe (内嵌框架)「详细介绍」

news2024/9/22 19:29:38

Python + Playwright(23):处理 iframe 内嵌框架「详细介绍」

  • 简介
  • 1. 理解 iframe 的特性
  • 2. 处理 iframe 的方法
    • 2.1 使用 `page.frames` 遍历所有的 iframe
    • 2.2 通过 `page.frames` 访问特定 iframe
    • 2.2 通过 `page.frames` 的索引访问 iframe
    • 2.3 通过 `page.frame()` 方法的 name 或 id 处理 iframe
    • 2.4 通过 `page.frame()` 方法操作嵌套 iframe
    • 2.5 等待 iframe 加载
    • 2.6 使用 `page.frame_locator()` 方法
    • 2.7 使用 `locator.frame_locator()` 方法
    • 2.8 `frame_locator()` 方法的优势
  • 3. 高级 iframe 操作技巧
    • 3.1 处理动态内容
  • 4. 常见问题与解决方案
    • 4.1 iframe 无法访问或定位失败
    • 4.2 iframe 中的元素操作失败
  • 总结

简介

iframe,即内嵌框架,是 HTML 标签之一,允许在网页内嵌入另一个 HTML 页面。与普通的页面元素不同,iframe 有自己独立的 DOM 树、浏览上下文、JavaScript 运行环境以及网络会话(如 Cookie 和 LocalStorage)。因此,处理 iframe 需要特别注意它与主页面的隔离性。

1. 理解 iframe 的特性

  • 由于 iframe 是独立的文档,直接操作 iframe 内的元素需要切换到该 iframe的上下文。
  • 与主文档直接交互不同,自动化工具必须明确地“切换”到 iframe 中才能执行操作。
  • 在 Playwright 中,虽然 iframe 依然是一个独立的上下文,但不再需要手动切换。Playwright
    提供了专门的方法,可以直接操作 iframe 内的元素。

2. 处理 iframe 的方法

2.1 使用 page.frames 遍历所有的 iframe

page.frames 属性返回当前页面中所有已加载的 Frame 对象列表。这些 Frame 对象包括主页面(通常是第一个 Frame)和所有嵌入的 iframe。

通过 page.frames,可以遍历所有的 iframe,并对它们进行相应的操作。

from playwright.sync_api import sync_playwright


def run(playwright):
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://music.163.com/#")

    frames = page.frames
    for frame in frames:
        print(f"Frame Name: {frame.name}, Frame URL: {frame.url}")

    context.close()
    browser.close()


with sync_playwright() as playwright:
    run(playwright)

代码解释:

  • frames = page.frames:获取页面中所有已加载的 iframe
  • frame.name:返回 iframe 的名称(如果存在)
  • frame.url:返回 iframe 的当前 URL

执行结果如下:
在这里插入图片描述

2.2 通过 page.frames 访问特定 iframe

有时,页面上可能存在多个 iframe,直接通过 name 或 url 定位可能不太方便。这时,你可以使用 page.frames 获取所有 iframe 的列表,然后根据需要的属性手动选择特定的 iframe。

通过 frame.name:

from playwright.sync_api import sync_playwright


def run(playwright):
    browser = playwright.chromium.launch(headless=True)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://music.163.com/#")

    frames = page.frames
    target_frame = None
    for frame in frames:
        if "contentFrame" in frame.name:
            target_frame = frame
            print("Target frame:", target_frame)
            break

    if target_frame:
        target_frame.click("#index-banner")

    page.wait_for_timeout(1000)
    page.screenshot(path="screenshot.png")

    context.close()
    browser.close()

在这里插入图片描述

执行结果如下:
在这里插入图片描述

通过 frame.url:

from playwright.sync_api import sync_playwright


def run(playwright):
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://music.163.com/#")

    frames = page.frames
    target_frame = None
    for frame in frames:
        if "https://music.163.com/discover" in frame.url:
            target_frame = frame
            break

    if target_frame:
        target_frame.click("#index-banner")

    page.wait_for_timeout(1000)
    page.screenshot(path="screenshot.png")

    context.close()
    browser.close()


with sync_playwright() as playwright:
    run(playwright)

代码说明:

  • 通过遍历 page.frames 获取的 Frame 对象列表,根据特定条件(如 name 或 url)筛选目标 iframe。
  • 如果找到了目标 iframe(target_frame),则可以在其上执行操作,如点击按钮、填写表单等。

2.2 通过 page.frames 的索引访问 iframe

在某些情况下,iframe 可能没有明确的名称或 ID。这时可以通过索引来访问 iframe:

from playwright.sync_api import sync_playwright


def run(playwright):
    # 启动浏览器并打开页面
    browser = playwright.chromium.launch(headless=True)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://music.163.com/#")

    # 查找并访问 iframe
    frame = page.frames[0]  # 获取第一个 iframe
    if frame:
        print(f"Frame : {frame}")

    # 关闭浏览器
    context.close()
    browser.close()


with sync_playwright() as playwright:
    run(playwright)

这种方法在处理复杂页面结构时非常有用,尤其是在页面上存在多个 iframe 的情况下。

2.3 通过 page.frame() 方法的 name 或 id 处理 iframe

Playwright 提供了 page.frame() 方法来处理 iframe。

以下是如何通过 page.frame() 方法操作 iframe 的基本步骤:

from playwright.sync_api import sync_playwright

def run(playwright):
    # 启动浏览器并打开页面
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://music.163.com/#")

    # 查找并访问 iframe
    frame = page.frame(name="contentFrame")  # iframe 的名称或 ID访问iframe
    if frame:
        print(f"Frame Name: {frame.name}")

    # 关闭浏览器
    context.close()
    browser.close()

with sync_playwright() as playwright:
    run(playwright)

代码解释:

  • frame = page.frame(name="iframe_name_or_id"):通过 iframe 的名称或 ID 获取 iframe 对象。

2.4 通过 page.frame() 方法操作嵌套 iframe

嵌套 iframe 进一步增加了测试的复杂性。为了操作嵌套的 iframe,必须逐级访问:

outer_frame = page.frame(name="outer_frame")
inner_frame = outer_frame.frame(name="inner_frame")

inner_frame.click("button#submit")

这里,先通过 outer_frame 获取外层 iframe,然后再通过 inner_frame 获取嵌套的 iframe,最终在嵌套的 iframe 中执行操作。

2.5 等待 iframe 加载

在实际操作中,iframe 的内容可能会延迟加载。在这种情况下,可以使用 Playwright 的等待机制确保 iframe 已经加载完毕:

frame = page.wait_for_selector("iframe#frame_id", state="attached")  # 等待 iframe 出现
frame = page.frame(name="frame_id")

wait_for_selector 方法确保 iframe 存在并加载后,才开始执行后续操作,从而避免潜在的错误。

2.6 使用 page.frame_locator() 方法

page.frame_locator() 方法可以用于创建一个 FrameLocator 对象,它允许你在 iframe 中定位和操作元素,而无需显式切换到 iframe 上下文。这个方法可以让代码更简洁,并减少潜在的错误。

示例代码如下:

from playwright.sync_api import sync_playwright


def run(playwright):
    # 启动浏览器并打开页面
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://music.163.com/#")

    # 使用 frame_locator 定位 iframe 中的元素并进行操作
    frame_locator = page.frame_locator("iframe[name='contentFrame']")
    frame_locator.locator("#index-banner").click()

    # 截图保存操作结果
    page.screenshot(path="screenshot.png")

    # 关闭浏览器
    context.close()
    browser.close()


with sync_playwright() as playwright:
    run(playwright)

代码说明:

  • frame_locator = page.frame_locator("iframe[name='contentFrame']"):通过 iframe 的 name 属性创建一个 FrameLocator 对象。
  • frame_locator.locator("#index-banner").click():在指定的 iframe 中定位并点击 #index-banner 元素。

这种方法不需要显式地切换上下文,使得代码更加简洁且易于维护。

2.7 使用 locator.frame_locator() 方法

locator.frame_locator() 方法允许你在已有的 Locator 对象的基础上,进一步在其包含的 iframe 中进行操作。这种方法适合用于处理嵌套 iframe 中的元素操作,大大简化了代码逻辑。

示例代码如下:

from playwright.sync_api import sync_playwright


def run(playwright):
    # 启动浏览器并打开页面
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://music.163.com/#")

    # 使用 locator.frame_locator 定位嵌套 iframe 中的元素并进行操作
    frame_locator = page.locator("iframe[name='contentFrame']").frame_locator("iframe")
    frame_locator.locator("#some-element-in-nested-iframe").click()

    # 截图保存操作结果
    page.screenshot(path="screenshot_nested.png")

    # 关闭浏览器
    context.close()
    browser.close()


with sync_playwright() as playwright:
    run(playwright)

代码说明:

  • frame_locator = page.locator("iframe[name='contentFrame']").frame_locator("iframe"):首先定位外层的 iframe,然后在其内部的嵌套 iframe 中继续定位。
  • frame_locator.locator("#some-element-in-nested-iframe").click():在嵌套 iframe 中定位并点击元素。

2.8 frame_locator() 方法的优势

相比传统的 page.framespage.frame 方法,frame_locator() 提供了以下几个优势:

  1. 简洁性:无需手动切换上下文,代码更简洁。
  2. 灵活性:可以轻松处理嵌套的 iframe。
  3. 可读性:代码可读性更高,更容易理解和维护。

通过这些方法,处理复杂的 iframe 结构变得更加容易,有效减少了操作 iframe 时可能遇到的问题。

3. 高级 iframe 操作技巧

3.1 处理动态内容

在实际场景中,很多 iframe 包含动态内容,例如广告或第三方组件。这些内容可能会根据用户操作或时间动态变化。为了在测试中处理这种情况,可以使用 Playwright 的 wait_for_function 方法,确保内容加载完成或某个特定条件满足后再继续执行操作。

示例代码如下:

frame = page.frame(name="dynamic_frame")
page.wait_for_function("() => document.querySelector('button#dynamic_button') !== null", timeout=5000)
frame.click("button#dynamic_button")

4. 常见问题与解决方案

4.1 iframe 无法访问或定位失败

有时,Playwright 可能无法找到特定的 iframe。这种情况下可以检查以下几点:

  • 名称或 ID 是否正确:确保使用的名称或 ID 在 HTML 代码中确实存在。
  • iframe 动态加载:如果 iframe 是动态加载的,确保在尝试访问前,使用 wait_for_selector 方法等待其加载完成。
  • 跨域问题:对于跨域的 iframe,检查浏览器的安全策略设置,确保自动化工具具有必要的权限访问。

4.2 iframe 中的元素操作失败

操作 iframe 内部元素失败可能是由于以下原因:

  • 元素未加载:使用 wait_for_selector 等待元素加载。
  • 元素被覆盖:检查元素是否被其他浮动元素覆盖,可能需要滚动页面或使用 force=True 强制点击。

总结

iframe 是 Web 开发中常见的元素,但它的独立性和隔离性为自动化测试带来了挑战。通过 Playwright 提供的强大 API,我们可以轻松应对这些挑战,实现对 iframe 的有效操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2078756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业如何实现多个分公司组网方案

在现代商业环境中,企业往往需要连接多个分公司以实现高效的资源共享和协同工作。以下是一个全面的多个分公司组网策略供参考。 一、确定网络架构和布局 总部作为核心数据中心:总部应配备高性能的网络设备和完善的安全防护措施,承担数据存储和…

医疗器械管理软件 符合新规 免费升级

盘谷医疗器械管理软件具有对采购、收货、验收、贮存、销售、出库、复核、退货等各经营环节进行实时质量控制的功能;具有权限管理功能,确保各类数据的录入、修改、保存等操作应当符合授权范围、管理制度和操作规程的要求,保证数据真实、准确、…

深入理解ARM64的函数调用标准与栈布局

一、引言 随着计算机技术的飞速发展,人们对计算机的性能要求越来越高,为了突破32位架构的4GB地址空间限制,并实现更好的性能提升。ARM公司推出了一种64位处理器架构,也就是我们今天所要讨论的ARM64。ARM64(也称ARMv8)面世以来,在…

leetcode 3146 两个字符串的排列差

leetcode 3146 两个字符串的排列差 正文题目描述解题思路方法1 Python 处理字符串的思路方法2 正文 题目描述 解题思路 直接 for 循环遍历第一个字符串,在第二个字符串中找出第一个字符串中的对应字符的位置,做差,再取绝对值,最…

Clickhouse集群化(三)集群化部署

1. 准备 clickhouse支持副本和分片的能力,但是自身无法实现需要借助zookeeper或者clickhouse-keeper来实现不同节点之间数据同步,同时clickhouse的数据是最终一致性 。 2. Zookeeper 副本的写入流程 没有主从概念 平等地位 互为副本 2.1. 部署zookeep…

高效能低延迟:EasyCVR平台WebRTC支持H.265在远程监控中的优势

TSINGSEE青犀视频EasyCVR视频汇聚平台在WebRTC方面确实支持H.265编码,尽管标准的WebRTC API在大多数浏览器中默认并不支持H.265(也称为HEVC,高效视频编码)编码。EasyCVR平台通过一系列创新的技术手段,实现了在WebRTC协…

区块链应用,密码学会议书籍推荐以及隐私保护知识整理

基于区块链技术的安全多方计算项目示例 1. iCube——全球首个安全多方计算区块链金融项目 iCube团队通过与美国普渡大学区块链人工智能实验室深度合作,实现了区块链的安全多方计算。iCube建立了面向信息的终极抽象基础层和基于个人工智能的算法模型层,…

互联网盲盒小程序,提高企业市场竞争力

盲盒作为一种休闲娱乐的方式,受到了大众的追捧,各大消费者争相购买,市场一时火热非凡! 随着互联网电商的出现,盲盒也开始在线上发展,当消费者距离盲盒门店较远或者没有时间下,就可以在小程序上…

Linux:Socket网络编程

目录 1. 理解源 IP 地址和目的 IP 地址 2:认识端口号 3:端口号范围划分 4:理解源端口号和目的端口号 5:理解Socket(套接字) 6:两个传输协议 (TCP/UDP) 6.1:User Datagram Prot…

重磅!尤文图斯携手Fortinet打造足球界的网络安全堡垒

近日,尤文图斯足球俱乐部与推动网络与安全融合的全球网络安全领导者 Fortinet(NASDAQ:FTNT)正式宣布建立合作伙伴关系,并签署了一项为期至2026年的赞助协议。在此框架下,Fortinet荣膺尤文图斯未来两个赛季的…

深度学习/机器学习软件教学平台

1、基本介绍 机器学习与深度学习教学系统是基于业界应用广泛的在线机器学习和深度学习建模开发框架JupyterLab开发的,面向高校数据分析、机器学习、深度学习,以及人工智能相关专业教学和实训的教学系统。 2、系统特色 系统首页 系统主界面 在线实验界面…

LLM推理端实现

LLM推理端是什么 Large Language Model,大语言模型。典型代表ChatGPT。 推理端:模型训练出来后,用于模型应用和部署的interface。 推理端实现了本地环境中部署大语言模型。可以实现LLM的基本功能,包括生成文本、自动摘要、语言…

目标小程序和当前小程序主体必须为绑定在同一0pen下的相关或关联主体

第一步:登录微信开放平台->账号中心->基本资料->关联主体信息->管理 第二步:管理员微信扫码二维码验证 第三步:管理员微信手机确认 第四步:管理员微信扫码确认后,即可“添加关联主体” 第五步:…

HarmonyOS开发之Gauge(环形图表)的简单使用

效果图: 代码块: Entry Component struct GaugePage {Builder descriptionBuilder() {Text(优).maxFontSize(30).minFontSize(30).fontColor("#fffa2a2d").fontWeight(FontWeight.Medium).width(100%).height("100%").textAlign(Te…

企业数据防泄密刻不容缓|八个措施拒绝泄密

随着信息技术的飞速发展和全球化的推进,企业数据的安全与保密性日益凸显其重要性。数据泄露不仅可能导致企业的核心资产流失、经济损失,还可能严重损害企业的声誉和市场竞争力。因此,建立一套完善的数据防泄密系统,已成为企业维护…

strace 简介和使用

简介 strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序。 在Linux系统中,用户程序运行在一个沙箱(sandbox)里,用户进程不…

园区中的智慧用电管理

随着物联网、云平台等新兴信息科技的日益成熟,未来园区用电管理的发展将更加智能化、信息化。近年来,越来越多的能源互联网企业为园区用电管理提供了解决方案,文献[1]提出基于大数据技术设计开发的智能电表远程抄表系统替代传统的人工抄表方法…

常用标准化图像分辨率

常用标准化图像分辨率 标准化图像格式通常指的是将图像数据转换为统一的、标准化的格式,以便于存储、传输和处理。这种格式化过程可能包括调整图像的大小、颜色空间转换、归一化像素值等。 以下是常见标准化图像名称及分辨率(在深度学习和计算机视觉领域…

衡石科技BI的API如何授权文档解析

授权说明​ 授权模式​ 使用凭证式(client credentials)授权模式。 授权模式流程说明​ 第一步,A 应用在命令行向 B 发出请求。 第二步,B 网站验证通过以后,直接返回令牌。 授权模式结构说明​ 接口说明​ 获取a…

【Qt学习】Qlabel 的核心属性 与 代码实例

文章目录 1. 介绍2. 显示文本3. 显示图片4. 设置文本对齐方式5. 设置自动换行、边距、缩进6. 设置伙伴 1. 介绍 在Qt学习的专题中,我们以及多次使用过QLabel,作用就是用于显示文本和图片; QLabel有以下 核心属性: 好的&#xf…