Selenium with Python 009 - WebDriver API
官方API文档:https://seleniumhq.github.io/selenium/docs/api/py/api.html
更多详情,最好的学习方式可以查阅官方API文档或直接阅读源码,本文只列出常用的WebDriver类与WebElement类供参考
selenium.webdriver.remote.webdriver
https://seleniumhq.github.io/selenium/docs/api/py/_modules/selenium/webdriver/remote/webdriver.html#WebDriver
class WebDriver(object):
"""
Controls a browser by sending commands to a remote server.
This server is expected to be running the WebDriver wire protocol
as defined at
https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol :Attributes:
- session_id - String ID of the browser session started and controlled by this WebDriver.
- capabilities - Dictionaty of effective capabilities of this browser session as returned
by the remote server. See https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities
- command_executor - remote_connection.RemoteConnection object used to execute commands.
- error_handler - errorhandler.ErrorHandler object used to handle errors.
""" _web_element_cls = WebElement def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=None, browser_profile=None, proxy=None,
keep_alive=False, file_detector=None):
"""
Create a new driver that will issue commands using the wire protocol. :Args:
- command_executor - Either a string representing URL of the remote server or a custom
remote_connection.RemoteConnection object. Defaults to 'http://127.0.0.1:4444/wd/hub'.
- desired_capabilities - A dictionary of capabilities to request when
starting the browser session. Required parameter.
- browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object.
Only used if Firefox is requested. Optional.
- proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will
be started with given proxy settings, if possible. Optional.
- keep_alive - Whether to configure remote_connection.RemoteConnection to use
HTTP keep-alive. Defaults to False.
- file_detector - Pass custom file detector object during instantiation. If None,
then default LocalFileDetector() will be used.
"""
if desired_capabilities is None:
raise WebDriverException("Desired Capabilities can't be None")
if not isinstance(desired_capabilities, dict):
raise WebDriverException("Desired Capabilities must be a dictionary")
if proxy is not None:
warnings.warn("Please use FirefoxOptions to set proxy",
DeprecationWarning)
proxy.add_to_capabilities(desired_capabilities)
self.command_executor = command_executor
if type(self.command_executor) is bytes or isinstance(self.command_executor, str):
self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive)
self._is_remote = True
self.session_id = None
self.capabilities = {}
self.error_handler = ErrorHandler()
self.start_client()
if browser_profile is not None:
warnings.warn("Please use FirefoxOptions to set browser profile",
DeprecationWarning)
self.start_session(desired_capabilities, browser_profile)
self._switch_to = SwitchTo(self)
self._mobile = Mobile(self)
self.file_detector = file_detector or LocalFileDetector() def __repr__(self):
return '<{0.__module__}.{0.__name__} (session="{1}")>'.format(
type(self), self.session_id) @contextmanager
def file_detector_context(self, file_detector_class, *args, **kwargs):
"""
Overrides the current file detector (if necessary) in limited context.
Ensures the original file detector is set afterwards. Example: with webdriver.file_detector_context(UselessFileDetector):
someinput.send_keys('/etc/hosts') :Args:
- file_detector_class - Class of the desired file detector. If the class is different
from the current file_detector, then the class is instantiated with args and kwargs
and used as a file detector during the duration of the context manager.
- args - Optional arguments that get passed to the file detector class during
instantiation.
- kwargs - Keyword arguments, passed the same way as args.
"""
last_detector = None
if not isinstance(self.file_detector, file_detector_class):
last_detector = self.file_detector
self.file_detector = file_detector_class(*args, **kwargs)
try:
yield
finally:
if last_detector is not None:
self.file_detector = last_detector @property
def mobile(self):
return self._mobile @property
def name(self):
"""Returns the name of the underlying browser for this instance. :Usage:
- driver.name
"""
if 'browserName' in self.capabilities:
return self.capabilities['browserName']
else:
raise KeyError('browserName not specified in session capabilities') def start_client(self):
"""
Called before starting a new session. This method may be overridden
to define custom startup behavior.
"""
pass def stop_client(self):
"""
Called after executing a quit command. This method may be overridden
to define custom shutdown behavior.
"""
pass def start_session(self, capabilities, browser_profile=None):
"""
Creates a new session with the desired capabilities. :Args:
- browser_name - The name of the browser to request.
- version - Which browser version to request.
- platform - Which platform to request the browser on.
- javascript_enabled - Whether the new session should support JavaScript.
- browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested.
"""
if not isinstance(capabilities, dict):
raise InvalidArgumentException("Capabilities must be a dictionary")
if browser_profile:
if "moz:firefoxOptions" in capabilities:
capabilities["moz:firefoxOptions"]["profile"] = browser_profile.encoded
else:
capabilities.update({'firefox_profile': browser_profile.encoded})
w3c_caps = _make_w3c_caps(capabilities)
parameters = {"capabilities": w3c_caps,
"desiredCapabilities": capabilities}
response = self.execute(Command.NEW_SESSION, parameters)
if 'sessionId' not in response:
response = response['value']
self.session_id = response['sessionId']
self.capabilities = response.get('value') # if capabilities is none we are probably speaking to
# a W3C endpoint
if self.capabilities is None:
self.capabilities = response.get('capabilities') # Double check to see if we have a W3C Compliant browser
self.w3c = response.get('status') is None def _wrap_value(self, value):
if isinstance(value, dict):
converted = {}
for key, val in value.items():
converted[key] = self._wrap_value(val)
return converted
elif isinstance(value, self._web_element_cls):
return {'ELEMENT': value.id, 'element-6066-11e4-a52e-4f735466cecf': value.id}
elif isinstance(value, list):
return list(self._wrap_value(item) for item in value)
else:
return value def create_web_element(self, element_id):
"""Creates a web element with the specified `element_id`."""
return self._web_element_cls(self, element_id, w3c=self.w3c) def _unwrap_value(self, value):
if isinstance(value, dict):
if 'ELEMENT' in value or 'element-6066-11e4-a52e-4f735466cecf' in value:
wrapped_id = value.get('ELEMENT', None)
if wrapped_id:
return self.create_web_element(value['ELEMENT'])
else:
return self.create_web_element(value['element-6066-11e4-a52e-4f735466cecf'])
else:
for key, val in value.items():
value[key] = self._unwrap_value(val)
return value
elif isinstance(value, list):
return list(self._unwrap_value(item) for item in value)
else:
return value def execute(self, driver_command, params=None):
"""
Sends a command to be executed by a command.CommandExecutor. :Args:
- driver_command: The name of the command to execute as a string.
- params: A dictionary of named parameters to send with the command. :Returns:
The command's JSON response loaded into a dictionary object.
"""
if self.session_id is not None:
if not params:
params = {'sessionId': self.session_id}
elif 'sessionId' not in params:
params['sessionId'] = self.session_id params = self._wrap_value(params)
response = self.command_executor.execute(driver_command, params)
if response:
self.error_handler.check_response(response)
response['value'] = self._unwrap_value(
response.get('value', None))
return response
# If the server doesn't send a response, assume the command was
# a success
return {'success': 0, 'value': None, 'sessionId': self.session_id} def get(self, url):
"""
Loads a web page in the current browser session.
"""
self.execute(Command.GET, {'url': url}) @property
def title(self):
"""Returns the title of the current page. :Usage:
driver.title
"""
resp = self.execute(Command.GET_TITLE)
return resp['value'] if resp['value'] is not None else "" def find_element_by_id(self, id_):
"""Finds an element by id. :Args:
- id\_ - The id of the element to be found. :Usage:
driver.find_element_by_id('foo')
"""
return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_):
"""
Finds multiple elements by id. :Args:
- id\_ - The id of the elements to be found. :Usage:
driver.find_elements_by_id('foo')
"""
return self.find_elements(by=By.ID, value=id_) def find_element_by_xpath(self, xpath):
"""
Finds an element by xpath. :Args:
- xpath - The xpath locator of the element to find. :Usage:
driver.find_element_by_xpath('//div/td[1]')
"""
return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath):
"""
Finds multiple elements by xpath. :Args:
- xpath - The xpath locator of the elements to be found. :Usage:
driver.find_elements_by_xpath("//div[contains(@class, 'foo')]")
"""
return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text):
"""
Finds an element by link text. :Args:
- link_text: The text of the element to be found. :Usage:
driver.find_element_by_link_text('Sign In')
"""
return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, text):
"""
Finds elements by link text. :Args:
- link_text: The text of the elements to be found. :Usage:
driver.find_elements_by_link_text('Sign In')
"""
return self.find_elements(by=By.LINK_TEXT, value=text) def find_element_by_partial_link_text(self, link_text):
"""
Finds an element by a partial match of its link text. :Args:
- link_text: The text of the element to partially match on. :Usage:
driver.find_element_by_partial_link_text('Sign')
"""
return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text):
"""
Finds elements by a partial match of their link text. :Args:
- link_text: The text of the element to partial match on. :Usage:
driver.find_element_by_partial_link_text('Sign')
"""
return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name):
"""
Finds an element by name. :Args:
- name: The name of the element to find. :Usage:
driver.find_element_by_name('foo')
"""
return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name):
"""
Finds elements by name. :Args:
- name: The name of the elements to find. :Usage:
driver.find_elements_by_name('foo')
"""
return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name):
"""
Finds an element by tag name. :Args:
- name: The tag name of the element to find. :Usage:
driver.find_element_by_tag_name('foo')
"""
return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name):
"""
Finds elements by tag name. :Args:
- name: The tag name the use when finding elements. :Usage:
driver.find_elements_by_tag_name('foo')
"""
return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name):
"""
Finds an element by class name. :Args:
- name: The class name of the element to find. :Usage:
driver.find_element_by_class_name('foo')
"""
return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name):
"""
Finds elements by class name. :Args:
- name: The class name of the elements to find. :Usage:
driver.find_elements_by_class_name('foo')
"""
return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector):
"""
Finds an element by css selector. :Args:
- css_selector: The css selector to use when finding elements. :Usage:
driver.find_element_by_css_selector('#foo')
"""
return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector):
"""
Finds elements by css selector. :Args:
- css_selector: The css selector to use when finding elements. :Usage:
driver.find_elements_by_css_selector('.foo')
"""
return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args):
"""
Synchronously Executes JavaScript in the current window/frame. :Args:
- script: The JavaScript to execute.
- \*args: Any applicable arguments for your JavaScript. :Usage:
driver.execute_script('document.title')
"""
converted_args = list(args)
command = None
if self.w3c:
command = Command.W3C_EXECUTE_SCRIPT
else:
command = Command.EXECUTE_SCRIPT return self.execute(command, {
'script': script,
'args': converted_args})['value'] def execute_async_script(self, script, *args):
"""
Asynchronously Executes JavaScript in the current window/frame. :Args:
- script: The JavaScript to execute.
- \*args: Any applicable arguments for your JavaScript. :Usage:
driver.execute_async_script('document.title')
"""
converted_args = list(args)
if self.w3c:
command = Command.W3C_EXECUTE_SCRIPT_ASYNC
else:
command = Command.EXECUTE_ASYNC_SCRIPT return self.execute(command, {
'script': script,
'args': converted_args})['value'] @property
def current_url(self):
"""
Gets the URL of the current page. :Usage:
driver.current_url
"""
return self.execute(Command.GET_CURRENT_URL)['value'] @property
def page_source(self):
"""
Gets the source of the current page. :Usage:
driver.page_source
"""
return self.execute(Command.GET_PAGE_SOURCE)['value'] def close(self):
"""
Closes the current window. :Usage:
driver.close()
"""
self.execute(Command.CLOSE) def quit(self):
"""
Quits the driver and closes every associated window. :Usage:
driver.quit()
"""
try:
self.execute(Command.QUIT)
finally:
self.stop_client() @property
def current_window_handle(self):
"""
Returns the handle of the current window. :Usage:
driver.current_window_handle
"""
if self.w3c:
return self.execute(Command.W3C_GET_CURRENT_WINDOW_HANDLE)['value']
else:
return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] @property
def window_handles(self):
"""
Returns the handles of all windows within the current session. :Usage:
driver.window_handles
"""
if self.w3c:
return self.execute(Command.W3C_GET_WINDOW_HANDLES)['value']
else:
return self.execute(Command.GET_WINDOW_HANDLES)['value'] def maximize_window(self):
"""
Maximizes the current window that webdriver is using
"""
command = Command.MAXIMIZE_WINDOW
if self.w3c:
command = Command.W3C_MAXIMIZE_WINDOW
self.execute(command, {"windowHandle": "current"}) @property
def switch_to(self):
return self._switch_to # Target Locators
def switch_to_active_element(self):
""" Deprecated use driver.switch_to.active_element
"""
warnings.warn("use driver.switch_to.active_element instead", DeprecationWarning)
return self._switch_to.active_element def switch_to_window(self, window_name):
""" Deprecated use driver.switch_to.window
"""
warnings.warn("use driver.switch_to.window instead", DeprecationWarning)
self._switch_to.window(window_name) def switch_to_frame(self, frame_reference):
""" Deprecated use driver.switch_to.frame
"""
warnings.warn("use driver.switch_to.frame instead", DeprecationWarning)
self._switch_to.frame(frame_reference) def switch_to_default_content(self):
""" Deprecated use driver.switch_to.default_content
"""
warnings.warn("use driver.switch_to.default_content instead", DeprecationWarning)
self._switch_to.default_content() def switch_to_alert(self):
""" Deprecated use driver.switch_to.alert
"""
warnings.warn("use driver.switch_to.alert instead", DeprecationWarning)
return self._switch_to.alert # Navigation
def back(self):
"""
Goes one step backward in the browser history. :Usage:
driver.back()
"""
self.execute(Command.GO_BACK) def forward(self):
"""
Goes one step forward in the browser history. :Usage:
driver.forward()
"""
self.execute(Command.GO_FORWARD) def refresh(self):
"""
Refreshes the current page. :Usage:
driver.refresh()
"""
self.execute(Command.REFRESH) # Options
def get_cookies(self):
"""
Returns a set of dictionaries, corresponding to cookies visible in the current session. :Usage:
driver.get_cookies()
"""
return self.execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name):
"""
Get a single cookie by name. Returns the cookie if found, None if not. :Usage:
driver.get_cookie('my_cookie')
"""
cookies = self.get_cookies()
for cookie in cookies:
if cookie['name'] == name:
return cookie
return None def delete_cookie(self, name):
"""
Deletes a single cookie with the given name. :Usage:
driver.delete_cookie('my_cookie')
"""
self.execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self):
"""
Delete all cookies in the scope of the session. :Usage:
driver.delete_all_cookies()
"""
self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict):
"""
Adds a cookie to your current session. :Args:
- cookie_dict: A dictionary object, with required keys - "name" and "value";
optional keys - "path", "domain", "secure", "expiry" Usage:
driver.add_cookie({'name' : 'foo', 'value' : 'bar'})
driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'})
driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True}) """
self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) # Timeouts
def implicitly_wait(self, time_to_wait):
"""
Sets a sticky timeout to implicitly wait for an element to be found,
or a command to complete. This method only needs to be called one
time per session. To set the timeout for calls to
execute_async_script, see set_script_timeout. :Args:
- time_to_wait: Amount of time to wait (in seconds) :Usage:
driver.implicitly_wait(30)
"""
if self.w3c:
self.execute(Command.SET_TIMEOUTS, {
'implicit': int(float(time_to_wait) * 1000)})
else:
self.execute(Command.IMPLICIT_WAIT, {
'ms': float(time_to_wait) * 1000}) def set_script_timeout(self, time_to_wait):
"""
Set the amount of time that the script should wait during an
execute_async_script call before throwing an error. :Args:
- time_to_wait: The amount of time to wait (in seconds) :Usage:
driver.set_script_timeout(30)
"""
if self.w3c:
self.execute(Command.SET_TIMEOUTS, {
'script': int(float(time_to_wait) * 1000)})
else:
self.execute(Command.SET_SCRIPT_TIMEOUT, {
'ms': float(time_to_wait) * 1000}) def set_page_load_timeout(self, time_to_wait):
"""
Set the amount of time to wait for a page load to complete
before throwing an error. :Args:
- time_to_wait: The amount of time to wait :Usage:
driver.set_page_load_timeout(30)
"""
try:
self.execute(Command.SET_TIMEOUTS, {
'pageLoad': int(float(time_to_wait) * 1000)})
except WebDriverException:
self.execute(Command.SET_TIMEOUTS, {
'ms': float(time_to_wait) * 1000,
'type': 'page load'}) 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'] def find_elements(self, by=By.ID, value=None):
"""
'Private' method used by the find_elements_by_* methods. :Usage:
Use the corresponding find_elements_by_* instead of this. :rtype: list of 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_ELEMENTS, {
'using': by,
'value': value})['value'] @property
def desired_capabilities(self):
"""
returns the drivers current desired capabilities being used
"""
return self.capabilities def get_screenshot_as_file(self, filename):
"""
Saves a screenshot of the current window to a PNG image file. Returns
False if there is any IOError, else returns True. Use full paths in
your filename. :Args:
- filename: The full path you wish to save your screenshot to. This
should end with a `.png` extension. :Usage:
driver.get_screenshot_as_file('/Screenshots/foo.png')
"""
if not filename.lower().endswith('.png'):
warnings.warn("name used for saved screenshot does not match file "
"type. It should end with a `.png` extension", UserWarning)
png = self.get_screenshot_as_png()
try:
with open(filename, 'wb') as f:
f.write(png)
except IOError:
return False
finally:
del png
return True def save_screenshot(self, filename):
"""
Saves a screenshot of the current window to a PNG image file. Returns
False if there is any IOError, else returns True. Use full paths in
your filename. :Args:
- filename: The full path you wish to save your screenshot to. This
should end with a `.png` extension. :Usage:
driver.save_screenshot('/Screenshots/foo.png')
"""
return self.get_screenshot_as_file(filename) def get_screenshot_as_png(self):
"""
Gets the screenshot of the current window as a binary data. :Usage:
driver.get_screenshot_as_png()
"""
return base64.b64decode(self.get_screenshot_as_base64().encode('ascii')) def get_screenshot_as_base64(self):
"""
Gets the screenshot of the current window as a base64 encoded string
which is useful in embedded images in HTML. :Usage:
driver.get_screenshot_as_base64()
"""
return self.execute(Command.SCREENSHOT)['value'] def set_window_size(self, width, height, windowHandle='current'):
"""
Sets the width and height of the current window. (window.resizeTo) :Args:
- width: the width in pixels to set the window to
- height: the height in pixels to set the window to :Usage:
driver.set_window_size(800,600)
"""
command = Command.SET_WINDOW_SIZE
if self.w3c:
command = Command.W3C_SET_WINDOW_SIZE
self.execute(command, {
'width': int(width),
'height': int(height),
'windowHandle': windowHandle}) def get_window_size(self, windowHandle='current'):
"""
Gets the width and height of the current window. :Usage:
driver.get_window_size()
"""
command = Command.GET_WINDOW_SIZE
if self.w3c:
command = Command.W3C_GET_WINDOW_SIZE
size = self.execute(command, {'windowHandle': windowHandle}) if size.get('value', None) is not None:
return size['value']
else:
return size def set_window_position(self, x, y, windowHandle='current'):
"""
Sets the x,y position of the current window. (window.moveTo) :Args:
- x: the x-coordinate in pixels to set the window position
- y: the y-coordinate in pixels to set the window position :Usage:
driver.set_window_position(0,0)
"""
if self.w3c:
return self.execute(Command.W3C_SET_WINDOW_POSITION, {
'x': int(x),
'y': int(y)
})
else:
self.execute(Command.SET_WINDOW_POSITION,
{
'x': int(x),
'y': int(y),
'windowHandle': windowHandle
}) def get_window_position(self, windowHandle='current'):
"""
Gets the x,y position of the current window. :Usage:
driver.get_window_position()
"""
if self.w3c:
return self.execute(Command.W3C_GET_WINDOW_POSITION)['value']
else:
return self.execute(Command.GET_WINDOW_POSITION, {
'windowHandle': windowHandle})['value'] def get_window_rect(self):
"""
Gets the x, y coordinates of the window as well as height and width of
the current window. :Usage:
driver.get_window_rect()
"""
return self.execute(Command.GET_WINDOW_RECT)['value'] def set_window_rect(self, x=None, y=None, width=None, height=None):
"""
Sets the x, y coordinates of the window as well as height and width of
the current window. :Usage:
driver.set_window_rect(x=10, y=10)
driver.set_window_rect(width=100, height=200)
driver.set_window_rect(x=10, y=10, width=100, height=200)
"""
if (x is None and y is None) and (height is None and width is None):
raise InvalidArgumentException("x and y or height and width need values") return self.execute(Command.SET_WINDOW_RECT, {"x": x, "y": y,
"width": width,
"height": height})['value'] @property
def file_detector(self):
return self._file_detector @file_detector.setter
def file_detector(self, detector):
"""
Set the file detector to be used when sending keyboard input.
By default, this is set to a file detector that does nothing. see FileDetector
see LocalFileDetector
see UselessFileDetector :Args:
- detector: The detector to use. Must not be None.
"""
if detector is None:
raise WebDriverException("You may not set a file detector that is null")
if not isinstance(detector, FileDetector):
raise WebDriverException("Detector has to be instance of FileDetector")
self._file_detector = detector @property
def orientation(self):
"""
Gets the current orientation of the device :Usage:
orientation = driver.orientation
"""
return self.execute(Command.GET_SCREEN_ORIENTATION)['value'] @orientation.setter
def orientation(self, value):
"""
Sets the current orientation of the device :Args:
- value: orientation to set it to. :Usage:
driver.orientation = 'landscape'
"""
allowed_values = ['LANDSCAPE', 'PORTRAIT']
if value.upper() in allowed_values:
self.execute(Command.SET_SCREEN_ORIENTATION, {'orientation': value})
else:
raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'") @property
def application_cache(self):
""" Returns a ApplicationCache Object to interact with the browser app cache"""
return ApplicationCache(self) @property
def log_types(self):
"""
Gets a list of the available log types :Usage:
driver.log_types
"""
return self.execute(Command.GET_AVAILABLE_LOG_TYPES)['value'] def get_log(self, log_type):
"""
Gets the log for a given log type :Args:
- log_type: type of log that which will be returned :Usage:
driver.get_log('browser')
driver.get_log('driver')
driver.get_log('client')
driver.get_log('server')
"""
return self.execute(Command.GET_LOG, {'type': log_type})['value']
selenium.webdriver.remote.webelement
https://seleniumhq.github.io/selenium/docs/api/py/_modules/selenium/webdriver/remote/webelement.html#WebElement
class WebElement(object):
"""Represents a DOM element. Generally, all interesting operations that interact with a document will be
performed through this interface. All method calls will do a freshness check to ensure that the element
reference is still valid. This essentially determines whether or not the
element is still attached to the DOM. If this test fails, then an
``StaleElementReferenceException`` is thrown, and all future calls to this
instance will fail.""" def __init__(self, parent, id_, w3c=False):
self._parent = parent
self._id = id_
self._w3c = w3c def __repr__(self):
return '<{0.__module__}.{0.__name__} (session="{1}", element="{2}")>'.format(
type(self), self._parent.session_id, self._id) @property
def tag_name(self):
"""This element's ``tagName`` property."""
return self._execute(Command.GET_ELEMENT_TAG_NAME)['value'] @property
def text(self):
"""The text of the element."""
return self._execute(Command.GET_ELEMENT_TEXT)['value'] def click(self):
"""Clicks the element."""
self._execute(Command.CLICK_ELEMENT) def submit(self):
"""Submits a form."""
if self._w3c:
form = self.find_element(By.XPATH, "./ancestor-or-self::form")
self._parent.execute_script(
"var e = arguments[0].ownerDocument.createEvent('Event');"
"e.initEvent('submit', true, true);"
"if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }", form)
else:
self._execute(Command.SUBMIT_ELEMENT) def clear(self):
"""Clears the text if it's a text entry element."""
self._execute(Command.CLEAR_ELEMENT) def get_property(self, name):
"""
Gets the given property of the element. :Args:
- name - Name of the property to retrieve. Example:: # Check if the "active" CSS class is applied to an element.
text_length = target_element.get_property("text_length")
"""
try:
return self._execute(Command.GET_ELEMENT_PROPERTY, {"name": name})["value"]
except WebDriverException:
# if we hit an end point that doesnt understand getElementProperty lets fake it
return self.parent.execute_script('return arguments[0][arguments[1]]', self, name) def get_attribute(self, name):
"""Gets the given attribute or property of the element. This method will first try to return the value of a property with the
given name. If a property with that name doesn't exist, it returns the
value of the attribute with the same name. If there's no attribute with
that name, ``None`` is returned. Values which are considered truthy, that is equals "true" or "false",
are returned as booleans. All other non-``None`` values are returned
as strings. For attributes or properties which do not exist, ``None``
is returned. :Args:
- name - Name of the attribute/property to retrieve. Example:: # Check if the "active" CSS class is applied to an element.
is_active = "active" in target_element.get_attribute("class") """ attributeValue = ''
if self._w3c:
attributeValue = self.parent.execute_script(
"return (%s).apply(null, arguments);" % getAttribute_js,
self, name)
else:
resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})
attributeValue = resp.get('value')
if attributeValue is not None:
if name != 'value' and attributeValue.lower() in ('true', 'false'):
attributeValue = attributeValue.lower()
return attributeValue def is_selected(self):
"""Returns whether the element is selected. Can be used to check if a checkbox or radio button is selected.
"""
return self._execute(Command.IS_ELEMENT_SELECTED)['value'] def is_enabled(self):
"""Returns whether the element is enabled."""
return self._execute(Command.IS_ELEMENT_ENABLED)['value'] def find_element_by_id(self, id_):
"""Finds element within this element's children by ID. :Args:
- id\_ - ID of child element to locate.
"""
return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_):
"""Finds a list of elements within this element's children by ID. :Args:
- id\_ - Id of child element to find.
"""
return self.find_elements(by=By.ID, value=id_) def find_element_by_name(self, name):
"""Finds element within this element's children by name. :Args:
- name - name property of the element to find.
"""
return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name):
"""Finds a list of elements within this element's children by name. :Args:
- name - name property to search for.
"""
return self.find_elements(by=By.NAME, value=name) def find_element_by_link_text(self, link_text):
"""Finds element within this element's children by visible link text. :Args:
- link_text - Link text string to search for.
"""
return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, link_text):
"""Finds a list of elements within this element's children by visible link text. :Args:
- link_text - Link text string to search for.
"""
return self.find_elements(by=By.LINK_TEXT, value=link_text) def find_element_by_partial_link_text(self, link_text):
"""Finds element within this element's children by partially visible link text. :Args:
- link_text - Link text string to search for.
"""
return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text):
"""Finds a list of elements within this element's children by link text. :Args:
- link_text - Link text string to search for.
"""
return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_tag_name(self, name):
"""Finds element within this element's children by tag name. :Args:
- name - name of html tag (eg: h1, a, span)
"""
return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name):
"""Finds a list of elements within this element's children by tag name. :Args:
- name - name of html tag (eg: h1, a, span)
"""
return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_xpath(self, xpath):
"""Finds element by xpath. :Args:
xpath - xpath of element to locate. "//input[@class='myelement']" Note: The base path will be relative to this element's location. This will select the first link under this element. :: myelement.find_elements_by_xpath(".//a") However, this will select the first link on the page. :: myelement.find_elements_by_xpath("//a") """
return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath):
"""Finds elements within the element by xpath. :Args:
- xpath - xpath locator string. Note: The base path will be relative to this element's location. This will select all links under this element. :: myelement.find_elements_by_xpath(".//a") However, this will select all links in the page itself. :: myelement.find_elements_by_xpath("//a") """
return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_class_name(self, name):
"""Finds element within this element's children by class name. :Args:
- name - class name to search for.
"""
return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name):
"""Finds a list of elements within this element's children by class name. :Args:
- name - class name to search for.
"""
return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector):
"""Finds element within this element's children by CSS selector. :Args:
- css_selector - CSS selctor string, ex: 'a.nav#home'
"""
return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector):
"""Finds a list of elements within this element's children by CSS selector. :Args:
- css_selector - CSS selctor string, ex: 'a.nav#home'
"""
return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def send_keys(self, *value):
"""Simulates typing into the element. :Args:
- value - A string for typing, or setting form fields. For setting
file inputs, this could be a local file path. Use this to send simple key events or to fill out form fields:: form_textfield = driver.find_element_by_name('username')
form_textfield.send_keys("admin") This can also be used to set file inputs. :: file_input = driver.find_element_by_name('profilePic')
file_input.send_keys("path/to/profilepic.gif")
# Generally it's better to wrap the file path in one of the methods
# in os.path to return the actual path to support cross OS testing.
# file_input.send_keys(os.path.abspath("path/to/profilepic.gif")) """
# transfer file to another machine only if remote driver is used
# the same behaviour as for java binding
if self.parent._is_remote:
local_file = self.parent.file_detector.is_local_file(*value)
if local_file is not None:
value = self._upload(local_file) self._execute(Command.SEND_KEYS_TO_ELEMENT,
{'text': "".join(keys_to_typing(value)),
'value': keys_to_typing(value)}) # RenderedWebElement Items
def is_displayed(self):
"""Whether the element is visible to a user."""
# Only go into this conditional for browsers that don't use the atom themselves
if self._w3c and self.parent.capabilities['browserName'] == 'safari':
return self.parent.execute_script(
"return (%s).apply(null, arguments);" % isDisplayed_js,
self)
else:
return self._execute(Command.IS_ELEMENT_DISPLAYED)['value'] @property
def location_once_scrolled_into_view(self):
"""THIS PROPERTY MAY CHANGE WITHOUT WARNING. Use this to discover
where on the screen an element is so that we can click it. This method
should cause the element to be scrolled into view. Returns the top lefthand corner location on the screen, or ``None`` if
the element is not visible. """
if self._w3c:
old_loc = self._execute(Command.W3C_EXECUTE_SCRIPT, {
'script': "arguments[0].scrollIntoView(true); return arguments[0].getBoundingClientRect()",
'args': [self]})['value']
return {"x": round(old_loc['x']),
"y": round(old_loc['y'])}
else:
return self._execute(Command.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW)['value'] @property
def size(self):
"""The size of the element."""
size = {}
if self._w3c:
size = self._execute(Command.GET_ELEMENT_RECT)['value']
else:
size = self._execute(Command.GET_ELEMENT_SIZE)['value']
new_size = {"height": size["height"],
"width": size["width"]}
return new_size def value_of_css_property(self, property_name):
"""The value of a CSS property."""
return self._execute(Command.GET_ELEMENT_VALUE_OF_CSS_PROPERTY, {
'propertyName': property_name})['value'] @property
def location(self):
"""The location of the element in the renderable canvas."""
if self._w3c:
old_loc = self._execute(Command.GET_ELEMENT_RECT)['value']
else:
old_loc = self._execute(Command.GET_ELEMENT_LOCATION)['value']
new_loc = {"x": round(old_loc['x']),
"y": round(old_loc['y'])}
return new_loc @property
def rect(self):
"""A dictionary with the size and location of the element."""
return self._execute(Command.GET_ELEMENT_RECT)['value'] @property
def screenshot_as_base64(self):
"""
Gets the screenshot of the current element as a base64 encoded string. :Usage:
img_b64 = element.screenshot_as_base64
"""
return self._execute(Command.ELEMENT_SCREENSHOT)['value'] @property
def screenshot_as_png(self):
"""
Gets the screenshot of the current element as a binary data. :Usage:
element_png = element.screenshot_as_png
"""
return base64.b64decode(self.screenshot_as_base64.encode('ascii')) def screenshot(self, filename):
"""
Saves a screenshot of the current element to a PNG image file. Returns
False if there is any IOError, else returns True. Use full paths in
your filename. :Args:
- filename: The full path you wish to save your screenshot to. This
should end with a `.png` extension. :Usage:
element.screenshot('/Screenshots/foo.png')
"""
if not filename.lower().endswith('.png'):
warnings.warn("name used for saved screenshot does not match file "
"type. It should end with a `.png` extension", UserWarning)
png = self.screenshot_as_png
try:
with open(filename, 'wb') as f:
f.write(png)
except IOError:
return False
finally:
del png
return True @property
def parent(self):
"""Internal reference to the WebDriver instance this element was found from."""
return self._parent @property
def id(self):
"""Internal ID used by selenium. This is mainly for internal use. Simple use cases such as checking if 2
webelements refer to the same element, can be done using ``==``:: if element1 == element2:
print("These 2 are equal") """
return self._id def __eq__(self, element):
return hasattr(element, 'id') and self._id == element.id def __ne__(self, element):
return not self.__eq__(element) # Private Methods
def _execute(self, command, params=None):
"""Executes a command against the underlying HTML element. Args:
command: The name of the command to _execute as a string.
params: A dictionary of named parameters to send with the command. Returns:
The command's JSON response loaded into a dictionary object.
"""
if not params:
params = {}
params['id'] = self._id
return self._parent.execute(command, params) def find_element(self, by=By.ID, value=None):
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_CHILD_ELEMENT,
{"using": by, "value": value})['value'] def find_elements(self, by=By.ID, value=None):
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_CHILD_ELEMENTS,
{"using": by, "value": value})['value'] def __hash__(self):
return int(hashlib.md5(self._id.encode('utf-8')).hexdigest(), 16) def _upload(self, filename):
fp = IOStream()
zipped = zipfile.ZipFile(fp, 'w', zipfile.ZIP_DEFLATED)
zipped.write(filename, os.path.split(filename)[1])
zipped.close()
content = base64.encodestring(fp.getvalue())
if not isinstance(content, str):
content = content.decode('utf-8')
try:
return self._execute(Command.UPLOAD_FILE, {'file': content})['value']
except WebDriverException as e:
if "Unrecognized command: POST" in e.__str__():
return filename
elif "Command not found: POST " in e.__str__():
return filename
elif '{"status":405,"value":["GET","HEAD","DELETE"]}' in e.__str__():
return filename
else:
raise e
***微信扫一扫,关注“python测试开发圈”,了解更多测试教程!***
Selenium with Python 009 - WebDriver API的更多相关文章
- Selenium2+Python:Webdriver API速记手册
由于web自动化常常需要控制浏览器行为和操作页面元素,相关函数又比较多,于是再此记下一份Webdriver API查阅文档以备不时之需. 参考:虫师<Selenium2自动化测试实战>,和 ...
- Selenium with Python 008 - WebDriver 元素等待
如今大多数Web应用程序使用Ajax技术,当浏览器在加载页面时,页面上的元素可能并不是同时被加载完成的,这给元素的定位增加了困难.如果因为在加载某个元素时延迟而造成ElementNotVisibleE ...
- python+selenium自动化软件测试(第2章):WebDriver API
2.1 操作元素基本方法 前言前面已经把环境搭建好了,从这篇开始,正式学习selenium的webdriver框架.我们平常说的 selenium自动化,其实它并不是类似于QTP之类的有GUI界面的可 ...
- [译]Selenium Python文档:七、WebDriver API接口
由于API文档格式不太适合cnblog博客,暂且翻译一部分,且暂未校对 注意:这不是官方文档,官方 API文档在这里. 本章包含Selenium WebDriver的所有接口 推荐import风格 本 ...
- 转:python webdriver API 之操作测试对象
一般来说,所有有趣的操作与页面交互都将通过 WebElement 接口,包括上一节中介绍的对象定位,以及本节中需要介绍的常对象操作.webdriver 中比较常用的操作元素的方法有下面几个: cle ...
- Selenium WebDriver Api 知识梳理
之前一直没有系统的梳理WebDriver Api的相关知识,今天借此机会整理一下. 1.页面元素定位 1.1.8种常用定位方法 # id定位 driver.find_element_by_id() # ...
- Selenium自动化测试Python二:WebDriver基础
WebDriver基础 欢迎阅读WebDriver基础讲义.本篇讲义将会重点介绍Selenium WebDriver的环境搭建和基本使用方法. WebDriver环境搭建 Selenium WebDr ...
- selenium初识(二)——之webdriver API
配置完的环境之后,我们先来写一个小脚本: # __Author__:"Jim_xie" from selenium import webdriver from time impor ...
- Selenium自动化测试Python四:WebDriver封装
WebDriver 封装 欢迎阅读WebDriver封装讲义.本篇讲义将会重点介绍Selenium WebDriver API的封装的概念和方法,以及使用封装进行自动化测试的设计. WebDriver ...
随机推荐
- HTTP Keep-Alive是什么?如何工作?(转)
add by zhj: 本篇只是Keep-Alive的第一篇,其它文章参见下面的列表. 原文: HTTP Keep-Alive是什么?如何工作? 1. HTTP Keep-Alive是什么?如何工作? ...
- hibernate自动建表之engine设置
1.MYSQL的数据库引擎中,只有InnoDB和BDB(Berkley DB )包括了对事务处理和外键的支持.如果数据引擎建为MyISAM则rollback无效. 2.而hibernate自动建表的时 ...
- sql server中index的REBUILD和REORGANIZE的区别及工作方式
sql server中index的REBUILD和REORGANIZE 转自:https://www.cnblogs.com/flysun0311/archive/2013/12/05/3459451 ...
- Deeplearning——动态图 vs. 静态图
动态图 vs. 静态图 在 fast.ai,我们在选择框架时优先考虑程序员编程的便捷性(能更方便地进行调试和更直观地设计),而不是框架所能带来的模型加速能力.这也正是我们选择 PyTorch 的理由, ...
- springcloud Hystrix fallback无效
在使用feign调用服务的时候防止雪崩效应,因此需要添加熔断器.(基于springboot2.0) 一.在控制器的方法上添加 fallbackMethod ,写一个方法返回,无须在配置文件中配置,因 ...
- PyMySQL防止SQL注入
一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...
- Delphi 正则表达式语法(2): 或者与重复
Delphi 正则表达式语法(2): 或者与重复 // | 号的使用, | 是或者的意思 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create ...
- 练Focus T25必看!T25课表 视频与成功案例汇总
练Focus T25必看!T25课表 视频与成功案例汇总! [复制链接] http://jianfei.39.net/thread-3645799-1.html 小西i减肥 ...
- pt-osc测试
pt-osc测试 1.原表必须存在主键 PRIMARY KEY 或者 UNIQUE KEY The new table `darren`.`_t_user_new` does not have a P ...
- 非阻塞套接字与IO多路复用
我们了解了socket之后已经知道,普通套接字实现的服务端的缺陷:一次只能服务一个客户端! 并且,为了使一个客户端能够不断收发消息,我们还要使用while循环来轮询,这极大地降低了我们的效率 acce ...