python selenium使用方法笔记(下) - ZhouXuyan/notes GitHub Wiki

四 定位

概述:

selenium提供如下方法定位一个页面中的元素:

  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

寻找多个元素的方法(返回一个列表):

  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

除了以上方法,还有两种方法备用:

  find_element
  find_elements

  #参数为:
  ID = "id"
  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"

使用方法:

  from selenium.webdriver.common.by import By
  driver.find_element(By.XPATH, '//button[text()="Some text"]')
  driver.find_elements(By.XPATH, '//button')

使用方法:

一、通过Id定位

会返回第一个id匹配的元素。如果没有,就报错NoSuchElementException

  login_form = driver.find_element_by_id('loginForm')

二、通过xpath定位

  login_form = driver.find_element_by_xpath("/html/body/form[1]")
  login_form = driver.find_element_by_xpath("//form[1]")
  login_form = driver.find_element_by_xpath("//form[@id='loginForm']")

三、通过文本定位超链接

  <body>
    <p>Are you sure you want to do this?</p>
    <a href="continue.html">Continue</a>
    <a href="cancel.html">Cancel</a>
  </body>

  有如下两种方法:

  continue_link = driver.find_element_by_link_text('Continue')
  continue_link = driver.find_element_by_partial_link_text('Conti')

四、通过TagName定位元素

  <html>
   <body>
    <h1>Welcome</h1>
    <p>Site content goes here.</p>
  </body>
  <html>

  方法:

  heading1 = driver.find_element_by_tag_name('h1')

五、通过类名定位

  <html>
   <body>
    <p class="content">Site content goes here.</p>
  </body>
  <html>

  方法:

  content = driver.find_element_by_class_name('content')

六、通过CSS定位

  <html>
   <body>
    <p class="content">Site content goes here.</p>
  </body>
  <html>

  方法:

  content = driver.find_element_by_css_selector('p.content')

七、通过补充方法定位

  from selenium.webdriver.common.by import By
  driver.find_element(By.XPATH, '//button[text()="Some text"]')
  driver.find_elements(By.XPATH, '//button')

五 等待

现在很多web app使用了AJAX技术,导致浏览器在加载某个指定页面时,元素加载是有时间间隔的,这就导致如果调用这个方法时这一个元素还没加载出来,就会报错ElementNotVisibleException 。这时候就可以使用等待了。

一般来讲,selenium中可以用到三种等待方法:

一、强制等待(sleep)

最简单的方法就,其实就是time.sleep()方法,略去不表。

二、隐式等待(implicitly_wait())

跟强制等待很像,不智能。

  from selenium import webdriver
  driver.implicitly_wait(10)
  #等待10秒,最长30秒

三、显式等待(WebDriverWait)

selenium.webdriver.support.ui 中的wait模块的 WebDriverWait()方法,配合until或者until_not方法,再辅助以selenium.webdriver.support中的expected_conditions,就可以构成一条等待命令。 以下代码,在抛出TimeoutException 错误之前会等待十秒。WebDriverWait默认每秒调用ExpectedCondition 50000次直到成功返回。

  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.Firefox()
  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()

ExpectedCondition包含如下预期情况:

  title_is
  title_contains
  presence_of_element_located
  visibility_of_element_located
  visibility_of
  presence_of_all_elements_located
  text_to_be_present_in_element
  text_to_be_present_in_element_value
  frame_to_be_available_and_switch_to_it
  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

注:如果以上所有情况都不满足,就自己diy一个情况:

新建类,然后写一个__call__方法。 情况不满足时返回False。 例:

  class element_has_css_class(object):
    """An expectation for checking that an element has a particular css class.

    locator - used to find the element
    returns the WebElement once it has the particular css class
    """
    def __init__(self, locator, css_class):
      self.locator = locator
      self.css_class = css_class
  
    def __call__(self, driver):
      element = driver.find_element(*self.locator)   # Finding the referenced element
      if self.css_class in element.get_attribute("class"):
          return element
      else:
          return False

  # Wait until an element with id='myNewInput' has class 'myCSSClass'
  wait = WebDriverWait(driver, 10)
  element = wait.until(element_has_css_class((By.ID, 'myNewInput'), "myCSSClass"))

六 page模式

  1. 抽象出来一个BasePage基类,它包含一个指向Selenium.webdriver的属性

  2. 每一个webpage都继承自BasePage基类,通过driver来获取本页面的元素,每个页面的操作都抽象为一个个方法

  3. TestCase继承自unittest.Testcase类,并依赖相应的Page类来实现相应的test case步骤

使用页面对象的优势:

  1. 创造可复用的代码,可以在多个测试用例上运行

  2. 减少重复代码

  3. 如果ui改变,只需要更改一处代码即可

七 selenium API

https://seleniumhq.github.io/selenium/docs/api/py/api.html

或:

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

⚠️ **GitHub.com Fallback** ⚠️