selenium笔记

目录

常用的定位元素与常用方法

官网: http://selenium-python.readthedocs.io/api.html

一、 定位元素方法

(1). 查找单个元素:

find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector

(2). 查找多个元素

find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector

(3).两个私有方法

find_element
find_elements

(4) find_element和find_elements用法:

from selenium.webdriver.common.by import By
 
driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"

(5) find_element_by_xpath用法:

绝对路径:login_form = driver.find_element_by_xpath("/html/body/form[1]")
HTML中的第一个表单元素: login_form = driver.find_element_by_xpath("//form[1]")
属性id=loginForm的元素:login_form = driver.find_element_by_xpath("//form[@id='loginForm']")

(6 )xpath 常用操作

//div/*                 div下面的所有的元素
//div//p                查找div中的p节点,等于 css_selector里的('div p')
//div/p                查找div的子节点p; 等价于 css_selector里的('div > p')   
//*[@style]        查找所有包含style的所有元素,所有的属性要加@,等于('*[style]')
//p[@spec='len']     必须要加引号;等价于 css_selector里的("p[spec='len']")
//p[@id='kw']        xpath中对于id,class与其他元素一视同仁,没有其他的方法
//div/p[2]                   选择div下的第二个p节点 ;等价于css_selector里的div>p:nth-of-type(2)  符合p类型的第二个节点
//div/*[2]                   选择div下第二个元素

//div/p[position()=2]        position()=2   指定第二个位置;  等价于上面的 //div/p[2] 
		  position()>=2      位置大于等于2
          position()<2       位置小于2
          position()!=2     位置不等于2

//div/p[last()]              选择div下的倒数第一个p节点; last()倒数第一个
//div/p[last()-1]            选择div下的倒数第二个p节点;

//div/p[position()=last()]   倒数第一个
//div/p[position()=last()-1] 倒数第二个
//div/p[position()>=last()-2]倒数第一个,第二个,第三个
//p | //button  选择所有的p和button,等价于css_selector里的 p, button

# 多条件
//input[@id='kw' and @class='su']    选择id=kw 并且 class=su的input元素

如果想获取id为food的p节点,还可以这样写
food=driver.find_element_by_id('food').find_element_by_xpath('.//p')

//p[@spec='len']/..      选择p节点的上层节点       此方法在css_selector中没有
//p[@spec='len']/../..   上层节点的上层节点


-------------------------------------------------------------------------
'//div[@class="pos-top"]/select/option[3]'
'//div[@class="inp-w"]/input[@class="inp_selected"]'
'//div[@class="inp-w"]/input[@id="fromStationText"]'
'//tbody[@id="queryLeftTable"]/tr'

'//div[@class="cal-cm"]/div[@style="border: 1px solid rgb(165, 185, 218); background: rgb(193, 217, 255); left: 183px; top: 5px; cursor: pointer;"]/following-sibling::div[1]'

"/bookstore/book[price>35.00]" #  选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
"/bookstore/book[price>35.00]/title	" 

xpath:模糊匹配

"//*[contains(text(), "匹配文本")]"  # 文本模糊匹配
"//*[contains(@id, "匹配文本")]" # 属性名称 模糊匹配
"//*[starts-with(@id, "匹配文本")]" #以什么开头 模糊匹配
"//*[ends-with(@id, "匹配文本")]" #以什么结尾

xpath:正则匹配

"//*[matchs(text(), "匹配文本")]"

6.1 Xpath 倒叙选择

<div id="food" style="margin-top:10px">
   <span class="vegetable good">黄瓜</span>
   <span class="meat">牛肉</span>
   <p class="vegetable">黄瓜pp</span>
   <p class="vegetable">青菜</span>
   
 选择最后一个,也就是倒数第一个
//[@id="food"]/*[last()]
选择倒数第二个
//[@id="food"]/*[last()-1]
选择倒数第三个
//[@id="food"]/*[last()-2]

如果是选择span类型的最后一个
//[@id="food"]/span[last()]

css中选择span类型的最后一个
#food >span:nth-last-of-type(1)
如果是p类型的最后一个
#food >p:nth-last-of-type(1)

选中最后一个
//[@id="food"]/*[position()=last()]
选中最后两个
//[@id="food"]/*[position()>=last()-1]
last()-1是倒数第二个

6.2 组元素的选择

在css中 组元素之间用逗号隔开
比如 p , button
在xpath中用 | 隔开
//p | //button

6.3 相邻兄弟选择器

  • following-sibling (选择后面的兄弟节点)

  • preceding-sibling (选择前面的兄弟节点)

    <div clsaa="top">...<div>
    <div id="food" style="margin-top:10px">
       <span class="vegetable good">黄瓜</span>
       <span class="meat">牛肉</span>
       <p class="vegetable">黄瓜pp</span>
       <p class="vegetable">青菜</span>
    
    选择id为food后面的div,两个是相邻元素,也就是属于同一级的兄弟节点
     css中的写法是 : #food ~ div
     
    Xpath中的写法是:
    //[@id="food"]/following-sibling::div    (注意div前面两个冒号)
    
    如果是选择id为food前面的兄弟节点
    //[@id="food"]/preceding-sibling::div
    
    如果是查找前面紧跟着的第一个元素
    //[@id="food"]/preceding-sibling::div[1]
    
    如果找前面紧跟着的第二个
    //[@id="food"]/preceding-sibling::div[2]
    
    如果想要更多范围的,可以加上position,参考上面的方法
    

