selenium之python源碼解讀-webdriver繼承關係

1、webdriver繼承關係

在selenium中,不管是經常使用的Firefox Driver 仍是Chrome Driver和Ie Drive,他們都繼承至selenium\webdriver\remote下webdriver.py中的WebDriver 類,以下css

chrome WebDriverhtml

selenium\webdriver\chrome下webdriver.py中WebDriver定義以下html5

from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

class WebDriver(RemoteWebDriver):
"""
Controls the ChromeDriver and allows you to drive the browser.
"""

firefox WebDriverandroid

selenium\webdriver\firefox 下webdriver.py中WebDriver定義以下web

from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

class WebDriver(RemoteWebDriver):
    pass

ie WebDriverchrome

selenium\webdriver\ie  下webdriver.py中WebDriver定義以下json

from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

class WebDriver(RemoteWebDriver):

    def __init__(self, executable_path='IEDriverServer.exe', capabilities=None,
                 port=DEFAULT_PORT, timeout=DEFAULT_TIMEOUT, host=DEFAULT_HOST,
                 log_level=DEFAULT_LOG_LEVEL, log_file=DEFAULT_LOG_FILE):
    ......

如上源碼:from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver 都是繼承至RemoteWebDriver ,並主要重寫__init__方法session

其餘方法主要繼承至父類RemoteWebDriver ,所以着重看下RemoteWebDriver 類中的方法app

一、find類ui

編寫腳本經常使用的查找頁面元素方法

def find_element_by_id(self, id_):
    #Finds an element by id.'''
    pass
def find_elements_by_id(self, id_):
    #Finds multiple elements by id.
    pass
def find_element_by_xpath(self, xpath):
    #Finds an element by xpath.
    pass
def find_elements_by_xpath(self, xpath):
    #Finds multiple elements by xpath.
    pass
def find_element_by_link_text(self, link_text):
    #Finds an element by link text
    pass
def find_elements_by_link_text(self, text):
    #Finds elements by link text.
    pass
def find_element_by_partial_link_text(self, link_text):
    #Finds elements by a partial match of their link text.
    pass
def find_elements_by_partial_link_text(self, link_text):
    #Finds an element by a partial match of its link text.
    pass
def find_element_by_name(self, name):
    #Finds an element by name.
    pass
def find_elements_by_name(self, name):
    #Finds elements by name.
    pass
def find_element_by_tag_name(self, name):
    #Finds an element by tag name.
    pass
def find_elements_by_tag_name(self, name):
    #Finds elements by tag name.
    pass
def find_element_by_class_name(self, name):
    Finds an element by class name.
    pass
def find_elements_by_class_name(self, name):
    #Finds elements by class name.
    pass
def find_element_by_css_selector(self, css_selector):
    #Finds an element by css selector.
    pass
def find_elements_by_css_selector(self, css_selector):
    #Finds elements by css selector.
    pass
def find_element(self, by=By.ID, value=None):
    #'Private' method used by the find_element_by_* methods.
    pass
def find_elements(self, by=By.ID, value=None):
    #'Private' method used by the find_elements_by_* methods.
    pass

經過查看源碼,其實以上方法都是經過調用

self.find_element(by=By.XXX, value=name)或者self.find_elements(by=By.XXX, value=name)方法來從新定義的

    def find_element(self, by=By.ID, value=None):
        """
        'Private' method used by the find_element_by_* methods.

        :Usage:
            Use the corresponding find_element_by_* instead of this.

        :rtype: WebElement
        """
        if self.w3c:
            if by == By.ID:
                by = By.CSS_SELECTOR
                value = '[id="%s"]' % value
            elif by == By.TAG_NAME:
                by = By.CSS_SELECTOR
            elif by == By.CLASS_NAME:
                by = By.CSS_SELECTOR
                value = ".%s" % value
            elif by == By.NAME:
                by = By.CSS_SELECTOR
                value = '[name="%s"]' % value
        return self.execute(Command.FIND_ELEMENT, {
            'using': by,
            'value': value})['value']

其中by.XXX是selenium\webdriver\common下by.py文件中By類定義的靜態常量

class By(object):
    """
    Set of supported locator strategies.
    """

    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"

經過以上分析,不難發現,只要掌握了self.find_element(by=By.XXX, value=name)或者self.find_elements(by=By.XXX, value=name)方法,已就意味着掌握了所有的查找定位頁面元素的方法

二、除了經常使用的find類方法外,如下方法在編寫腳本是也是經常使用的

ef get(self, url):
    """
    Loads a web page in the current browser session.
    """    
    
@property
def title(self):
    """Returns the title of the current page."""

@property
def current_url(self):
    """Gets the URL of the current page."""
    
@property
def current_window_handle(self):
    """Returns the handle of the current window."""

