🚤 iframe 操作
<iframe>
元素是一种特殊的元素,它既是元素,也是页面,因此独立一个章节对其进行介绍。
与 selenium 不同,DrissionPage 无需切入切出即可处理<iframe>
元素。因此可实现跨级元素查找、元素内部单独跳转、同时操作<iframe>
内外元素、多线程控制多个<iframe>
等操作,功能更灵活,逻辑更清晰。
我们使用菜鸟教程在线编辑器来演示:
源代码框内容要作一点调整,然后按“点击运行”:
<!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_ele | str int ChromiumFrame | 必填 | 定位符<iframe> 元素序号(从1 开始,负数表示倒数)ChromiumFrame对象 id 属性内容name 属性内容 |
timeout | float | None | 超时时间,为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>
对象。
参数名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
locator | str Tuple[str, str] | None | 定位符,为None 时返回所有 |
timeout | float | None | 超时时间,为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