selenium常见问题笔记
import time
import allure
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.maximize_window()
'''
常见的定位方式:
1、id:针对元素的id进行定位—driver.find_element_by_id('值')
2、name:针对元素的name属性进行定位—driver.find_element_by_name('值')
3、className:针对元素的class属性进行定位,但是属性值中包含空格时不能定位,可以通过拆分,只输入部分值来进行定位—driver.find_element_by_class_name('值')
4、tagName:一般用在标签下
5、linkText :专门针对a标签定位—driver.find_element_by_link_text('文本内容')
6、partialLinkText:表示定位a标签并且模糊匹配内容-driver.find_element_by_partial_link_text('文本内容')
7、cssSelector:driver.find_element_by_css_selector('右键复制出来的值')
8、xpath:最常用的定位方式driver.find_element_by_xpath('右键复制出来值')
一般优先选择id,id找不到用Xpath,如果还不行,使用classname会好一些,如果是链接使用link
'''
driver.page_source()
1、下拉框的选择:
(1)、使用select定位(Select只对<select>标签的下拉菜单有效)
首先定位到下拉框的位置:
se = driver.find_element_by_xpath('')
选中下拉框元素->选择子元素
Select(se).select_by_visible_text('文本')
Select提供了三种选择方法:
select_by_index(index) ——通过选项的顺序,第一个为 0
select_by_value(value) ——通过value属性
select_by_visible_text(text) ——通过选项可见文本
Select提供了四种方法取消选择:
deselect_by_index(index)
deselect_by_value(value)
deselect_by_visible_text(text)
deselect_all()
(2)、定位非<select>标签的下拉菜单中的选项,需要两个步骤,先定位到下拉菜单,再对其中的选项进行定位。
首先定位ul元素的位置(使用Xpath定位不到就使用css试试)
ul = driver.find_element_by_css_selector('body > div.el-menu--horizontal.idaas_menu_popper > ul')
然后在ul的基础上定位li列表下的值
ul.find_element_by_xpath('li[1]').click()
(3、)输入检索式选择框
先定位输入框
然后输入值
driver.find_element_by_id('id').send_keys('ab')
检索列表的值获取需要的
ul = driver.find_element_by_css_selector(".ui-autocomplete-items")
li = ul.find_elements_by_tag_name('li')
执行操作
li[0].click()
2、鼠标操作
dk = ActionChains(driver)
dk.double_click(driver.find_element_by_xpath(''))
dk.perform()
ActionChains(driver).double_click(driver.find_element_by_xpath('')).perform()
context_click() 右击
double_click() 双击
drag_and_drop() 拖动
move_to_element() 鼠标悬浮在一个元素上
click_and_hold() 按下鼠标左键在一个元素上不松开
3、弹窗定位
(1)div弹窗:普通方法定位就可以,可能需要一个等待时间
(2)新标签页弹窗:新标签页弹窗,则需要进行窗口的切换。此处第一个窗口打开百度首页,在打开一个新窗口打开京东首页,在两个窗口之间进行切换
页面切换可以使用
winds = driver.window_handles
driver.switch_to.window(winds[0])
driver.current_window_handle()
(3)alert弹窗
1.警告类弹alert(),显示警告或其他信息,用于通知用户,下方只有一个【确认】按钮。
2.确认类弹窗confirm(),询问是否继续某种操作等功能,下方有【确认】和【取消】两种按钮。
3.消息类弹窗prompt(),需要输入一些信息,比如用户密码等,下方会有【确认】和【取消】按扭
在 WebDriver 中处理 JavaScript 所生成的 alert、confirm 以及 prompt 是很简单的。具体做法是使用
switch_to_alert()方法定位到 alert/confirm/prompt
accept 点击确认按钮。:driver.switch_to.alert.accept()
dismiss 点击取消按钮,如果有的话。:driver.switch_to.alert.dismiss()
send_keys 输入值,这个 alert\confirm 没有对话框就不能用了,不然会报错:driver.switch_to.alert.send_keys('')
text 获取文本内容:driver.switch_to.alert.text
(4)对于一些一闪而逝的提示信息,我们可以调用鼠标把鼠标悬浮在提示信息上,确保提示信息一直在
(5)对于一些内嵌的网页元素定位需要切换到需要操作的框架上用到的是frame方法
判断:一个页面存在多个html,标志性的文字是iframe标签
流程:先定位到iframe窗口,切换到这个窗口:
driver.switch_to.frame('id')
一般使用的是iframe标签后的id/name,如果不存在则需要先定位到这个框架
frame = driver.find_element_by_xpath('')
driver.switch_to.frame(frame)
然后定位新框架的元素,进行操作(正常定位就行)
执行之后需要且会原框架使用:
driver.switch_to.default_content()
driver.switch_to.parent_frame()
4、浏览器导航栏的三个按钮:后退、前进、刷新
driver.back()
driver.forward()
driver.refresh()
5、滚动条操作
(1)、如果滚动条是针对整个HTML可以用如下方式:
js = "var q=document.documentElement.scrollTop=10000"
self.driver.execute_script(js)
2、如果滚动条是针对整个body可以用如下方式:
js = "var q=document.body.scrollTop=10000"
self.driver.execute_script(js)
3、如果滚动条是针对某个div可以用如下方式:该页面的滚动条就是针对class='main'的div而言的
js = "var q=document.getElementsByClassName('main')[0].scrollTop = 10000"
self.driver.execute_script(js)
6、等待时间
使用time模块
固定等待时间:time.sleep()
隐性等待:implicitly_wait()
driver.implicitly_wait(),
隐性等待设置了一个时间,在一段时间内网页是否加载完成,
如果完成了,就进行下一步;在设置的时间内没有加载完成,则会报超时加载(针对的是整个页面的元素加载,且是全局性的)
显性等待:WebDriverWait
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 20, 0.5).until(expected_conditions.presence_of_element_located(需要判断的元素定位))
20是超时时间,0.5是刷新时间:他会每0.5秒刷新获取判断条件的信息,直到超时20秒才报错,这里是针对的需要判断的元素。
expected_conditions模块中提供了很多可以提供判断的条件:
selenium.webdriver.support.expected_conditions(模块)
这两个条件类验证title,验证传入的参数title是否等于或包含于driver.title
title_is
title_contains
这两个人条件验证元素是否出现,传入的参数都是元组类型的locator,如(By.ID, 'kw')
顾名思义,一个只要一个符合条件的元素加载出来就通过;另一个必须所有符合条件的元素都加载出来才行
presence_of_element_located
presence_of_all_elements_located
这三个条件验证元素是否可见,前两个传入参数是元组类型的locator,第三个传入WebElement
第一个和第三个其实质是一样的
visibility_of_element_located
invisibility_of_element_located
visibility_of
这两个人条件判断某段文本是否出现在某元素中,一个判断元素的text,一个判断元素的value
text_to_be_present_in_element
text_to_be_present_in_element_value
这个条件判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement
frame_to_be_available_and_switch_to_it
这个条件判断是否有alert出现
alert_is_present
这个条件判断元素是否可点击,传入locator
element_to_be_clickable
这四个条件判断元素是否被选中,第一个条件传入WebElement对象,第二个传入locator元组
第三个传入WebElement对象以及状态,相等返回True,否则返回False
第四个传入locator以及状态,相等返回True,否则返回False
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
最后一个条件判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了
staleness_of
7、文件上传
input标签的文件上传
直接输入需要上传的文件的地址就可以
driver.find_element_by_xpath('').send_keys('D:/11.txt')
非input标签的文件上传
三种方式:
autoIT,借助外力,我们去调用其生成的au3或exe文件
python pywin32库,识别对话框句柄,进而操作
SendKeys库:最简单但是不太稳定,不推荐长期使用
keybd_event,跟3类似,不过是模拟按键,ctrl+a,ctrl+c, ctrl+v
主要讲解:Python的pywin32库,通过识别对话框句柄来进行操作
pywin32库的安装因为文件较大,建议使用豆瓣源直接pip安装:pip install -i https://pypi.douban.com/simple pywin32
使用之前可以借助工具winspy来辅助定位,winspy下载地址:https://sourceforge.net/projects/winspyex/
winspy工具的定位方法采用的是绝对路径定位,即根路径为点击上传按钮后的弹出框的整个窗口页面,一般根据Text文本值和Class属性来定位
最终我们定位到文件路径输入框的Class属性路径为:Edit - combox - comboBoxEx32 -
“打开”按钮通过同样的绝对路径方式定位,得到它的Class属性路径为:button -
pywin32的实现步骤为:
1、找到绝对路径输入框和“打开”按钮的元素;
2、输入绝对路径,点击打开
在页面实现的前提条件为 :windows上传窗口已经出现,可以sleep1~2秒等待上传的弹框出现
代码:
import win32gui
import win32con
def shangchuan(path):
dialog = win32gui.FindWindow('#32770', None)
ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None)
ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None)
Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None)
button = win32gui.FindWindowEx(dialog, 0, 'Button', None)
win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, path)
win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)
多文件上传就是把path文件使用,隔开比如''D:/11.txt','D:/12.txt''
8、cookie处理
driver.get_cookies() 获得 cookie 信息
add_cookie(cookie_dict) 向 cookie 添加会话信息(token也是存在在此处)
特别注意:在添加cookie之前首先要先请求一下这个网址,确保浏览器知道cookie是谁的,然后需要清除之前存在的cookie,
最后写入的时候需要确保写入的cookie是生效的,然后请求你需要访问的这个网站地址就可以,这就免密登陆上了
driver.get('http://cswww.7dingdong.com/#/login')
time.sleep(2)
driver.delete_all_cookies()
list_cookie=[{},{},{}]
for aa in list_cookie:
driver.add_cookie(aa)
driver.get('http://cswww.7dingdong.com/b2b/b2bchoiceList')
delete_cookie(name) 删除特定(部分)的 cookie
delete_all_cookies() 删除所有 cookie
9、常用的js操作(https://www.cnblogs.com/tobecrazy/p/4817946.html)
对input执行输入:直接设置value属性, 此方法主要应对输入框自动补全以及readonly属性的element,sendkeys不稳定
js='document.getElementById("nice").setAttribute("title","测试title")'
js='document.getElementById("nice").removeAttribute("title")'
js='document.getElementById("nice").getAttribute("title")'
js='document.getELementById("nice").title="测试"'
需要再执行js操作
driver.execute_script(js)
去掉只读属性
e = driver.find_element()
driver.execute_script('arguments[0].removeAttribute("readonly")', e)
常用脚本:
获取页面的标题document.title:driver.execute_script('dociment.title')
页面弹框window.alert("页面弹框")
获取当前页面的性能JSON.stringify(performance.timing)
滑动页面到底部:document.documentElement.scrollTop=10000
滑动页面到顶部:document.documentElement.scrollTop=0
通过js去定位元素:document.getElementById('el-icon-git-pause')
10、截取屏幕(https://blog.csdn.net/DansonC)
截取整个屏幕(需要安装pillow包)
from PIL import ImageGrab
im = ImageGrab.grab()
im.save('1.jpg','jpeg')
对浏览器进行截图:调用get_screenshot_as_file(filename)方法,对浏览器截图
driver.get_screenshot_as_file(r'11.png')
11、隐藏元素的操作
定位隐藏要素的原理:页面主要通过“display:none”来控制元素不可见。
所以我们需要通过javaScript修改display的值得值为display="block,来实现元素定位的
隐藏元素代码:
<header id="header">
<a href="#" class="logo"><strong id="Title" style="display: none">AAAA</strong></a>
</header>
实现定位隐藏代码操作:
js = "document.getElementById('Title').style.display='block'"
driver.execute_script(js)
contentText = driver.find_element_by_id('Title').text
print(contentText)
12、日历中的日期操作
可以通过一层层点击实现日期选择。这里需要注意窗口的切换frame
通过js操作日期控件,通过我们开发者工具观察,input标签由于readonly 属性,所以日期控件是不允许输入的,那么我们主要通过js来删除或者readonly制成否,这样可以直接允许输入。
删除readonly属性:
通过js操作,首先我们需要定位到input标签,然后再次删除readonly属性
js = "$('input:eq(0)').removeAttr('readonly')"
修改readonly属性:
通过js操作,首先我们需要定位到input标签,然后readonly 是false
js = "$('input:eq(0)').attr('readonly',false)"
调用execute_script方法来执行js,来处理时间控件,然后我们可以直接输入日期。
driver.execute_script(js)
driver.find_element_by_xpath('').send_keys('2017-9-2')
13、把元素滑动至页面可见位置
self.driver.find_element_by_xpath('下拉框元素位置')
list = self.driver.find_elements_by_xpath('/html/body/div[7]/div[1]/div[1]/ul/li/span')
time.sleep(2)
self.driver.execute_script('window.scrollBy(0,500)')
ele = list[random.randint(0,len(list) -1)]
self.driver.execute_script("arguments[0].scrollIntoView();",ele)
ele.click()
14、按键事件
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys("seleniumm")
driver.find_element_by_id('kw').send_keys(Keys.BACK_SPACE)
driver.find_element_by_id('kw').send_keys(Keys.F5)
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
driver.find_element_by_id("kw").send_keys(u"教程")
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'v')
15、失败截图pytest【待验证】
使用attath标签,添加附件到测试报告详情
allure.attach()
案例:
配置文件conftest.py:执行失败自动截图然后放到测试报告详情中
driver = None
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
'''
获取每个用例状态的钩子函数
:param item:
:param call:
:return:
'''
outcome = yield
rep = outcome.get_result()
if rep.when == "call" and rep.failed:
mode = "a" if os.path.exists("failures") else "w"
with open("failures", mode) as f:
if "tmpdir" in item.fixturenames:
extra = " (%s)" % item.funcargs["tmpdir"]
else:
extra = ""
f.write(rep.nodeid + extra + "\n")
if hasattr(driver, "get_screenshot_as_png"):
with allure.step('添加失败截图...'):
allure.attach(driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)
@pytest.fixture(scope='session')
def browser():
global driver
if driver is None:
driver =webdriver.Chrome()
yield driver
driver.quit()
|