跳到主要内容

🚤 iframe 操作


<iframe>元素是一种特殊的元素,它既是元素,也是页面,因此独立一个章节对其进行介绍。

与 selenium 不同,DrissionPage 无需切入切出即可处理<iframe> 元素。因此可实现跨级元素查找、元素内部单独跳转、同时操作<iframe>内外元素、多线程控制多个<iframe>等操作,功能更灵活,逻辑更清晰。

我们使用菜鸟教程在线编辑器来演示:

菜鸟教程在线编辑器 (runoob.com)

源代码框内容要作一点调整,然后按“点击运行”:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>

<body>
<iframe id="sss" src="https://www.runoob.com">
<p>您的浏览器不支持 iframe 标签。</p>
</iframe>
</body>
</html>

F12,可以看到网页右侧是一个两层<iframe>,一个 id 是'iframeResult'<iframe>里面有一个 id 是'sss'<iframe> 。最里层的<iframe> 页面指向 https://www.runoob.com。


✅️ 获取<iframe>对象

获取<iframe>对象的方法有两种,可用获取普通元素的方式获取,或者用get_frame()方法获取。推荐优先使用get_frame() 方法,因为当作普通元素获取时,IDE 无法正确识别获取到的是<iframe>元素。

📌 get_frame()

此方法用于获取页面中一个<frame><iframe>对象。

参数名称类型默认值说明
loc_ind_elestr
int
ChromiumFrame
必填定位符
<iframe>元素序号(从1开始,负数表示倒数)
ChromiumFrame对象
id属性内容
name属性内容
timeoutfloatNone超时时间,为None时使用页面超时时间
返回类型说明
ChromiumFrame<frame><iframe>元素对象
NoneElement找不到时返回NoneElement
注意

需要特别注意的是,如果页面中有嵌套的<iframe>,用序号获取的方式会存在不准确。 比如上面说的网站,用get_frames()可获取到 6 个元素,但用get_frame(6)却获取不到最后一个。 这是因为有两个<iframe>是嵌套关系,导致获取不准确。

示例:

# 使用定位符获取
iframe = page.get_frame('#sss')

# 获取第1个iframe
iframe = page.get_frame(1)

📌 get_frames()

此方法用于获取页面中多个符合条件的<frame><iframe>对象。

参数名称类型默认值说明
locatorstr
Tuple[str, str]
None定位符,为None时返回所有
timeoutfloatNone超时时间,为None时使用页面超时时间
返回类型说明
List[ChromiumFrame]<frame><iframe>元素对象组成的列表
提醒

获取所有<iframe>会很慢,而且浪费资源,一般使用获取需要用到的就好。


📌 普通元素方式

可以用获取普通元素的方式获取<iframe>对象:

iframe = page('#sss')
print(iframe.html)

输出:

<iframe id="sss" src="https://www.runoob.com"><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>菜鸟教程 - 学的不仅是技术,更是梦想!</title>

<meta name="robots" content="max-image-preview:large">

下面省略。。。

这个ChromiumFrame对象既是页面也是元素。由于 IDE 不会提示<iframe> 元素对象相关的属性和方法,因此用这种方式获取时建议再用get_frame()包装一下:

iframe = page('#sss')
iframe = page.get_frame(iframe)

✅️ 查找<iframe>内元素

从刚才获取元素对象看出,我们并不需要先切入 id 为'iframeResult'<iframe> ,就可以获取到里面的元素。所以我们获取元素也并不一定要先获取到ChromiumFrame对象。

📌 在<iframe>内查找

使用我们刚才获取到的元素,可以在里面查找元素:

ele = iframe('首页')
print(ele)

输出:

<ChromiumElement a href='https://www.runoob.com/' data-id='index' title='菜鸟教程' class='current'>

📌 页面跨<iframe>查找

如果<iframe>元素的网址和主页面是同域的,我们可以直接用页面对象查找<iframe>内部元素,而无需先获取ChromiumFrame对象:

ele = page('首页')
print(ele)

输出:

<ChromiumElement a href='https://www.runoob.com/' data-id='index' title='菜鸟教程' class='current'>

只要是同域名的,无论跨多少层<iframe>都能用页面对象直接获取。


📌 与 selenium 对比

WebPage

from DrissionPage import WebPage

page = WebPage()
ele = page('首页')

MixPage(基于 selenium):

from DrissionPage import MixPage

page = MixPage()
page.to_frame('#iframeResult')
page.to_frame('#sss')
ele = page('首页')
page.to_frame.main()

可见,原来的逻辑要切入切出,比较繁琐。


📌 重要事项

如果<iframe>跟当前标签页是不同域名的,不能使用页面对象直接查找其中元素,只能先获取其ChromiumFrame元素对象,再在这个对象中查找。


✅️ ChromiumFrame的元素特征

正如上面所说,ChromiumFrame既是元素也是页面,这里说一下其元素方面的用法。

📌 tag

此属性返回元素名称。

类型:str


📌 html

此属性返回整个<iframe>元素的 outerHTML 文本。

类型:str


📌 inner_html

此属性返回 innerHTML 文本。

类型:str


📌 attrs