def maximize_window(self):
    """Maximizes the current window that webdriver is using"""
    
@property
def switch_to(self):
    return self._switch_to

# Target Locators
def switch_to_active_element(self):
    """ Deprecated use driver.switch_to.active_element"""

def switch_to_window(self, window_name):
    """ Deprecated use driver.switch_to.window"""

def switch_to_frame(self, frame_reference):
    """ Deprecated use driver.switch_to.frame"""

def switch_to_default_content(self):
    """ Deprecated use driver.switch_to.default_content"""

def switch_to_alert(self):
    """ Deprecated use driver.switch_to.alert"""

其中使用@property修飾的,能夠看成爲屬性來使用,如driver.current_url

三、爲何在實際應用過程當中經過from selenium import webdriver引入webdriver,而後經過webdriver.Chrome()就能夠實例化Chrome的Driver對象呢?

從以上selenium目錄結構,理論上須要經過如下來導入

#導入chrome的WebDriver
from selenium.webdriver.chrome.webdriver import WebDriver
#導入firefox的WebDriver
from selenium.webdriver.firefox.webdriver import WebDriver
#導入ie的WebDriver
from selenium.webdriver.ie.webdriver import WebDriver

selenium項目目錄結構

selenium
│ __init__.py

├─common
│ │ exceptions.py
│ │ __init__.py

├─webdriver
│ │ __init__.py
│ │
│ ├─android
│ │ │ webdriver.py
│ │ │ __init__.py
│ │
│ ├─blackberry
│ │ │ webdriver.py
│ │ │ __init__.py
│ │
│ ├─chrome
│ │ │ options.py
│ │ │ remote_connection.py
│ │ │ service.py
│ │ │ webdriver.py
│ │ │ __init__.py
│ │
│ ├─common
│ │ │ action_chains.py
│ │ │ alert.py
│ │ │ by.py
│ │ │ desired_capabilities.py
│ │ │ keys.py
│ │ │ proxy.py
│ │ │ service.py
│ │ │ touch_actions.py
│ │ │ utils.py
│ │ │ __init__.py
│ │ │
│ │ ├─actions
│ │ │ │ action_builder.py
│ │ │ │ input_device.py
│ │ │ │ interaction.py
│ │ │ │ key_actions.py
│ │ │ │ key_input.py
│ │ │ │ mouse_button.py
│ │ │ │ pointer_actions.py
│ │ │ │ pointer_input.py
│ │ │ │ __init__.py
│ │ │
│ │ │
│ │ ├─html5
│ │ │ │ application_cache.py
│ │ │ │ __init__.py
│ │
│ ├─edge
│ │ │ options.py
│ │ │ service.py
│ │ │ webdriver.py
│ │ │ __init__.py
│ ├─firefox
│ │ │ extension_connection.py
│ │ │ firefox_binary.py
│ │ │ firefox_profile.py
│ │ │ options.py
│ │ │ remote_connection.py
│ │ │ service.py
│ │ │ webdriver.py
│ │ │ webdriver.xpi
│ │ │ webdriver_prefs.json
│ │ │ webelement.py
│ │ │ __init__.py
│ │
│ ├─ie
│ │ │ service.py
│ │ │ webdriver.py
│ │ │ __init__.py
│ ├─opera
│ │ │ options.py
│ │ │ webdriver.py
│ │ │ __init__.py
│ ├─phantomjs
│ │ │ service.py
│ │ │ webdriver.py
│ │ │ __init__.py
│ ├─remote
│ │ │ command.py
│ │ │ errorhandler.py
│ │ │ file_detector.py
│ │ │ getAttribute.js
│ │ │ isDisplayed.js
│ │ │ mobile.py
│ │ │ remote_connection.py
│ │ │ switch_to.py
│ │ │ utils.py
│ │ │ webdriver.py
│ │ │ webelement.py
│ │ │ __init__.py
│ ├─safari
│ │ │ service.py
│ │ │ webdriver.py
│ │ │ __init__.py
│ ├─support
│ │ │ abstract_event_listener.py
│ │ │ color.py
│ │ │ events.py
│ │ │ event_firing_webdriver.py
│ │ │ expected_conditions.py
│ │ │ select.py
│ │ │ ui.py
│ │ │ wait.py
│ │ │ __init__.py

經過查看selenium\webdriver下__init__.py文件發現

from .firefox.webdriver import WebDriver as Firefox  # noqa
from .firefox.firefox_profile import FirefoxProfile  # noqa
from .chrome.webdriver import WebDriver as Chrome  # noqa
from .chrome.options import Options as ChromeOptions  # noqa
from .ie.webdriver import WebDriver as Ie  # noqa

實際上是由於該出已經導入了,因此才能夠直接使用Firefox、Chrome

相關文章
相關標籤/搜索