(7) 判断节点是否存在

def isElementPresent(driver, path):
    #从selenium.common.exceptions 模块导入 NoSuchElementException类
    from selenium.common.exceptions import NoSuchElementException
    try:
        element = driver.find_element_by_xpath(path)
    #原文是except NoSuchElementException, e:
    except NoSuchElementException as e:
        #打印异常信息
        # print(e)
        #发生了NoSuchElementException异常,说明页面中未找到该元素,返回False
        return False
    else:
        #没有发生异常,表示在页面中找到了该元素,返回True
        return True
 
res = isElementPresent(driver, "/html/div")
if res is True:
    # -----

(8) 复杂页面元素定位方法

driver.find_element_by_xpath('//a[@aria-label="{}"]/parent::td/preceding-sibling::td[@width="2%"]/span/input[@type="checkbox"]'.format(i.strip())).click()

(9) 滚动滚动条到指定的页面元素element

driver.execute_script("arguments[0].click();", element)

二、driver 常用方法和一些常用操作

(1) 获取网页/文本

-  driver.get(url)      请求某个URL对应的响应(自己公司未配置域名是是IP)
-  driver.refresh()     刷新页面操作
-  driver.back()      回退到之前页面(163的网页好像有问题,回退无效)
-  driver.forward()     前进到之后页面

-  driver.current_url #获取当前访问网页的url:
-  driver.title #获取浏览器顶部标题:
-  driver.get_screenshot_as_file('起点.png') #保存图片:
   driver.get_screenshot_as_file('起点.png') # 保存图片第一种方式

  • driver.get_screenshot_as_png() #保存图片第二种方式(此方式在selenium2中需要手动写入文件)
    d = driver.get_screenshot_as_png()
    with open('qidian.png','wb') as f:
    f.write(d)
  •   y = driver.page_source # 获取网页源码
      with open('qidian.html','wb') as f:
          f.write(y.encode())# 将字符串类型转换成二进制类型并写入文件
    
  • get_attribute("outerHTML")    # 输出当前标签的本身和标签内的文本内容,如果有子标签,那么子标签本身和标签内的文本内容也将一起输出
  • get_attribute('innerHTML')     获取当前标签的文本内容,如果标签内有子标签,会连子标签本身和子标签内的文本内容一起输出
  • get_attribute('textContent')  == .text
  • driver.quit() # 关闭浏览器

(2) 操作节点/获取/文本框

- aList[i].get_attribute('src')   #获取标签内的属性值
- aList[i].text  获取标签下的文本

(3)操作输入框

- inputTag = driver.find_element_by_id('kw') # 第一步:找到这个元素
- inputTag.clear()  # 清除输入框中的数据
- inputTag.send_keys('python')  # 使用send_keys(value),将数据填充进去

(4)鼠标点击/复选框点选

- inputTag = driver.find_element_by_id('kw') # 第一步:找到这个元素
- inputTag .click()

