报错一:Exception1:no such element(没有在页面上找到这个元素)
reason1:元素延迟加载
solution:添加隐式等待
#超时时间10s,10秒内一旦加载完成,就执行下一条语句;如果10秒内页面都没有加载完,就超时抛出异常。
driver.implicitly_wait(10)
reason2:元素定位器错误(id动态变化掉,拼写错误等)
solution:将元素放到控制台中,查看是否定位到
或者在console中,使用$x(‘xpath’)调试
reason3:嵌套了iframe
solution:在selenium里面,每一个iframe和网页本身都是被分割开来的独立部分,必须进入到iframe,才能看到
# 切换进入iframe
frame = driver.find_element(By.XPATH, '//*[@id="layui-layer-iframe1"]')
driver.switch_to.frame(frame)
# 一定要最后退出iframe(最外层)
driver.switch_to.default_content()
reason4:元素切换到了另一个窗口
solution:
若网页打开了新窗口,希望在新打开的窗口上定位操作元素,就必须把窗口切换过去
# 切换窗口
handles = driver.window_handles
print(handles)
# # 按下标切换,每次都切换到新的页面
# driver.switch_to.window(handles[-1])
#或者直接访问跳转后的URL,不通过handles进行切换
# 按title切换
for h in handles:
driver.switch_to.window(h)
if driver.title.__contains__('我的订单'):
break
报错二:Exception2:element not interactable(元素不可交互)
reason1:被遮住了
solution:
如果是弹窗类遮住了,就把弹窗关闭,让它显示出来。
reason2:没有显示出来
solution:
元素需要前置操作,或者特殊操作才能显示出来。
报错三:Exception3:element not attached to the page document(元素还没有显示到页面上)
reason:元素存在,但需要在前端渲染
solution:
元素已经找到了,但是还没有正式显示到网页上,需要进行前端加载(比如js动态加载)
对于这种情况,隐式等待、显示等待都没有用了,只能使用固定等待
time.sleep(1)
XPATH详解:
Xpath 是一种用在 XML 文档中定位元素的语言,同样也支持 HTML 元素的解析。
绝对xpath:它其实是标签的层级路径
绝对路径从 HTML 根节点开始算,
此种定位方式很不稳定,只要元素前面多出元素就有可能影响xpath的准确性
相对xpath:它其实是通过属性定位元素
相对路径从任意节点开始
此种方式定位灵活,且相对稳定
相对xpath的结构
表达式 | 说明 |
---|---|
/ | 代表路径 |
// | 代表在当前路径下查找(比如以//开头,就是在整个HTML里面找) |
* 或者 标签名 | //* (所有标签) //a (所有元素里面的a标签) |
[] 里面写筛选条件 | [@id=“username”] 筛选id为username的元素 |
@属性 | id,name…… (凡是标签名里面的都是属性的键值对) |
特殊属性 | 特殊属性 text() (元素的文本值) //a[text()=“个人信息”] |
contains | 包含 (属性值或者文本值包含) //a[contains(text(),“个人信息”)] |
N大特殊场景:
场景一:IE浏览器或者其他浏览器,有些点击无效
解决:js点击
场景二:需要先将鼠标移动到元素上(悬停:hover)
解决:使用selenium提供的鼠标操作类
# 在driver浏览器上面,创建selenium的鼠标操作类的对象
action = ActionChains(driver)
# 把鼠标移动到元素上,perform是使操作生效
action.move_to_element(ele).perform()
场景三:文件图片上传(批量上传)
解决:检查上传按钮,在按钮附近找到一个<input type="file"这样的标签
# 单文件上传
driver.find_element(By.XPATH, '//*[@id="filePicker"]/div[2]/input').send_keys(r'C:\Users\Amy\Desktop\will.png')
# 多文件上传
driver.find_element(By.XPATH, '//*[@id="filePicker"]/div[2]/input').send_keys('\n'.join([r'C:\Users\xxx\Desktop\xxx.png',r'C:\Users\xxxx\Desktop\xxxx.png']))
场景四:关联型xpath(轴定位xpath)
解决:使用轴定位编写xpath
$x('//span[text()="老Will"]/../../li//a[text()="删除"]')
# 祖先元素
# //span[text()="老Will"]/ancestor::div[1] 最近一个
# //span[text()="老Will"]/ancestor::div 最古老一个
$x('//span[text()="老will"]/ancestor::ul//a[text()="删除"]')
# 兄弟元素
$x('//a[text()="地址管理"]/../preceding-sibling::li[3]')
$x('//a[contains(text(),"小诸葛1")]/.././following-sibling::div[1]//a[text()="加入购物车"]')
场景五:数据提取
解决:可通过正则进行匹配想要的内容
s = '订单号: 202203232203535547 | 付款金额(元): 960.00 元'
orderid = re.findall(r'\d{18}',s)
print(orderid)
场景六:获取元素属性
解决:获取元素属性
ele=driver.find_element_by_xpath('//input[@class="save"]')
t=ele.get_attribute('value')
print(t)
场景七:select标签的下拉框
#下拉框的定位
ele1=driver.find_element_by_xpath('//*[@id="province"]')
ele1.click()
select=Select(ele1)
#通过value定位
select.select_by_value("338")
ele1=driver.find_element_by_xpath('//*[@id="city"]')
ele1.click()
select=Select(ele1)
#通过文本值定位
select.select_by_visible_text("市辖区")
场景七:显示等待
对指定元素进行等待的一种等待方式。通过设置最大等待时间、检查频率,对页面的元素来进行等待,一旦找到元素,则停止等待,进入后续步骤。
缺点:
1、使用相对比较复杂;
2、和强制等待类似,每一行等待只执行一次,如果要进行多个元素的等待,则需要多次写入。
优点:
等待判断准确,不会浪费多余的等待时间,在用例中使用,可以提高执行效率
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
driver:浏览器驱动
timeout:最大等待时间
poll_frequency:检测的间隔时间,默认0.5
ignored_exceptions:超时后的异常信息,默认抛出NoSuchElementException
#expected_conditions是selenium的一个模块,其中包含一系列可用于判断的条件:
#官网链接:selenium.webdriver.support.expected_conditions — Selenium 4.6 documentation
from selenium.webdriver.support import expected_conditions as EC
# 显示等待
# 等待元素的文本属性包含:已上传1份
# 每隔0.5s判断一次,直到10s,就报错
# 判断条件,是//div[@class="info"]元素的文本内容包含:已上传1份
#判断某个元素中的text是否 包含 了预期的字符串
WebDriverWait(driver, 10, 0.5).until(
EC.text_to_be_present_in_element((By.XPATH, '//div[@class="info"]'), '已上传1份'))
场景八:IE浏览器或者其他浏览器,有些点击无效
解决:通过js点击
ele = self.__find_ele(lo)
if self.br == 'ie':
self.driver.execute_script('arguments[0].click()', ele)
else:
ele.click()