遇到“noSuchElement”原因是把元素放在iframe里面,根本就找不到。
按f12,html里面嵌套的html,嵌套的不一定和外面的html页面一样,例如孩子和妈妈也不一定是一模一样。
看下这个就能看出是否在iframe中。
如果我要操作的元素在iframe中,那么先过了这关,再去操作旗下的内容。
首先这样一个弹出框,这样一个iframe出来呢,是因为你的一个操作出来的,所以你可以调用我们的各种操作进入到这个页面之后,iframe就出来了。
输入iframe,看看有多少个:
这个页面有5个iframe。
如果页面只有一个iframe,非常好切换。这个iframe也是当前html页面的一个元素。只不过它是个载体,它里面的内容是另外一个东西。
先找到我要切换的iframe,再去切换,切换的方式比较多。
switch_to
意思是切换。
frame
这个函数表示iframe。
当你上面一个操作导致iframe出现之后,你未来要操作的元素在iframe中,就必须先切换进去。
如果有name属性,就通过name,但是这种页面有多个iframe的时候,没法判定这个name是绝对唯一的。
先判断下name是不是绝对唯一的,这是xpath表达式:
通过name属性能够唯一找到它,通过name来切换。
driver.switch_to.frame('login_frame_qq')
driver.switch_to.frame(driver.find_element_by_xpath('//frame[@name="login_frame_qq"]'))
switch_to
和等待。 WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it("login_frame_qq"))
从iframe当中回到默认的页面当中。
driver.switch_to.default_content()
想在这个iframe当中再切换到下一级,一层一层切进去就可以了,不能够跳层,如果你在这个html页面中还有iframe,那就切换两次。
能退到iframe的上一级。
driver.switch_to.parent_frame()
parent_frame
就是跳到它的父级。
from selenium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
#web自动化有8种定位方式在By这个类中,详情可以看源码。
#启动谷歌浏览器,开启与浏览器之间的会话。
driver=webdriver.Chrome(service_log_path="D://chromedriver_service.log")
# 全局等待--隐性等待
# driver.implicitly_wait(30)
#访问网页
driver.get("http://www.baidu.com")#写全网址的路径。
driver.find_element_by_xpath('//*[@id="u1"]//a[@name="tj_login"]').click()
# 这种情况下需要等待新的弹框出现,然后点击其中的用户名密码方式。
id="TANGRAM__PSP_10__footerULoginBtn"
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,id)))
#点击 用户名密码方式。
driver.find_element_by_id("TANGRAM__PSP_10__footerULoginBtn").click()
#切换iframe=进入了另外一个html页面
# 等待iframe存在,可见
# 方式一:
driver.switch_to.frame('login_frame_qq')
#方式二:想通过定位表达式来查找。
driver.switch_to.frame(driver.find_element_by_xpath('//frame[@name="login_frame_qq"]'))
#切换进来之后需要适当的等待,有的时候切换过程没有那么快
time.sleep(0.5)
driver.find_element_by_id('switcher_plogin')
#方式三:iframe切换
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it("login_frame_qq"))
time.sleep(0.5)#最好加上等待方便切换。
#从iframe当中回到默认的页面当中。
# 默认的页面就是访问一个网址,默认加载的,在f12中,看到的第一个html是它的主页面。
driver.switch_to.default_content()
driver.switch_to.parent_frame()
对于Windows系统而言,大家都有自己的控件,控件都有自己的Handle
1.首页知道目前有多少窗口打开的。
2.窗口的句柄是哪些。
3.然后找到句柄切过去。
handles=driver.window_handles
print(handles)
谁先打开谁就先排第一位,后打开的排后面,根据窗口打开的先后顺序来排序。一般来说,新打开的窗口都是排在最后的。
send_keys()
输入操作
click()
点击操作
在写代码,调试代码的阶段,不需要把quit
加上,如果运行的过程中有一个地方报错了,不要着急把窗口关闭,先看看报错信息是什么,然后直接在运行结果页面调试的,按f12。
按ctrl+f,确认你的定位表达式在运行结果的页面中是否也可靠,直接在运行结果页面调试,这是初期最主要的调试手段。
图中就是句柄的id。
new_window_is_opened()
遇到性能比较差,打开新的浏览器比较慢的时候,用这个new_window_is_opened()
等待新的窗口出现之后再去操作,比较稳妥。
from selenium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
#web自动化有8种定位方式在By这个类中,详情可以看源码。
#启动谷歌浏览器,开启与浏览器之间的会话。
driver=webdriver.Chrome(service_log_path="D://chromedriver_service.log")
# 最大化一下窗口
driver.maximize_window()
# 全局等待--隐性等待
# driver.implicitly_wait(30)
#访问网页
driver.get("http://www.baidu.com")#写全网址的路径。
driver.find_element_by_id("kw").send_keys("柠檬班")
driver.find_element_by_id("su").click()
WebDriverWait(driver,20).until(EC.visibility_of_element_located((By.XPATH,'//a[contains(text(),"吧_百度贴吧")]')))
# 第一步:获取窗口的总数以及句柄是多少 新打开的窗口,位于最后一个
handles=driver.window_handles #总数为2
#操作,引起了窗口数量的变化,窗口数量会变为3
driver.find_element_by_xpath('//a[contains(text(),"吧_百度贴吧")]').click()
# 等待新的窗口出现
WebDriverWait(driver,10).until(EC.new_window_is_opened(handles))
# 重新获取一次窗口总数
handles=driver.window_handles #总数为3
#切换最新打开的窗口
driver.switch_to.window(handles[-1])
# time.sleep(0.5)
# 切换二 窗口切换
# 第一步:获取窗口的总数以及句柄是多少 新打开的窗口,位于最后一个
# handles=driver.window_handles#获取当前浏览器所有打开的句柄
# 返回是一个列表对象,列表中存储的是句柄的名字
# print(handles)
#当前窗口的句柄
print(driver.current_window_handle)
#第二步:切换
# driver.switch_to.window(handles[-1])
# 新的页面打开,人家加载也是需要时间的,时刻要有等待的思想。
# 新的窗口页面操作。
WebDriverWait(driver,20).until(EC.visibility_of_element_located((By.ID,'j_head_focus_btn')))
driver.find_element_by_id('j_head_focus_btn').click()
# j_head_focus_btn 关注
# 这个类判定新的窗口是否打开
EC.new_window_is_opened
如果是自己写的页面,可以用driver.get(文件路径)
访问本地文件。
如果你写的代码是因为某个操作,例如点击某个按钮导致弹框出现,或者是加载完成出现。无论是哪种情况,先利用自动化代码让弹框出现,出现了之后才能够对alert弹框处理。
想接受alert.accept()
想拒绝alert.dismiss()
获取文本print(alert.text)
WebDriverWait(driver,10).until(EC.alert_is_present())
它是有返回值,但是目前它是作为条件,我们没有办法接收到。
因为我们WebDriver是根据条件的结果是true还是false,来断定是否成立的。所以,我们即使确认alert弹框出现了,我们自己想要对它进行下一步处理的时候,还是要driver.switch_to.alert
自己再切一次,不然就不好处理了。
注意:不要同时打开多个自动化窗口,相互之间可能会有影响,这样不太好。
sleep()
implicitly_wait()
等待+条件
是最常用的方式,是未来app以及框架当中主用的等待方式。
driver.switch_to.frame/window/alert
3种切换当中,各自有各自的特征,我们都可以使用到条件WebDriverWait(driver,10).until(EC.alert_is_present())
当中对应的方法以及它的每一个步骤和套路。
例如窗口切换的句柄,获取句柄总数,然后通过句柄所在的窗口位置来切换。
iframe的下标,name属性,WebElement对象都是可以切换的。如果使用EC的frame切换的话,主动帮我们切换了,就不用管了。
from selenium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
#web自动化有8种定位方式在By这个类中,详情可以看源码。
#启动谷歌浏览器,开启与浏览器之间的会话。
driver=webdriver.Chrome(service_log_path="D://chromedriver_service.log")
# 最大化一下窗口
driver.maximize_window()
# 全局等待--隐性等待
# driver.implicitly_wait(30)
#访问网页
# 文件和它同级目录,试试不传入路径就传文件名
driver.get(r"C:\Users\18210\Desktop\python\python11_web\\lesson1_20181206_html页面.html")#写全网址的路径。
#判定这个弹框是否呈现
# 因为某个操作导致弹框出现,可以等待一下,等到这个窗口出现
# 等待alert出现
WebDriverWait(driver,10).until(EC.alert_is_present())
# alert切换 不是html页面元素
alert=driver.switch_to.alert
#打印弹出框的内容
print(alert.text)
# 关闭弹出框
alert.accept()
#想拒绝
# alert.dismiss()