(5)下拉框点选操作

  • 一种为select标签

    # 选择select,select元素不能直接点击。因为点击后还需要选中元素。这时候selenium就专门
    # 为select标签提供了一个类,示例:
    from selenium.webdriver.support.ui import Select
    # 选中这个标签,然后使用Select创建对象
    selectTag = Select(driver.find_element_by_name("jumpMenu"))
    # 根据索引选择
    selectTag.select_by_index(1)
    # 根据值选择
    selectTag.select_by_value("http://www.95yueba.com")
    # 根据可视的文本选择
    selectTag.select_by_visible_text("95秀客户端")
    # 取消选中所有选项
    selectTag.deselect_all()
    
  • 一种 ul/li 标签

    self.driver.find_element_by_xpath('//ul[@class="ant_t"]').click() # 点击下拉框小指标
    source = self.driver.find_element_by_xpath('//ul[@class="ant"]') # 找到下拉框中 ul 所以内容
    source_list = source.find_elements_by_tag_name('li')
    for bsr_info in source_list:
    if bsr_info.text == "瞿": # 找到符合自己要的条件
    bsr_info.click() # 点选
    time.sleep(3)
    ​```

(6) ActionChains

ActionChains方法列表

action info
click(on_element=None) 单击鼠标左键
click_and_hold(on_element=None) 点击鼠标左键,不松开
context_click(on_element=None) 点击鼠标右键
double_click(on_element=None) 双击鼠标左键
drag_and_drop(source, target) 拖拽到某个元素然后松开
drag_and_drop_by_offset(source, xoffset, yoffset) 拖拽到某个坐标然后松开
key_down(value, element=None) 按下某个键盘上的键
key_up(value, element=None) 松开某个键
move_by_offset(xoffset, yoffset) 鼠标从当前位置移动到某个坐标
move_to_element(to_element) 鼠标移动到某个元素
move_to_element_with_offset(to_element, xoffset, yoffset) 移动到距某个元素(左上角坐标)多少距离的位置
perform() 执行链中的所有动作
release(on_element=None) 在某个元素位置松开鼠标左键
send_keys(*keys_to_send) 发送某个键到当前焦点的元素
send_keys_to_element(element, *keys_to_send) 发送某个键到指定元素
行为链:有时候在页面中的操作可能要有很多步,那么这时候可以使用鼠标行为链类ActionChains来完成。
6.1, ActionChains(driver)
鼠标移动操作
actions = ActionChains(driver)  # 实例化一个action对象
inputTag = driver.find_element_by_id('kw')
submitTag = driver.find_element_by_id('su')

# 移动操作
actions.move_to_element(inputTag)  # 把鼠标移动到inputTag元素上,鼠标悬停
actions.move_by_offset(10, 20)  # 从当前鼠标的位置向水平方向移动10个像素,向竖直方向移动20个像素

actions.send_keys_to_element(inputTag,'python')
actions.send_keys("追光者")  # 输入“追光者”

# 全选,复制,粘贴(跨浏览器)
actions.key_down(Keys.CONTROL).send_keys(‘a‘).key_up(Keys.CONTROL)  #ctrl+a
actions.key_down(Keys.CONTROL).send_keys(‘c‘).key_up(Keys.CONTROL)  #ctrl+c
actions.key_down(Keys.CONTROL,search_key).send_keys(‘v‘).key_up(Keys.CONTROL)  #ctrl+v
search_key=driver.find_element_by_id("search-key")
search_key.send_keys(Keys.CONTROL,'v')
key_down,发送,只是按下按键,并不会自动松开,而send_keys发送的键,会实现按下-松开的全过程

# 拖拽操作
actions.drag_and_drop(elem1, elem2).perform()  # 把elem1元素拖拽到elem2上
actions.click_and_hold(elem1).release(elem2).perform()  # 在elem1元素上按下鼠标左键不松,在elem2元素上释放,实现拖拽操作

点击操作
actions.click(submitTag)  # 单击
actions.click_and_hold(element)   # 鼠标左键按下不放
actions.context_click(element)  # 右键点击。
actions.double_click(element)  # 鼠标双击。

按下鼠标左键在一个元素上,release()释放

ActionChains(driver).click_and_hold(element).perform()
ActionChains(driver).release(element).perform()
actions.perform()  #  执行所有ActionChains 中存储的行为
6.2 滑动解锁
```
time.sleep(3)
    button = driver.find_element_by_xpath('//*[@id="login-slider"]/div[1]/div[2]/div')
    action = ActionChains(driver)  # 实例化一个action对象
    action.click_and_hold(button).perform()  # 鼠标左键按下不放
    action.move_by_offset(400, 0).perform()  # 平行移动鼠标
    action.reset_actions()
​```
6.3 登录输入
inputTag = driver.find_element_by_xpath('//*[@id="loginPage"]/ul/li[1]/div/input')
inputTag.send_keys('13547584541')
inputTag2 = driver.find_element_by_xpath('//*[@id="loginPage"]/ul/li[2]/div/input')
inputTag2.send_keys('734888')
driver.find_element_by_xpath('//*[@id="loginPage"]/div/button').click()
6.4 鼠标点击
import pyautogui

# 用0.5 秒的时间把光标移动到x,y(437, 151) 位置,y竖向向下增加
pyautogui.moveTo(437, 151, duration=0.5)
pyautogui.click()
pyautogui.click(350, 190, button ='left')# 左击
pyautogui.click(350, 190, button ='right')# 右击
6.5 鼠标操作

​ 关于鼠标的操作封装在ActionChains()类里,所以需要提前导入ActionChains()类;perform() 执行所有 ActionChains 中存储的行为(接在ActionChains类之后)

  导入ActionChains 类:from selenium.webdriver import ActionChains

  格式:ActionChains(浏览器).[行为(需要操作的元素)].perform()

  1.1、鼠标右击与双击操作(单击即click())

    右击操作:ActionChains(浏览器).context_click(需要右击的定位好的元素).perform()

    双击:ActionChains(浏览器).double_click(需要右击的定位好的元素).perform()

from selenium import webdriver
from selenium.webdriver import ActionChains
import time
# 创建一个浏览器对象
driver = webdriver.Firefox()
# 设置浏览器最大化
driver.maximize_window()

# 右击操作:
# 访问百度
url = 'http://www.baidu.com'
driver.get(url)
# 定位元素loge元素
d = driver.find_element_by_css_selector('#s_lg_img')
# 对元素进行鼠标右击操作
'''
ActionChains(driver):使用动作链类对浏览器进行操作
context_click(d):使用动作链类对定位好的d元素进行右击
perform():执行动作链类的操作'''
ActionChains(driver).context_click(d).perform()
time.sleep(2)

# 双击操作:
# 定位元素
ee = driver.find_element_by_link_text('新闻')
# 双击元素
ActionChains(driver).double_click(ee).perform()
time.sleep(2)
# 关闭浏览器
driver.quit()

1.2、鼠标悬停操作

​ 悬停:ActionChains(driver).move_to_element(元素).perform()

# 导入相关的模块
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
# 创建浏览器对象、设为最大化屏幕
driver = webdriver.Firefox()
driver.maximize_window()
# 访问京东
url = 'https://www.jd.com/'
driver.get(url)

# 定位需要鼠标悬停单个元素
xuan = driver.find_element_by_css_selector('li.cate_menu_item:nth-child(1) > a:nth-child(1)')
# 悬停操作
ActionChains(driver).move_to_element(xuan).perform()
time.sleep(3)

# 获取一组悬停的元素,并且一个个遍历
xuans_list = driver.find_elements_by_css_selector('li.cate_menu_item')
# 遍历悬停操作
for el in xuans_list:
    ActionChains(driver).move_to_element(el).perform()
    time.sleep(2)

# 关闭浏览器
driver.quit()
(7) pyHook监听鼠标并打印位置
import pythoncom
import PyHook3 as pyHook
# 监听到鼠标事件调用
def onMouseEvent(event):
	if (event.MessageName == "mouse left down") and (event.MessageName != "mouse move"):
		# 因为鼠标一动就会有很多mouse move,所以把这个过滤下
		x,y = pag.position() #返回鼠标的坐标
		print(x,y)
        return True # 为True才会正常调用,如果为False的话,此次事件被拦截
      # 创建管理器
      hm = pyHook.HookManager()
      # 监听鼠标
      hm.MouseAll = onMouseEvent
      hm.HookMouse()
      # 循环监听
      pythoncom.PumpMessages()
(8)selenium 设置代理ip
from selenium import webdriver
 
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://110.73.2.248:8123")
driver_path = r"D:\ProgramApp\chromedriver\chromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path,chrome_options=options)
 
driver.get('http://xxxxx')
(9) tab页面切换
# 打开一个新的页面
driver.execute_script("window.open('https://xxxxxxxx')")
print(driver.window_handles)
# 切换到这个新的页面中
driver.switch_to_window(self.driver.window_handles[1])
print(driver.current_url)
#注意
#虽然在浏览器窗口中切换到了新的页面,但是driver中还没有切换
#如果想要在代码中切换到新的界面,那么应该使用driver.switch_to_window来切换到指定的窗口
#从driver.window_handles中取出具体第几个窗口
#driver.window_handles是一个列表,里面装的都是窗口句柄,它会按照打开的页面顺序来存储窗口的句柄。
(10) 窗口切换
# 当前打开的所有窗口
windows = driver.window_handles 
 
# 转换到最新打开的窗口
driver.switch_to.window(windows[-1])
 
for handle in windows :  # 切换窗口
    if handle != driver.current_window_handle:
        print('switch to second window', handle)
        driver.close()  # 关闭第一个窗口
        driver.switch_to.window(handle)  # 切换到第二个窗口
(11) html转字符串:
driver.find_element_by_xpath('/html/body').get_attribute("outerHTML").__str__().replace('"', "'")
import json
 
json.loads() 将json转换为dict
json.dumps() 将dict转换为json
json.load() 将json文件转换为dict
json.dump() 将dict转换为json文件 person.json
 
# 类对象转换为json
person_json = json.dumps(person.__dict__)   
 
# 或者
# 第二个参数传递转换函数,或者使用default=lambda o: o.__dict__
person_json = json.dumps(person, default=convert2json)
 
# 将person转换为dict
def convert2json(person):
  return {
    'name': person.name,
    'age': person.age,
    'email': person.email
  }
 
# dict/对象转换为json文件
with open('person.json', 'w') as f:
  json.dump(person, f)
 
# 将json文件转换为dict/对象
import json
with open('person.json', 'r') as f:
  print(json.load(f))
 
 
python json.dumps() 中文乱码问题


(12) 勾选框点选
<input type='chechbox' name='vebicle' value='bike'> 我有一辆自行车
<input type='chechbox' name='vebicle' value='car'> 我有一辆汽车

使用click方法选择
is_selected方法来获取选择的状态


首先判断该元素有没有选中,可以用is_selected方法来获取该元素有没有被选中
input=driver.find_element_by_css_selector( 'input[value=car]')
selected=input.is_selected()  #判断是否选中

if selected:
    print('已经选中了,无需点击')
else:
    print('没有选中,需要点击')
    input.click()
(13) 复选框点选
复选框多选使用select类 (注意:select类只适用于元素必须是select类型的)

先使用deselect_all把勾选的全部去掉
然后在用select_by_visible_text 进行勾选

导入Select类

from selenium.webdriver.support.ui import Select
获取对应的element
select=Select(deiver.find_element_by_id('#multi')

#先去掉所有选择的项
select.deselect_all()
#然后选择

select.select_by_visible_text('雅阁')
select.select_by_visible_text('宝马740')

如果是单选框就直接用
select.select_by_visible_text('男')
(14) 弹出警告/提示窗口的处理(弹出窗口)
(15)键盘操作(按键名称需要大写、组合键里的参数需要小写)

Keys()类提供了键盘上几乎所有按键的方法,原理与鼠标相似;使用键盘操作前需先导入Keys()类,然后配合send_keys()使用

导入Keys()类:from selenium.webdriver.common.keys import Keys

格式:元素.send_keys(Keys.键盘名称) 或组合键方式:元素.send_keys(Keys.CONTROL,'x')

# 导入需要的模块
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
# 创建浏览器对象设置为最大化
driver = webdriver.Firefox()
driver.maximize_window()
# 访问百度
driver.get('http:www.baidu.com')

# 定位输入框
srk = driver.find_element_by_id('kw')
# 输入框输入内容
srk.send_keys('周润发')
time.sleep(1)
# 全选输入框内容
srk.send_keys(Keys.CONTROL,'a')
time.sleep(1)
# 剪切输入框内容
srk.send_keys(Keys.CONTROL,'x')
time.sleep(1)
# 粘贴已经剪切的内容
srk.send_keys(Keys.CONTROL,'v')
time.sleep(1)
# 全选删除内容
srk.send_keys(Keys.CONTROL,'a')
time.sleep(1)
srk.send_keys(Keys.BACK_SPACE)
time.sleep(1)
# 重新输入内容
srk.send_keys('刘德华')
time.sleep(1)
# 全选复制输入框内容
srk.send_keys(Keys.CONTROL,'a')
time.sleep(1)
srk.send_keys(Keys.CONTROL,'c')
time.sleep(1)
srk.send_keys(Keys.CONTROL,'v')
time.sleep(1)
# 使用enter键代替点击搜索动作
srk.send_keys(Keys.ENTER)
time.sleep(3)
# 关闭浏览器
driver.quit()

键盘操作常用内容:

  • send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
  • send_keys(Keys.SPACE) 空格键(Space)
  • send_keys(Keys.TAB) 制表键(Tab)
  • send_keys(Keys.ESCAPE) 回退键(Esc)
  • send_keys(Keys.ENTER) 回车键(Enter)
  • 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)
  • send_keys(Keys.NUMPAD3) 输入键盘数字3(数字及文中 输入一般直接打字即可,此方法较少用)
(14) selenium中隐藏元素、动态元素如何定位 及对应的处理情况

1、如何判断一个页面上元素是否存在?
判断元素存在方法有3种:(存在返回True,不存在返回False)
方法1:用try…except…

def is_element_exsist1(driver, element):
    """
    :param driver: webdriver
    :param locator: tuple
    :return: bool
    """
    try:
        driver.find_element(element)
        return True
    except Exception as msg:
        print("元素 %s 找不到:%s" %(element, msg))
        return False
    
if __name__ == '__main__':
    driver = webdriver.Chrome()
    loc1 = ("id", "bibi")
    print(is_element_exsist1(driver,loc1))

方法2:用elements定义一组元素方法

def is_element_exsist2(driver, element):
    """
    :param driver: webdriver
    :param element: 
    :return: bool
    """
    eles = driver.find_elements(element)
    if len(eles) < 1:
        return False
    else:
        return True
    
if __name__ == '__main__':
    driver = webdriver.Chrome()
    # loc1 = ("id", "bibi")
    # print(is_element_exsist1(driver,loc1))
    loc2 = ("id", "bibi")
    print(is_element_exsist2(driver, loc2))

方法3:结合WebDriverWait和excepted_conditions判断 (强烈推荐!!!)

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

def is_element_exsist3(driver, element):
    """
    :param driver: webdriver
    :param locator: tuple
    :return: bool
    """
    try:
       # 显示等待 判断元素是否存在
        WebDriverWait(driver, 30, 1).until(EC.presence_of_element_located(element))
        return True
    except :
        return False

if __name__ == '__main__':
    driver = webdriver.Chrome()
    # loc1 = ("id", "bibi")
    # print(is_element_exsist1(driver,loc1))
    # loc2 = ("id", "bibi")
    # print(is_element_exsist2(driver, loc2))
    loc3 = ("id", "bibi")
    print(is_element_exsist3(driver, loc3))
(15)、如何提高脚本的稳定性

优化方向:

  1、不要右键复制xpath,自己写相对路径,多用id为节点查找
  2、定位没问题,第二个影响因素就是等待时间了。sleep等待尽量少用(影响执行时间)。                        
     driver.implicity_wait(10)隐式等待也不要用,不要以为是全局的就是好事。有些JS加载失败时候      
     会一直等,并且页面跳转时也无法识别。
  3、定位元素方法重新封装,结合WebDriverWait和excepted_conditions判断元素方法,自己封装一套定位元素方法
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

def find_ele(driver, locator, timeout=30):
    ele = WebDriverWait(driver, timeout, 1).until(EC.presence_of_element_located(locator))
    return ele
16、如何定位动态元素
动态元素有2种情况,一个是属性动态,比如id是动态的,定位时那就不要用id定位。还有一种情况动态的,那就是这个元素一会在页面上方,一会在下方,飘忽不定的动态元素,定位方法一样按F12,根据元素属性定位(元素的tag、name的步伐属性是不会变的,动的只是class属性和styles属性)
17、如何通过子元素定位父元素

selenium里通过父元素定位子元素,可以通过二次定位来找到该元素。

ele=driver.find_element_by_id("parent").find_element_by_id("child")
18、子元素定位父元素
可以通过xpath的语法直接定位:.//*[@name="hell"]/.. 两个点就是代表父级元素了。
19、一个元素明明定位到了,点击无效(也没报错),如何解决?(重点)

使用js点击,selenium有时点击元素是会失效的

# js点击
js = 'document.getElementById("baidu").click()'
driver.execute_script(js)
20、隐藏元素操作

元素的属性隐藏和显示,主要是 type="hidden"和style="display:none;"属性来控制的

定位 type="hidden"隐藏元素 获取 元素属性

ele=driver.find_element_by_id("p")
print("打印元素信息:%s" %ele)
print(ele.get_attribute("name"))

判断元素是否隐藏
print(ele.is_displayed())

-----------------------------------------------------------------------------

隐藏元素可以正常定位到,只是不能操作。操作元素是click,clear,send_keys这些方法。
隐藏输入框元素输入文本:隐藏元素用send_keys()方法会抛异常
ElementNotVisibleException。这个报错是说元素不可见,不可以被操作

(1).JS操作隐藏元素
selenium是无法操作隐藏元素的(但是能正常定位到),本身这个框架就是设计如此。如果非要去操作隐藏元素,那就用js的方法去操作,selenium提供了一个入口可以执行js脚本。

js点击hidden元素

js = 'document.getElementById("baidu").click()'
driver.execute_script(js)

(2) 先用js去掉hidden属性
先用js去掉hidden属性,再用selenium操作

21、Iframe 标签的简单操作
     # 找到 iframe 元素 动态名称情况
        iframeIds = self.browser.execute_script("""var iframes = document.querySelectorAll('iframe');
        var iframeIds = [];
        for (var i = 0; i < iframes.length; i++) {
          iframeIds.push(iframes[i].id);
        }
        return iframeIds;""")
        iframe 切换
        for iframe_element in iframeIds:
            if iframe_element == 'rtf_iframe_defaultpage-dashboard':
                continue
            id_name = self.browser.execute_script("return document.querySelector('iframe').id")
            iframe = self.browser.find_element_by_xpath(f'//iframe[@id="{id_name}"]')
            self.browser.switch_to.frame(iframe)

原文参考: https://www.cnblogs.com/String-song/p/14304230.html

三 、自动填写网页表格程序 填表

​ 原文连接: https://blog.csdn.net/qq_45426233/article/details/99870333

参考代码实例一:

from selenium import webdriver
import time
import xlrd
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select

""""""
url = 'https://reserveamerica.com/xxx'
account_user = 'xxx'
account_password = 'xxx'
wb = xlrd.open_workbook('D://AddNotesandAlerts.xls')
""""""
sheet1 = wb.sheet_by_index(0)
contract = sheet1.col_values(0)[1].strip()
park_name = sheet1.col_values(1)[1].strip()
type_name = sheet1.col_values(2)
error = ''
# Open firefox browser with addons and go to Orms page
driver = webdriver.Firefox(executable_path='D:\Selenium 3.14\geckodriver.exe', timeout=5)
driver.delete_all_cookies()
driver.get(url)
driver.maximize_window()
time.sleep(2)

# Input user name on login page
user_name_element = driver.find_element_by_id('userName')
user_name_element.clear()
user_name_element.send_keys(account_user)

# Input password on login page
user_password_element = driver.find_element_by_id('password')
user_password_element.clear()
user_password_element.send_keys(account_password)

# Login
ok_button = driver.find_element_by_id('okBtnAnchor')
ok_button.click()
time.sleep(2)

# Choose contract
contract_option = driver.find_element_by_xpath("//option[text()='" + contract + " Contract']")
contract_option.click()
time.sleep(2)

# Go to Inventory Manager page
finance_manager = driver.find_element_by_link_text('Inventory Manager')
finance_manager.click()
time.sleep(2)

# Input park name and search
facility_name = driver.find_element_by_id('FacilitySearchCriteria.facilityName')
facility_name.send_keys(park_name)

search_button = driver.find_element_by_xpath('//a[@aria-label="Search"]')
search_button.click()
time.sleep(3)

# Click facility id in search results to facility details page
facility_id = driver.find_element_by_xpath('//tr[@name="e_Glow"]/td/a')
facility_id_num = facility_id.text
facility_id.click()
time.sleep(2)

# Choose Nots and Alerts for Facility Details drop-down list
page_list = driver.find_element_by_id('page_name')
Select(page_list).select_by_value('note_alerts_list_page')
time.sleep(2)

ids_list = []
error_names = []
for m in range(1, len(type_name)):
	type = type_name[m].strip()
	start_date = sheet1.col_values(3)[m].strip()
	end_date = sheet1.col_values(4)[m].strip()
	note_alert_details = sheet1.col_values(5)[m].strip()
	confirmation_letter_option = sheet1.col_values(6)[m].strip()
	printed_permit_option = sheet1.col_values(7)[m].strip()
	call_manager_option = sheet1.col_values(8)[m].strip()
	operations_manager_option = sheet1.col_values(9)[m].strip()
	web_option = sheet1.col_values(10)[m].strip()
	# 1 is Facility and 2 is Loops/Sites
	applies_to_id = str(sheet1.col_values(11)[m]).strip().strip('.0')

	ids_in_excel = sheet1.col_values(12)[m]
	ids = ids_in_excel.strip().split(',')

	if applies_to_id == '1':
		print('Now will add a new facility "{}" for the park "{}"!'.format(type, park_name))
		print('*' * 180)
	else:
		print('Now will add a new "{}" with site names {} for the park "{}"!'.format(type, ids, park_name))
		print('*' * 180)

	# Add a new note or alert
	WebDriverWait(driver, 20, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//a[@aria-label="Add New"]')))
	add_new = driver.find_element_by_xpath('//a[@aria-label="Add New"]')
	add_new.click()
	time.sleep(1)

	# Note/Alert Type
	select_type = driver.find_element_by_id('MessageView.Type')
	Select(select_type).select_by_visible_text(type)

	# Start Date *
	start_date_element = driver.find_element_by_id('MessageView.StartDate_ForDisplay')
	start_date_element.send_keys(start_date)

	# End Date *
	end_date_element = driver.find_element_by_id('MessageView.EndDate_ForDisplay')
	end_date_element.send_keys(end_date)

	# Note/Alert Text *
	message = driver.find_element_by_id('MessageView.message')
	message.send_keys(note_alert_details)

	# Include in Confirmation Letter
	confirm_letter_radio = driver.find_element_by_id('MessageView.IncludeInConfLetter')
	if confirmation_letter_option.strip().lower() == 'true':
		confirm_letter_radio.click()
	else:
		pass

	# Include in Printed Permit
	printed_permit_radio = driver.find_element_by_id('MessageView.includeInPrintedPermit')
	if printed_permit_option.strip().lower() == 'true':
		driver.execute_script("arguments[0].click();", printed_permit_radio)
	else:
		pass

	# Applications: Call Center options
	call_manager = driver.find_element_by_xpath('//input[@aria-label="Call Manager"]')
	if call_manager_option.strip().lower() == 'true':
		driver.execute_script("arguments[0].click();", call_manager)
	else:
		pass

	operations_manager = driver.find_element_by_xpath('//input[@aria-label="Operations Manager"]')
	if operations_manager_option.strip().lower() == 'true':
		driver.execute_script("arguments[0].click();", operations_manager)
	else:
		pass

	# Applications: Web options
	web = driver.find_element_by_xpath('//input[@aria-label="Web"]')
	if web_option.strip().lower() == 'true':
		driver.execute_script("arguments[0].click();", web)
	else:
		pass

	# Applies To: Facility(1) or Loops/Sites(2)
	applies_to_option = driver.find_element_by_id('MessageView.AppliesTo{}'.format(applies_to_id))
	driver.execute_script("arguments[0].click();", applies_to_option)
	time.sleep(2)

	# Click Apply button
	apply = driver.find_element_by_xpath('//a[@aria-label="Apply"]')
	driver.execute_script("arguments[0].click();", apply)
	time.sleep(2)

	if applies_to_id == '2':
		sites_button = driver.find_element_by_xpath('//a[@accesskey="S" and @tabindex="-1"]')
		sites_button.click()
		time.sleep(5)

		try:
			js = 'document.getElementsByTagName("option")[document.getElementsByTagName("option").length-1].value="5000"'
			driver.execute_script(js)
		except Exception as e:
			print(e)
		WebDriverWait(driver, 30, 0.5).until(EC.element_to_be_clickable((By.ID, 'pagingBarRowsPerPage')))
		driver.find_element_by_id('pagingBarRowsPerPage').find_element_by_xpath('option[@value="5000"]').click()
		WebDriverWait(driver, 30, 0.5).until(EC.element_to_be_clickable((By.ID, 'pagingBarRowsPerPage')))

		page_ids = []
		duplicate_ids = []
		page_id_elements = driver.find_elements_by_xpath('//tr[@name="e_Glow"]/td[3]/a')
		for page_id_element in page_id_elements:
			page_ids.append(page_id_element.text)
		# print(page_ids)
		for page_id in page_ids:
			if page_ids.count(page_id) > 1:
				duplicate_ids.append(page_id)
		# print(duplicate_ids)

		error_ids = []
		compare_ids = duplicate_ids + ids
		for compare_id in compare_ids:
			if compare_ids.count(compare_id) <= 2:
				for i in ids:
					try:
						driver.find_element_by_xpath(
							'//a[@aria-label="{}"]/parent::td/preceding-sibling::td[@width="2%"]/span/input[@type="checkbox"]'.format(
								i.strip())).click()
						# time.sleep(0.5)
					except NoSuchElementException as e:
						error_ids.append(i.strip())
						continue
				time.sleep(2)
				driver.find_element_by_xpath('//a[@accesskey="A" and @aria-label="Assign"]').click()
				time.sleep(2)

				# Return to Notes & Alerts page to add new one
				driver.find_element_by_xpath('//li[@class="selected first last"]/a').click()
				break
			else:
				error = 'Note: provided site name(s) "{}" in line "{}" are duplicates on assign page.'.format(compare_id, m)
				# Return to Notes & Alerts page to add new one
				driver.find_element_by_xpath('//li[@class="selected first last"]/a').click()
				break
	else:
		# Return to Notes & Alerts page to add new one
		driver.find_element_by_xpath('//li[@class="selected first last"]/a').click()
	error_names.append(error_ids)

# print(error_names)
for i in range(len(error_names)):
	if len(error_names[i]) > 0:
		message = 'Warning: please review the "{}" line site names: {}'.format(i+1, error_names[i])
		print(f'\033[31m{message}\033[0m')
	else:
		pass
print(f'\033[31m{error}\033[0m')
相关操作封装代码
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException, TimeoutException
import traceback
import time


class BasePage:
	def __init__(self, driver):
		self.driver = driver

    # 对查找单个页面元素进行封装。
	def find_element(self, by, locator):
		by = by.lower()
		element = None
		if by in ['id', 'name', 'xpath', 'class', 'tag', 'link', 'plink']:
			try:
				if by == 'id':
					element = self.driver.find_element_by_id(locator)
				elif by == 'name':
					element = self.driver.find_element_by_name(locator)
				elif by == 'xpath':
					element = self.driver.find_element_by_xpath(locator)
				elif by == 'class':
					element = self.driver.find_element_by_class_name(locator)
				elif by == 'tag':
					element = self.driver.find_element_by_tag_name(locator)
				elif by == 'link':
					element = self.driver.find_element_by_link_text(locator)
				elif by == 'plink':
					element = self.driver.find_element_by_partial_link_text(locator)
				else:
					print('Not find the element "{}"!'.format(locator))
				return element
			except NoSuchElementException as e:
				print(traceback.print_exc())
		else:
			print('Provided a wrong locator "{}"!'.format(locator))
			
    # 对查找多个页面元素进行封装。
	def find_elements(self, by, locator):
		by = by.lower()
		elements = None
		if by in ['id', 'name', 'xpath', 'class', 'tag', 'link', 'plink']:
			try:
				if by == 'id':
					elements = self.driver.find_elements_by_id(locator)
				elif by == 'name':
					elements = self.driver.find_elements_by_name(locator)
				elif by == 'xpath':
					elements = self.driver.find_elements_by_xpath(locator)
				elif by == 'class':
					elements = self.driver.find_elements_by_class_name(locator)
				elif by == 'tag':
					elements = self.driver.find_elements_by_tag_name(locator)
				elif by == 'link':
					elements = self.driver.find_elements_by_link_text(locator)
				elif by == 'plink':
					elements = self.driver.find_elements_by_partial_link_text(locator)
				else:
					print('Not find the element "{}"!'.format(locator))
				return elements
			except NoSuchElementException as e:
				print(traceback.print_exc())
		else:
			print('Provided a wrong locator "{}"!'.format(locator))

	# 点击页面元素
	def click(self, by, locator):
		element = self.find_element(by, locator)
		element.click()

	# 输入框输入新信息
	def type(self, by, locator, value):
		y = [x for x in value if x != '']
		if len(y) > 0:
			element = self.find_element(by, locator)
			element.clear()
			element.send_keys(value.strip())
		else:
			pass

     # 下拉菜单通过可见文本进行选择
	def select(self, by, locator, text):
		y = [x for x in text if x != '']
		if len(y) > 0:
			element = self.find_element(by, locator)
			element_element = Select(element)
			element_element.select_by_visible_text(text.strip())
		else:
			pass

	# 复选按钮勾选时我们需要首先勾掉已选选项
	def uncheck(self, by, locator, options):
		y = [x for x in options if x != '']
		if len(y) > 0:
			elements = self.find_elements(by, locator)
			for element in elements:
				element.click()
		else:
			pass

	# 选择excel表格所提供的选项进行勾选
	def check(self, by, locator, options):
		y = [x for x in options if x != '']
		if len(y) > 0:
			be_options = options.split(',')
			for option in be_options:
				element = self.find_element(by, locator.format(option.strip()))
				element.click()
		else:
			pass

	# def input(self, left_title, excel_title, by, locator, values):
	# 	y = [x for x in values if x != '']
	# 	if len(y) > 0:
	# 		if left_title == excel_title:
	# 			self.type(by, locator, values)
	# 	else:
	# 		pass

    # 根据excel表格提供标题所包含的关键字来决定进行哪种数据操作
	def update(self, title, by, values):
		y = [x for x in values if x != '']
		if len(y) > 0:
			if '_Text' in title:  # 文本框
				field = title.strip().split('_')
				locator = field[0]
				self.type(by, locator, values)
			elif '_Select' in title:  # 下拉列表
				field = title.strip().split('_')
				locator = field[0]
				self.select(by, locator, values)
			elif '_Option' in title:  # 复选按钮
				field = title.strip().split('_')
				locator = field[0]
				self.uncheck('xpath', '//input[@checked="" and contains(@id, "{}__")]'.format(locator), values)
				self.check('id', '%s__{}'%locator, values)
			else:
				print('Please indicate the data type for the title "{}" in Excel!!!'.format(title))

		else:
			pass

	# def set(self, left_title, excel_title, by, locator, text):
	# 	y = [x for x in text if x != '']
	# 	if len(y) > 0:
	# 		if left_title == excel_title:
	# 			self.select(by, locator, text)
	# 	else:
	# 		pass

	# 登录系统进行封装方便以后重用
	def login_orms(self, url, username, password):
		# driver = webdriver.Firefox(executable_path='D:\\Selenium 3.14\\geckodriver.exe')
		self.driver.delete_all_cookies()
		self.driver.get(url)
		self.driver.maximize_window()
		time.sleep(2)

		self.type('id', 'userName', username)
		self.type('id', 'password', password)
		self.click('id', 'okBtnAnchor')
		time.sleep(2)

	# 登录系统后选择Contract
	def goto_manager_page(self, url, username, password, contract, page):
		self.login_orms(url, username, password)
		time.sleep(2)
		self.click('xpath', "//option[text()='" + contract + " Contract']")  # 通过click也可以对下拉列表进行选择
		time.sleep(2)
		self.click('link', page)
		time.sleep(2)
posted @ 2021-01-19 15:36  心如&  阅读(163)  评论(0)    收藏  举报