Selenium使用——动作链及等待(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wzyaiwl/article/details/89002958

一般来说我们与页面的交互可以使用Webelement的方法来进行点击等操作。但是,有时候我们需要一些更复杂的动作,类似于拖动,双击,长按等等。这个时候我们就需要将动作连贯在一起,即用到我们的Action Chains(动作链)。

下面是一个小例子:

from selenium.webdriver import ActionChains

element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")

actions = ActionChains(driver)
actions.drag_and_drop(element, target)
actions.perform()

在导入动作链模块以后,需要声明一个动作链对象,在声明时将webdriver当作参数传入,并将对象赋值给一个actions变量。然后我们通过这个actions变量,调用其内部附带的各种动作方法进行操作。在调用各种动作方法后,这些方法并不会马上执行,而是会按你代码的顺序存储在ActionChains对象的队列中。当你调用perform()时,这些动作才会依次开始执行。

常用动作方法

  • click(on_element=None)

左键单击传入的元素,如果不传入的话,点击鼠标当前位置。

  • context_click(on_element=None)

右键单击。

  • double_click(on_element=None)

双击。

  • click_and_hold(on_element=None)

点击并抓起

  • drag_and_drop(sourcetarget)

在source元素上点击抓起,移动到target元素上松开放下。

  • drag_and_drop_by_offset(sourcexoffsetyoffset)

在source元素上点击抓起,移动到相对于source元素偏移xoffset和yoffset的坐标位置放下。

  • send_keys(*keys_to_send)

将键发送到当前聚焦的元素。

  • send_keys_to_element(element, *keys_to_send)

将键发送到指定的元素。

  • move_by_offset(x,y)

将鼠标所点元素移动位置,指定x,y移动距离

  • release()

将点击状态的鼠标释放掉

  • reset_actions()

清除已经存储的动作。

例子

下面例子是进入bilili登陆界面,自动向右移动滑块200px。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import ActionChains
import time


# 打开一个Chrome浏览器
options = Options()
options.add_argument('--window-size=1000,700')
options.add_argument('--disable-infobars')
options.add_argument('--incognito')
driver = webdriver.Chrome(chrome_options = options)
# bilili登陆界面
driver.get('https://passport.bilibili.com/login')
time.sleep(1)
block = driver.find_element_by_xpath('//*[@id="gc-box"]/div/div[3]/div[2]')
action = ActionChains(driver)
action.click_and_hold(block)
action.move_by_offset(200,0)
action.perform()
time.sleep(1)
action = ActionChains(driver)
action.release()

time.sleep(5)
driver.quit()

等待

在selenium操作浏览器的过程中,每一次请求url,selenium都会等待页面加载完毕以后,才会将操作权限再次交给我们的程序。但是,由于ajax和各种JS代码的异步加载问题,所以我们在使用selenium的时候常常会遇到操作的元素还没有加载出来,就会引发报错。为了解决这个问题,Selenium提供了几种等待的方法,让我们可以等待元素加载完毕后,再进行操作。

显式等待

是在给定的最大时间内,一直等待,知道满足指定的条件。若超出最大时间,则会报错。如下所示:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("http://somedomain/url_that_delays_loading")
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
finally:
    driver.quit()

在这个例子中,我们在查找一个元素的时候,不再使用find_element_by_*这样的方式来查找元素,而是使用了WebDriverWait

try代码块中的代码的意思是:在抛出元素不存在异常之前,最多等待10秒。在这10秒中,WebDriverWait会默认每500ms运行一次until之中的内容,而until中的EC.presence_of_element_located则是检查元素是否已经被加载,检查的元素则通过By.ID这样的方式来进行查找。

就是说,在10秒内,默认每0.5秒检查一次元素是否存在,存在则将元素赋值给element这个变量。如果超过10秒这个元素仍不存在,则抛出超时异常。

Expected Conditions

  • title_is:判断当前页面的title是否精确等于预期;
  • title_contains:判断当前页面的title是否包含预期字符串;
  • presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见;
  • visibility_of_element_located:该方法是判断定位的元素是否存在;
  • visibility_of:判断某个元素是否可见(代表元素非隐藏,元素的宽和高都不等于0);
  • presence_of_all_elements_located:判断所有元素是否被加到了dom树里,并不代表该元素一定可见;
  • text_to_be_present_in_element:判断某个元素中的text是否包含了预期的字符串;
  • text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串;
  • frame_to_be_available_and_switch_to_it:判断该 frame 是否可以 switch进去,如果可以的话,返回 True 并且 switch 进去,否则返回 False
  • invisibility_of_element_located
  • element_to_be_clickable:判断某个元素中是否可见并且是可被点击的;
  • staleness_of
  • element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表;
  • element_located_to_be_selected
  • element_selection_state_to_be
  • element_located_selection_state_to_be
  • alert_is_present:判断页面上是否存在alert,即弹框;

 隐式等待

隐式等待指的是,在webdriver中进行find_element这一类查找操作时,如果找不到元素,则会默认的轮询等待一段时间。这种方式并不常用,因为不是所有的元素查找都需要等待。

如下所示:

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10) # 单位是秒
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

猜你喜欢

转载自blog.csdn.net/wzyaiwl/article/details/89002958