1、就是网页标签名为frame或iframe的元素,表单引用了其他页面的链接,真正的页面数据没有出现在源码中,但是在浏览器中可以看见,与浏览器的多个窗口类似
⑴这里说的表单不是HTML中的form标签,而是frame或iframe标签
⑵frame、iframe标签为HTML页面中的一种表单框架,主要作用是在当前页面中指定区域显示另一页面元素
2、frame或iframe标签表示在当前页面中镶嵌了另一个页面(以URL链接方式引用的)。因此就相当于是两个页面显示在了同一个窗口中
⑴这两个页面中的源码、元素是分开的
⑵外层页面:就是我们看到的主页面(用于包含frame、iframe标签的页面)
⑶内层页面:就是被镶嵌在外层页面中的页面(frame、iframe标签里面的页面)
⑷frame或iframe标签是属于外层页面的,要这两个标签包裹的部分才是内层页面的
3、在使用Selenium的WebDriver对象对这类页面(存在frame、iframe标签)进行元素定位时,WebDriver对象默认操作的是外层页面。对表单里的元素无法直接定位
⑴此时如果需要对frame、iframe标签内的元素进行定位的话,就需要切换到表单页面再进行定位
4、这个其实就跟前面介绍的"窗口切换"一样,Selenium服务默认使用的是使用get()方法打开的窗口,如果想要定位其他窗口中的元素的话,就需要切换窗口
⑴而frame、iframe标签可以理解成两个独立窗口显示在了一个页面中,Selenium服务默认使用外层页面,如果想要定位内嵌页面中的元素的话,就需要切换
⑵定位元素时候总是提示元素定位不到的问题,明明元素就在那里,这个时候就要关注你所定位的元素是否在frame和iframe里面
5、还有一种表单标签frameset,不过这个标签跟其他普通标签没有区别,不会影响到正常的定位
例1:直接定位内嵌页面元素
import time
from selenium import webdriver
# 获取浏览器对象
driver = webdriver.Chrome()
# 设置浏览器窗口大小
driver.maximize_window()
# 进入QQ空间首页
driver.get('https://qzone.qq.com/')
# 先定位外层页面中的元素
element = driver.find_element_by_xpath('//*[@id="lay"]/div[3]/div[1]/div[1]/ul/li[1]/a/i')
print(element)
# 直接定位内嵌页面元素
driver.find_element_by_id("switcher_plogin")
"""
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="switcher_plogin"]"}
"""
进入内嵌页面
1、Selenium服务表单切换有两种方式
⑴根据frame或iframe标签的id值或name属性值进行切换,涉及方法witch_to.frame('id的值或name属性值')
⑵先定位到表单,再切换到表单,然后定位到表单内的元素
⑶还有个switch_to_frame()方法,这个方法也是一样的,只是太老了
1、进入内嵌页面的第一种方式为:直接根据frame或iframe标签的id值或name属性值进行切换,涉及方法witch_to.frame('id的值或name属性值')
⑴WebDriver对象.witch_to.frame():默认使用表单(frame或iframe标签)的id值或name属性值进行切换
⑵witch_to.frame()方法实际可通过id、name、element(定位的某个元素)、索引来切换到某个frame
⑶整体思路:找到我们需要切换的那个表单标签(frame或iframe标签),然后使用witch_to.frame()方法进行切换
2、通过switch_to.frame()方法将当前定位的主体切换为frame或iframe表单的内嵌页面中
例2:
import time
from selenium import webdriver
# 获取浏览器对象
driver = webdriver.Chrome()
# 设置浏览器窗口大小
driver.maximize_window()
# 进入QQ空间首页
driver.get('https://qzone.qq.com/')
# 切换到内嵌页面:表单
driver.switch_to.frame("login_frame") # 根据id值进行切换(根据name属性值是一样的)
# 定位内嵌页面元素
element = driver.find_element_by_id("switcher_plogin")
print(element)
"""
"""
方式二
1、上面例子中表单标签(frame或iframe标签)有具体的id属性值或name属性值。这种情况下我们就可以很方便的切换到内嵌页面
2、但是实际中可能遇到id属性值为动态的(值是动态生成的,每次都不一样),又无name属性值。这个时候就可以使用第二种进入内嵌页面的方法了
3、进入内嵌页面的第二种方式为:先定位到表单,再切换到表单,然后定位到表单内的元素
⑴整体思路:找到我们需要切换的那个表单标签(frame或iframe标签),然后使用witch_to.frame()方法进行切换
⑵其实这种跟前面方法一是一样的,前面只是说存在id属性、name属性,因此可以根据id、name属性直接切换,相当于定位表单标签、切换一步就完成了
⑶而方法二中,由于id值不固定或不固定等,因此定位表单标签和切换不能一步就完成,就分开了
⑷都会使用到switch_to.frame()方法
4、表单标签frame或iframe标签是属于外层页面的,要这两个标签包裹的部分才是内层页面的。这样在外层页面才能定位到表单标签
例3:
import time
from selenium import webdriver
# 获取浏览器对象
driver = webdriver.Chrome()
# 设置浏览器窗口大小
driver.maximize_window()
# 进入QQ空间首页
driver.get('https://email.163.com/')
# 先定位到表单标签:通过tag_name进行定位
# frame = driver.find_element_by_tag_name('iframe')
frame = driver.find_element_by_xpath('/html/body/div[1]/div[2]/div[2]/div[1]/div[2]/div[2]/div/div[1]/iframe')
# 切换表单
driver.switch_to.frame(frame)
# 定位内嵌页面元素
element = driver.find_element_by_name("email")
print(element)
"""
"""
注:
1、这个例子中比较特殊的就是表单标签(frame),虽然说有id属性,但是其值是动态的,每次都不一样。因此就没法根据id值来直接切换表单了
⑴而是需要先定位到表单表标签(frame),然后再进行切换
2、在定位表单表标签(frame)时也不能根据id值来进行定位,因为id值是动态的,肯定定位不到,另外相对路径和css选择其也不能用,它们也是根据id属性生成的
⑴一般来说一个页面中最多只会镶嵌一个页面,很少有镶嵌多个页面的,因此整个HTML文档中只会有一个(frame或iframe标签)
⑵因此可以根据tag名字来定位,然后就是绝对路径了
3、如果真遇到了那种嵌套了多层页面的情况的话,其实也是一样的:从外到内一层一层的切换,直到切换到了我们需要的那一层
返回主页面1、切换到内嵌页面之后,同样也不能继续操作外层页面的内容了,若要操作外层页面的元素的话,就需切回到外层页面了
2、WebDriver对象提供了两个方法来切换到外层页面
⑴切换到最上层页面:switch_to.default_content()
⑵切换到上一层frame:switch_to.parent_frame()
1、方法:WebDriver对象.switch_to.default_content()
2、这个方法适用于当存在多层嵌套页面时,一次性切换到最外层页面
⑴当然也适用于只嵌套了一层的情况
例4:
import time
from selenium import webdriver
# 获取浏览器对象
driver = webdriver.Chrome()
# 设置浏览器窗口大小
driver.maximize_window()
# 进入QQ空间首页
driver.get('https://email.163.com/')
# 先定位到表单标签:通过tag_name进行定位
frame = driver.find_element_by_tag_name('iframe')
# 切换表单
driver.switch_to.frame(frame)
# 定位内嵌页面元素并操作
driver.find_element_by_name("email").send_keys("不怕猫的耗子")
driver.find_element_by_name("password").send_keys("12345678")
time.sleep(3)
# 切换到最外层页面
driver.switch_to.default_content()
# 操作最外层页面元素
driver.find_element_by_xpath('/html/body/div[1]/div[3]/div[1]/a[1]').click()
切换至上一层页面
1、方法:WebDriver对象.switch_to.parent_frame()
2、这个方法适用于当存在多层嵌套页面时,只切换到上一层页面(其父页面)
⑴当然也适用于只嵌套了一层的情况(这里就相当于切换到了最外层页面了)
例5:
import time
from selenium import webdriver
# 获取浏览器对象
driver = webdriver.Chrome()
# 设置浏览器窗口大小
driver.maximize_window()
# 进入QQ空间首页
driver.get('https://email.163.com/')
# 先定位到表单标签:通过tag_name进行定位
frame = driver.find_element_by_tag_name('iframe')
# 切换表单
driver.switch_to.frame(frame)
# 定位内嵌页面元素并操作
driver.find_element_by_name("email").send_keys("不怕猫的耗子")
driver.find_element_by_name("password").send_keys("12345678")
time.sleep(3)
# 切换到最外层页面
driver.switch_to.parent_frame()
# 操作最外层页面元素
driver.find_element_by_xpath('/html/body/div[1]/div[3]/div[1]/a[1]').click()
注:
1、对于切换表单标签(frame或iframe标签)只需要三个方法就够了:一进两出
⑴进内层页面就使用:switch_to.frame()
⑵出内层页面就使用:switch_to.parent_frame()或switch_to.default_content()
2、当我们定位一个元素时,始终定位不到,可以考虑一下两种情况
⑴元素是否加载完成:time.sleep()
⑵元素是否存在表单(内嵌页面)内:switch_to.frame()



