web自动化学习笔记
1、尽量做到唯一定位,而不是在一堆元素中选一个。
2、基本的八种元素定位:id,name,class_name,tag_name,link_text,partial_link_text,xpath,css
3、xpath在Chrome开发者工具里面可以直接复制路径,如://*[@id="kw"],这是相对定位的方式,很简洁,但这只局限于部分简单的元素,
在项目中大部分的元素如果采用直接cope的方式,你会发现它使用的是绝对定位的方式,如:/html/body/div[3]/div[4]/div[2]/div/div[1],
这种定位很脆弱,前端只要对html页面结构进行一些修改,比如加一个div,那这种定位就会立即失效。所以在真实的项目中都会采用相对定位的方式去定位元素。
所以尽量不要使用绝对路径和下标去定位,选择元素稳定的属性。
4、相对定位是以//开头的,不依赖于页面的顺序和位置。绝对定位是以/开头。
5、例如百度首页的“登录”,//*[@id="u1"]/a[7] , //*[@id="u1"]/a[@name='tj_login'] ,//*[@id="u1"]/a[text()='登录']都可以定位到。
6、xpath定位:
文本定位,//a[text()='hahahah']
模糊定位: //input[contains(@class,'abc')],//input[contains(text(),'abcde')],//div[starts-with(@href,'http')],//div[ends-with(@href,'com')]
逻辑定位://div[@id='hehe' and/or @class='haha']
有的页面有动态id,并且id中一部分是不变的,就可用contains定位。
7、显示等待就跟断言差不多,满足条件就执行下一步,不满足就抛异常,不局限于页面元素,如判断新窗口是否打开,打开则执行下一步,
而隐式等待仅仅只针对于页面元素而言,没定位到,则等会继续定位,直到超时抛出异常。
8、selenium中元素的基本操作:
clear():清除文本
send_keys(value):按键模拟输入
click():单击元素
submit():提交表单,例如,在输入框输入关键字之后的回车操作,就可以通过该方法模拟
size:返回元素的尺寸
text:返回元素的内容
get_attribute(name):返回元素属性的值
is_displayed():设置该元素是否用户可见
9、三种等待
强制等待sleep:不够灵活,有时会浪费时间,不建议在实际项目中使用,多用于脚本调试;
隐式等待implicitly_wait(time):针对页面,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间结束,然后执行下一步。
这样的隐式等待会有个坑,我们都知道js一般都是放在我们的body的最后进行加载,实际这是页面上的元素都已经加载完毕,我们却还在等待全部页面加载结束。隐式等待对整个driver周期都起作用,在最开始设置一次就可以了。
显式等待WebDriverWait:程序每隔0.5秒(默认)检索一下页面,如果给定的条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException。
隐式等待和显示等待都存在时,超时时间取二者中较大的。
至于等待的条件expected_conditions,那真是五花八门:
locator = (By.ID,'kw')
driver.get(base_url)
WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道"))
'''判断title,返回布尔值'''
WebDriverWait(driver,10).until(EC.title_contains(u"百度一下"))
'''判断title,返回布尔值'''
WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'kw')))
'''判断某个元素是否被加到了dom树里,并不代表该元素一定可见,如果定位到就返回WebElement'''
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,'su')))
'''判断某个元素是否被添加到了dom里并且可见,可见代表元素可显示且宽和高都大于0'''
WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value='kw')))
'''判断元素是否可见,如果可见就返回这个元素'''
WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'.mnav')))
'''判断是否至少有1个元素存在于dom树中,如果定位到就返回列表'''
WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,'.mnav')))
'''判断是否至少有一个元素在页面中可见,如果定位到就返回列表'''
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,"//*[@id='u1']/a[8]"),u'设置'))
'''判断指定的元素中是否包含了预期的字符串,返回布尔值'''
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,'#su'),u'百度一下'))
'''判断指定元素的属性值中是否包含了预期的字符串,返回布尔值'''
#WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it(locator))
'''判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False'''
#注意这里并没有一个frame可以切换进去
WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,'#swfEveryCookieWrap')))
'''判断某个元素在是否存在于dom或不可见,如果可见返回False,不可见返回这个元素'''
#注意#swfEveryCookieWrap在此页面中是一个隐藏的元素
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//*[@id='u1']/a[8]"))).click()
'''判断某个元素中是否可见并且是enable的,代表可点击'''
driver.find_element_by_xpath("//*[@id='wrapper']/div[6]/a[1]").click()
#WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//*[@id='wrapper']/div[6]/a[1]"))).click()
#WebDriverWait(driver,10).until(EC.staleness_of(driver.find_element(By.ID,'su')))
'''等待某个元素从dom树中移除'''
#这里没有找到合适的例子
WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,"//*[@id='nr']/option[1]")))
'''判断某个元素是否被选中了,一般用在下拉列表'''
WebDriverWait(driver,10).until(EC.element_selection_state_to_be(driver.find_element(By.XPATH,"//*[@id='nr']/option[1]"),True))
'''判断某个元素的选中状态是否符合预期'''
WebDriverWait(driver,10).until(EC.element_located_selection_state_to_be((By.XPATH,"//*[@id='nr']/option[1]"),True))
'''判断某个元素的选中状态是否符合预期'''
driver.find_element_by_xpath(".//*[@id='gxszButton']/a[1]").click()
instance = WebDriverWait(driver,10).until(EC.alert_is_present())
'''判断页面上是否存在alert,如果有就切换到alert并返回alert的内容'''
print instance.text
instance.accept()
10、iframe切换:iframe本质上就是一个标签,以腾讯课堂的登录界面为例
下标切换:driver.switch_to.frame(2) 从0开始
name属性切换:driver.switch_to.frame("login_frame_qq")
元素定位切换:driver.switch_to.frame(driver.find_element_by_name("login_frame_qq"))
显示等待切换:WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it("login_frame_qq"))
从iframe切回到原来的页面:driver.switch_to.default_content()
若内嵌多层iframe,回到上一层iframe:driver.switch_to.parent_frame()
11、通过窗口句柄切换窗口:
handles = driver.window_handles #所有句柄,列表
handle = driver.current_window_handle #当前窗口句柄
driver.switch_to.window(handles[-1]) #切换到最后一个,最新打开的那个
12、弹框alert处理
WebDriverWait(driver,10).until(EC.alert_is_present()) 等待可见
alert = driver.switch_to.alert 切入
print(alert.text) 获取弹出框文本
alert.accept() 接受
alert.dismiss() 取消
13、鼠标操作
先找到鼠标要操作的元素:
ele = driver.find_element_by_xpath("//*[@id='u1']//a[@name='tj_settingicon']")
实例化ActionChains类:ac = ActionChains(driver)
#鼠标悬停:ac.move_to_element(ele)
调用perform()来执行鼠标操作:ac.perform()
由于ActionChains类里面的方法除了perform其他都是return self,返回类的实例,所以支持链式调用:
ActionChains(driver).move_to_element(ele).perform()
# 鼠标双击
ActionChains(driver).double_click(ele).perform()
# 鼠标右键
ActionChains(driver).context_click(ele).perform()
14、键盘操作:
send_keys(Keys.CONTROL,'a') Ctrl+A 全选 组合键
send_keys(Keys.CONTROL,'c') Ctrl+C 复制
send_keys(Keys.CONTROL,'x') Ctrl+X 剪切
send_keys(Keys.CONTROL,'v') Ctrl+V 粘贴
Keys.TAB Keys.F5 Keys.SPACE
实例:百度输入搜索
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.implicitly_wait(20)
driver.get('http://www.baidu.com')
driver.find_element_by_xpath("//*[@id='kw']").send_keys("刘亦菲")
driver.find_element_by_xpath("//*[@id='kw']").send_keys(Keys.ENTER)
15、要定位鼠标悬停才能出现的元素时,可使用ctrl+shift+c快捷键,让下拉内容显示出来,或者直接悬停后通过link_text来定位
driver.find_element_by_link_text('高级搜索').click()
16.select下拉列表,以百度首页设置-高级搜索里面的下拉列表为例:
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import time
from selenium import webdriver
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome()
driver.implicitly_wait(20)
driver.get('http://www.baidu.com')
# 定位到select元素
ele = driver.find_element_by_link_text('设置')
# ele = driver.find_element_by_xpath("//*[@id='u1']/a[@name='tj_settingicon']")
ActionChains(driver).move_to_element(ele).perform()
driver.find_element_by_link_text('高级搜索').click()
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.XPATH,"//select[@name='ft']")))
select_ele = driver.find_element_by_xpath("//select[@name='ft']")
# 实例化Select类
s = Select(select_ele)
# 直接选,三种方式
s.select_by_index(4)
time.sleep(0.5)
s.select_by_value("doc")
time.sleep(0.5)
s.select_by_visible_text("所有格式")
17、通过执行JavaScript代码去拖拽滚动条:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.implicitly_wait(20)
driver.get('http://www.baidu.com')
driver.maximize_window()
driver.find_element_by_id('kw').send_keys('刘亦菲',Keys.ENTER)
# 上面点击搜索后应等待元素加载完毕再去定位元素,否则会报错,找不到
WebDriverWait(driver,20).until(EC.visibility_of_element_located((By.XPATH,"//div[@id='6']//h3//a")))
# 刘亦菲的个人微博,当然,id会有变化
lyf_ele = driver.find_element_by_xpath("//div[@id='6']//h3//a")
# 找一个不在当前显示区域的元素,若直接去点击会报错,应该下拉到那个元素,将他在显示区域置顶或置底
time.sleep(2)
# 滚动条拉到指定元素位置
driver.execute_script("arguments[0].scrollIntoView(false);",lyf_ele)
# driver.execute_script("arguments[0].scrollIntoView();",lyf_ele) # 会被顶部盖住
time.sleep(2)
lyf_ele.click()
# WebDriverWait(driver,20).until(EC.visibility_of_all_elements_located)
# WebDriverWait(driver,20).until(EC.presence_of_all_elements_located)
driver.switch_to.window(driver.window_handles[-1]) # 打开一个新窗口后一定要记住要切换窗口,老是忘记!!!
driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") # 拉到页面底部
time.sleep(2)
driver.execute_script("window.scrollTo(0,0)") # 拉到页面顶部
time.sleep(2)
driver.execute_script("window.scrollTo(0,200)") # 下拉200个像素
time.sleep(2)
driver.set_window_size(600, 500) # 缩小窗口,出现横向滚动条
time.sleep(2)
driver.execute_script("window.scrollTo(document.body.scrollWidth,0)") # 移到最右边
time.sleep(2)
driver.execute_script("window.scrollTo(0,0)") # 拉到页面最左边
time.sleep(2)
driver.execute_script("window.scrollTo(200,0)") # 右拉200个像素
time.sleep(2)
driver.quit()
#获取当前窗口的宽度和高度:document.body.scrollWidth 、document.body.scrollHeight
18、js处理12306网站日期选择弹出框,改只读为可写:
driver = webdriver.Chrome()
driver.implicitly_wait(20)
driver.get('https://www.12306.cn/index/')
js = "var ele = document.getElementById('train_date');ele.readOnly=false;ele.value='2019-10-01'"
driver.execute_script(js)
driver.find_element_by_id('search_one').click()
time.sleep(1)
driver.quit()
未完待续...