此属性以dict形式返回元素所有 attribute 属性。

类型:dict


📌 xpath

此属性返回元素在其页面上的 xpath 路径。

类型:str


📌 css_path

此属性返回元素在其页面上的 css selector 路径。

类型:str


📌 attr()

此方法用于一个获取元素 attribute 属性。

参数名称类型默认值说明
namestr必填属性名
返回类型说明
str属性值文本
None没有该属性返回None

📌 set.attr()

此方法用于设置元素的 attribute 属性。

参数名称类型默认值说明
namestr必填属性名
valuestr必填属性值

返回:None


📌 remove_attribute()

此方法用于删除元素的 attribute 属性。

参数名称类型默认值说明
namestr必填属性名

返回:None


📌 相对定位

相对定位方法与普通元素一致,详见获取元素章节。

  • parent():返回上面某一级父元素。

  • prev():返回前面的一个兄弟元素。

  • next():返回后面的一个兄弟元素。

  • before():返回当前元素前面的一个元素。

  • after():返回当前元素后面的一个元素。

  • prevs():返回前面全部兄弟元素或节点组成的列表。

  • nexts():返回后面全部兄弟元素或节点组成的列表。

  • befores():返回当前元素后面符合条件的全部兄弟元素或节点组成的列表。


✅️ ChromiumFrame的页面特征

📌 url

此属性返回页面当前 url。

类型:str


📌 title

此属性返回页面当前 title 文本。

类型:str


📌 get()

此方法用于实现<iframe>页面跳转,使用方法与ChromiumPage一致。

iframe.get('https://www.runoob.com/css3/css3-tutorial.html')

📌 refresh()

此方法用于刷新页面。

参数: 无

返回:None

iframe.refresh()

📌 active_ele

此属性返回页面中焦点所在元素。

类型:ChromiumElement


📌 run_js()

此方法用于在<iframe>内执行 js 脚本。

参数名称类型默认值说明
scriptstr必填js 脚本文本或脚本文件路径
*args-传入的参数,按顺序在js文本中对应arguments[0]arguments[1]...
as_exprboolFalse是否作为表达式运行,为Trueargs参数无效
timetoutfloatNonejs 超时时间,为None则使用页面timeouts.script设置
返回类型说明
Any脚本执行结果

📌 scroll

ChromiumFrame的滚动方法与页面或元素是一致的。

示例: 使<iframe>元素向下滚动 300 像素

iframe.scroll.down(300)

📌 get_screenshot()

此方法用于对<iframe>进行截图。由于技术限制,只能对视口截图。

下面三个参数三选一,优先级:as_bytes>as_base64>path

参数名称类型默认值说明
pathstr
Path
None保存图片的路径,为None时保存在当前文件夹
namestrNone完整文件名,后缀可选'jpg''jpeg''png''webp',为None时以用 jpg 格式
as_bytesstr
True
None是否以字节形式返回图片,可选'jpg''jpeg''png''webp'NoneTrue
不为Nonepathas_base64参数无效
True时选用 jpg 格式
as_base64str
True
None是否以 base64 形式返回图片,可选'jpg''jpeg''png''webp'NoneTrue
不为Nonepath参数无效
True时选用 jpg 格式
返回类型说明
bytesas_bytes生效时返回图片字节
stras_bytesas_base64None时返回图片完整路径
stras_base64生效时返回 base64 格式的字符串

✅️ 位置与大小

📌 rect.location

此属性返回 iframe 元素左上角在页面中的坐标。格式:(x, y),左上角为(0, 0)。

返回类型:Tuple[float, float]


📌 rect.viewport_location

此属性返回 iframe 元素左上角在视口中的坐标。格式:(x, y),左上角为(0, 0)。

返回类型:Tuple[float, float]


📌 rect.screen_location

此属性返回 iframe 元素左上角在屏幕上的坐标。格式:(x, y),左上角为(0, 0)。

返回类型:Tuple[float, float]


📌 rect.size

此属性返回 frame 内页面尺寸,格式:(宽, 高)。

返回类型:Tuple[float, float]


📌 rect.viewport_size

此属性返回 iframe 口宽高,格式:(宽, 高)。

返回类型:Tuple[float, float]


📌 rect.corners

此属性返回 iframe 元素四个角在页面中的坐标,顺序:坐上、右上、右下、左下。

返回类型:((float, float), (float, float), (float, float), (float, float),)


📌 rect.viewport_corners

此属性返回 iframe 元素四个角在视口中的坐标,顺序:坐上、右上、右下、左下。

返回类型:((float, float), (float, float), (float, float), (float, float),)


✅️ 对象状态

📌 states.is_loading

此属性返回页面是否在加载状态。

返回类型:bool


📌 states.is_alive

此属性返回frame元素是否可用,且里面仍挂载有frame。

返回类型:bool


📌 states.is_displayed

此属性返回 iframe 是否显示。

返回类型:bool


📌 states.ready_state

此属性返回加载状态,有 4 种:

  • 'connecting': 网页连接中
  • 'loading':文档还在加载中
  • 'interactive':DOM 已加载,但资源未加载完成
  • 'complete':所有内容已完成加载

返回类型:str