selenium 无法定位元素的一种情形 - iframe

发布时间 2023-08-05 18:44:58作者: sinatJ

今天在爬取一个反爬措施较严格的网站时,使用 selenium 做自动化登录时,无法定位输入框的问题。
查看网页源代码确实没有登录相关元素的标签,可以判定是采用的动态加载,但是即使使用的动态加载,等待页面渲染完毕之后应该还是能定位的。

看了下渲染完毕之后的网页源码,发现了在当前 html 页面中,又嵌套了一份 html 页面:

到这里,初步的猜想就是原来这里的登录页面是通过 iframe 嵌套在当前页面中的一个子页面。顺着这个思路,去百度了一下,果然,frame 标签包含 frameset、frame、iframe 三种:

  • frameset 和普通的标签一样,不会影响正常的定位
  • 而 iframe 和 frame 称之为框架标签,允许 html 文档前嵌入另一个 html 文档

而 selenium 默认是拿到当前页面的主 iframe 的句柄的,如果需要对内嵌的子 html 页面模块进行定位,需要先将 selenium 的句柄切换到该 iframe(即子 html 页面)上。

旧版 selenium 使用如下语法进行切换:

driver = webdriver.Firefox()
driver.get(r'http://www.126.com/')
driver.switch_to_frame('x-URS-iframe')  # 先跳转到iframe框架(参数直接写 iframe 标签的 id 或者 name 属性即可)
input = driver.find_element_by_name('email')
username.clear()

新版 selenium 使用如下语法进行切换:

# 通过元素定位方式切换窗口
browser.switch_to.frame(browser.find_element(by=By.ID, value='contentIframe'))
 
# 通过索引方式切换
driver.switch_to.frame(2)	# 第二个iframe

最后,在切换到指定 iframe 中执行完相关操作后,不要忘了切换回主页面:

# 从子frame切回到父frame(相当于后退)
driver.switch_to.parent_frame()
 
# 直接从 frame 中切回主文档
driver.switch_to.default_content()

参考: