上一篇博文简要

在上一篇博文中已得知:使用 execute 向远程服务器发送请求会通过 webdriver 与浏览器交互,且发送已定义的命令常量可获得一些相关信息。

其中 execute 方法实现已经在上一篇博文中有实现说明。并且在我们已经知道 webdriver基类(selenium.webdriver.remote.webdriver)中,实现了操作页面元素的基本方法。

通过简单运用全面学习

假设现在需要打开百度,搜索“CSDN A757291228”该如何进行操作呢?
通过查找 webdriver基类(selenium.webdriver.remote.webdriver)找到了以下几个查找元素的方法:

def find_element_by_id(self, id_):        """Finds an element by id.        :Args:         - id\_ - The id of the element to be found.        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = 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.        :Returns:         - list of WebElement - a list with elements if any was found.  An           empty list if not        :Usage:            elements = 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.        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = 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.        :Returns:         - list of WebElement - a list with elements if any was found.  An           empty list if not        :Usage:            elements = 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.        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = 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.        :Returns:         - list of webelement - a list with elements if any was found.  an           empty list if not        :Usage:            elements = 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.        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = 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.        :Returns:         - list of webelement - a list with elements if any was found.  an           empty list if not        :Usage:            elements = driver.find_elements_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.        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = 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.        :Returns:         - list of webelement - a list with elements if any was found.  an           empty list if not        :Usage:            elements = 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 - name of html tag (eg: h1, a, span)        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = driver.find_element_by_tag_name('h1')        """        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 - name of html tag (eg: h1, a, span)        :Returns:         - list of WebElement - a list with elements if any was found.  An           empty list if not        :Usage:            elements = driver.find_elements_by_tag_name('h1')        """        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.        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = 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.        :Returns:         - list of WebElement - a list with elements if any was found.  An           empty list if not        :Usage:            elements = 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 - CSS selector string, ex: 'a.nav#home'        :Returns:         - WebElement - the element if it was found        :Raises:         - NoSuchElementException - if the element wasn't found        :Usage:            element = 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 - CSS selector string, ex: 'a.nav#home'        :Returns:         - list of WebElement - a list with elements if any was found.  An           empty list if not        :Usage:            elements = driver.find_elements_by_css_selector('.foo')        """        return self.find_elements(by=By.CSS_SELECTOR, value=css_selector)def find_element(self, by=By.ID, value=None):        """        Find an element given a By strategy and locator. Prefer the find_element_by_* methods when        possible.        :Usage:            element = driver.find_element(By.ID, 'foo')        :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):        """        Find elements given a By strategy and locator. Prefer the find_elements_by_* methods when        possible.        :Usage:            elements = driver.find_elements(By.CLASS_NAME, 'foo')        :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 empty list if driver returns null        # See https://github.com/SeleniumHQ/selenium/issues/4555        return self.execute(Command.FIND_ELEMENTS, {            'using': by,            'value': value})['value'] or []

从以上实现的方法中,execute 方法实现在这里不在赘述实现,上一节已有说明,本节主要介绍方法使用。

首先查看 find_element_by_id 方法的使用,在方法说明中已经介绍使用方法:

element = driver.find_element_by_id('foo')

该方法注释说明为(以下为了清晰说明,使用截图展示注释):

通过注释说明得知,find_element_by_id 方法找到id为指定值的元素,并返回这个元素。

查看具体实现为:

self.find_element(by=By.ID, value=id_)

以上实现调用了 find_element 方法,并且传入 by的值为By.ID,随后传入具体值;首先查看By类(selenium.webdriver.common.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"

这个类与Command(selenium.webdriver.remote.command)类作用类似,上节已说明Command在这里也不过多说明By。

在这里查看 find_element 方法实现:

def find_element(self, =By.ID, value=None):    """    Find an element given a By strategy and locator. Prefer the find_element_by_* methods when    possible.    :Usage:        element = driver.find_element(By.ID, 'foo')    :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_SEhj0ECTOR            value = '[name="%s"]' % value    return self.execute(Command.FIND_ELEMENT, {        'using': by,        'value': value})['value']

以上类首先判断查找类型,随后进行值的拼接,最后把查找方式和值传入 execute 方法中,随后返回元素对象。

几乎所有的元素查找方法,实现相同,我们简单实用这个函数。

写代码前,我们需要打开百度网址,审查元素查找id值:

得到输入框的id值为kw,那么代码应该如下:

from selenium import webdriverdriver = webdriver.Chrome()driver.get("https://www.baidu.com/")input = driver.find_element_by_id('kw')# print('作者博客:https://blog.csdn.net/A757291228')#支持原创,转载请贴上链接

由于查到到元素后返回的是元素对象:

在元素类(selenium.webdriver.remote.webelement)中查找方法,找到如下方法:

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)})# 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)

得知 send_keys 也是通过 execute 发送命令得到结果。在注释说明中得到了 send_keys 的使用方法为:

form_textfield.send_keys("admin")

我们修改之前的代码:

from selenium import webdriverdriver = webdriver.Chrome()driver.get("https://www.baidu.com/")input = driver.find_element_by_id('kw')input.send_keys("CSDN A757291228")# print('作者博客:https://blog.csdn.net/A757291228')#支持原创,转载请贴上链接

最后还查个点击即可完成自动化搜索功能;我们继续查看元素类,找到如下方法:

def click(self):        """Clicks the element."""        self._execute(Command.CLICK_ELEMENT)

click 方法与 send_keys 方法实现相同,不在赘述。直接使用click方法即可进行元素的点击。查找百度搜索点击按钮的id:

修改代码如下:

from selenium import webdriverdriver = webdriver.Chrome()driver.get("https://www.baidu.com/")input = driver.find_element_by_id('kw')input.send_keys("CSDN A757291228")enter = driver.find_element_by_id('su')enter.click()# print('作者博客:https://blog.csdn.net/A757291228')#支持原创,转载请贴上链接

运行结果如下:

总结

我们简单的学习了使用 selenium 打开浏览器搜索 了“CSDN A757191228” ,在这个简单的例子的学习中,学习到的不仅是这个例子原本的那几行代码;通过实现分析,了解了其它功能函数所在的位置,可以通过这些功能函数,实现自己想要的功能!

从框架实现上分析可以事半功倍的学习框架的使用,以及了解框架的实现原理,更加利于我们的开发使用。