草庐IT

selenium页面元素定位、操作

tomoe女孩一米九 2023-04-12 原文

  
1、通过页面开发者工具(点击键盘F12或者空白处右击点击检查)中的element,查看页面html代码;
2、点击开发者工具左上角鼠标按钮;
3、鼠标移动至需要定位元素位置;
4、高亮显示;
5、右击选择定位方式。

1 打开 / 关闭浏览器

from selenium import webdriver
import time
from selenium.webdriver.common.by import By

browser = webdriver.Chrome()
url = 'https://www.csdn.net/'
browser.get(url)
browser.maximize_window()
time.sleep(5)
# browser.close() 
browser.quit() 

注意:
关闭浏览器close和quit的区别:
以下是两个函数的描述,可见close() 只关闭当前窗口;quit() 退出驱动程序并关闭所有相关窗口。

    def close(self) -> None:
        """
        Closes the current window.

        :Usage:
            ::

                driver.close()
        """
        self.execute(Command.CLOSE)

    def quit(self) -> None:
        """
        Quits the driver and closes every associated window.

        :Usage:
            ::

                driver.quit()
        """
        try:
            self.execute(Command.QUIT)
        finally:
            self.stop_client()
            self.command_executor.close()

2 打开URL链接

browser = webdriver.Chrome()
browser.get('https://www.csdn.net/')
browser.maximize_window()
time.sleep(5)
browser.quit()

3 定位单个页面元素

  使用find_element函数来定位元素。

3.1 通过ID定位

  id值在一个页面中是唯一的。

browser = webdriver.Chrome()
browser.get('https://www.csdn.net/')
browser.maximize_window()
time.sleep(5)
browser.find_element(By.ID, "toolbar-search-input").send_keys("python")
time.sleep(5)
browser.find_element(By.ID, "toolbar-search-button").click()
time.sleep(5)
browser.quit()

3.2 通过name定位

  name属性在同一个表单中唯一,但在页面不唯一。若有两个name属性相同的元素,使用该方法会定位到name属性第一次出现的地方。

browser.find_element(By.NAME, "username").click()

3.3 通过classname定位

  class属性同样不唯一,页面中可能会出现多个,使用该方法定位到的也是第一个拥有该class属性的元素。

browser.find_element(By.CLASS_NAME, "blog-nav-box").click()

3.4 通过CSS定位

  传入的参数格式:标签名[属性名=属性值],通过标签与属性的组合来唯一的定位页面元素

browser.find_element(By.CSS_SELECTOR, "input[id='toolbar-search-input']").click()

3.5 通过链接的文本信息定位

  这种方法只适合定位链接元素

browser.find_element(By.By.LINK_TEXT, "Python").click()

3.6 通过XPath定位

browser = webdriver.Chrome()
browser.get('https://www.csdn.net/')
browser.maximize_window()
browser.find_element(By.XPATH, '//*[@id="csdn-toolbar"]/div/div/div[3]/div/div[3]/a').click()
browser.find_element(By.XPATH, '//*[@id="toolbar-search-input"]').send_keys("人工智能")
browser.find_element(By.XPATH, '//*[@id="toolbar-search-button"]').click()
time.sleep(5)
browser.quit()
3.6.1 xpath语法
/表示一个层级,从根节点开始定位(绝对路径)
//表示多个层级,从任意位置开始定位
.选取当前节点
..选取当前节点的父节点
@选取属性
*匹配任何元素节点
//*选取文档中的所有元素
@*匹配任何属性节点
//title[@*]选取所有带有属性的title元素
3.6.2 实例
/div/div[3]选取div下的第三个div的元素
//div选取所有div元素,不管他们在文档中的位置
div//title选取div元素的后代的所有title元素
//@lang选取名为lang的所有属性
//title[@lang='eng]选取所有title元素,并且带有值为eng的lang属性
//div|//title选取文档中的所有div和title元素

4 操作

4.1 基本操作

# 清除文本框内容:使用clear()方法
browser.find_element(By.XPATH, '//*[@id="toolbar-search-input"]').clear() 
# 点击
browser.find_element(By.XPATH, '//*[@id="toolbar-search-button"]').click()  
# 填写文本内容
browser.find_element(By.XPATH, '//*[@id="toolbar-search-input"]').send_keys("人工智能") 
# 获取元素的属性信息:使用get_attribute(“属性名”)
browser.find_element(by, element_value).get_attribute('value') 

4.2 切换窗口、框架

 # 切换fram框架, "frame_value"可以是id、name属性值,也可以是序号index,假如有2个iframe
 # 第一个序号就是0
browser.switch_to.frame(frame_value)

# 切换窗口
handles = browser.window_handles # 获取当前全部窗口句柄集合
now_handle = driver.current_window_handle # 获取当前窗口句柄
browser.switch_to.window(now_handle) # 切换至当前窗口

# 切换alert
# accept - 点击【确认】按钮
# dismiss - 点击【取消】按钮(如有按钮)
# send_keys - 输入内容(如有输入框)
alert = switch_to.alert().accept()    #点击确认

5 封装selenium的基本操作

def open_browser0(public_devices):
    """
    打开浏览器------无头模式
    :param public_devices:
    """
    global browser
    ch_options = Options()
    ch_options.add_argument("--headless")  # 为chrome设置无头模式 options=ch_options
    public_devices.driver = webdriver.Chrome()
    log.info("打开浏览器:%s" % public_devices.driver)
    browser = public_devices.driver
    browser.get("http://%s" % public_devices.path)
    log.info("get_url: %s" % public_devices.path)
    browser.maximize_window()
    time.sleep(2)
    
def close_browser():
    """
    logout,并关闭浏览器
    """
    global browser
    browser.quit()
    log.info("关闭浏览器")

@exist
def logout(element_value, element_type):
    """
    退出登录
    """
    global browser
    alert_prencence()
    res = browser.switch_to.default_content()
    log.info("切换至默认frame")
    click_element_by(element_value, element_type)
    log.info("退出登录")

def execute(cmd):
    """
    执行命令
    :param cmd:
    """
    global browser
    log.info(browser.execute(cmd))

def refresh():
    """
    刷新页面
    """
    global browser
    browser.refresh()
    log.info("刷新页面")
    time.sleep(2)

@exist
def check_element(node_element):
    """
    判断用户是否可见该节点元素
    :param node_element:
    :return:
    """
    if node_element.is_displayed():
        return True
    else:
        return False

def switch_to_frame(frame_value):
    """
    切换fame
    :param frame_value:
    """
    global browser
    browser.switch_to.frame(frame_value)
    log.info("切换frame到:%s" % frame_value)

def switch_to_window(window_value, window_type):
    """
    切换浏览器窗口
    :param window_value:
    :param window_type:
    """
    global browser
    handles = browser.window_handles
    log.info(browser.switch_to.window(handles[window_value]))

@exist
def set_element_text(element_value, set_value, element_type):
    """
    输入框输入
    :param element_value:元素定位
    :param set_value:要设置的值
    :param element_type:元素类型,支持id、xpath、link_text、partial_link_text、name、tag_name、class_name、css_selector
    """
    global browser
    by = whichType(element_type)
    browser.find_element(by, element_value).send_keys(set_value)
    log.info("输入:%s", set_value)
    time.sleep(2)

@exist
def clear_element_text(element_value, element_type='XPATH'):
    """
    清空输入框
    :param element_value:元素定位
    :param element_type:元素类型,支持id、xpath、link_text、partial_link_text、name、tag_name、class_name、css_selector
    """
    global browser
    by = whichType(element_type)
    log.info(browser.find_element(by, element_value).clear())
    time.sleep(2)

@exist
def get_text(element_value, element_type):
    """
    获取元素,并打印
    :param element_value:元素定位
    :param element_type:元素类型,支持id、xpath、link_text、partial_link_text、name、tag_name、class_name、css_selector
    """
    global browser
    by = whichType(element_type)
    element = browser.find_elements(by, element_value)
    res = element.__getattribute__('text')
    log.info("获取元素", res)
    return res

@exist
def get_element_attribute(element_value, element_type):
    """
    获取元素属性并返回
    :param element_value:元素定位
    :param element_type:元素类型,支持id、xpath、link_text、partial_link_text、name、tag_name、class_name、css_selector
    :return:
    """
    global browser
    by = whichType(element_type)
    attribute = browser.find_element(by, element_value).get_attribute('value')
    log.info("获取元素属性:%s", attribute)
    return attribute


@exist
def click_element_by(element_value, element_type):
    """
    点击元素
    :param element_value:元素定位
    :param element_type:元素类型,支持id、xpath、link_text、partial_link_text、name、tag_name、class_name、css_selector
    """
    global browser
    by = whichType(element_type)
    log.info("点击元素 %s", element_value)
    browser.find_element(by, element_value).click()
    time.sleep(2)


def alert_prencence():
    result = EC.alert_is_present()(browser)
    if result:
        log.info(result.text)
        result.accept()
    else:
        log.info("未弹出!")

6 判断元素是否存在

  通过添加装饰器,不改变原函数代码、不改变函数返回值,判断元素是否存在。

def exist(func):
    """
    装饰器,判断元素是否存在
    :param func:需要判断元素的函数
    :return:函数
    """
    global browser
    def wrapper(*args, **kwargs):
        keys = inspect.signature(func).parameters  # 得到的是不可迭代对象
        keys_str = str(keys)
        if keys_str.find('element_type') >= 0 and keys_str.find('element_value') >= 0:
            # 变成list后,可根据索引获取参数名对应的参数值
            keys_lis = list(keys)
            index_type = keys_lis.index("element_type") # 获取元素类型索引
            index_value = keys_lis.index("element_value") # 获取元素值索引
            element_type = whichType(args[index_type]) # 取对应索引参数值
            element_value = args[index_value] 
        try:
            WebDriverWait(browser, 5, 0.5).until(EC.presence_of_element_located((element_type, element_value)))
            return func(*args, **kwargs)
        except TimeoutException as e:
            log.error("timeout")
            raise ElementnotFoundException(element_type, element_value)
    return wrapper

class ElementnotFoundException(Exception):
    """
    自定义异常
    :param
    :return:字符串
    """

    def __init__(self, element_type, element_value):
        self.element_type = element_type
        self.element_value = element_value

    def __str__(self):
        log.error("\n找不到元素: %s" % self.element_value)
        # return "\n找不到元素: %s" % self.element_value

有关selenium页面元素定位、操作的更多相关文章

  1. ruby - 在哈希的键数组中追加元素 - 2

    查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用

  2. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  3. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  4. ruby - Hanami link_to 助手只呈现最后一个元素 - 2

    我是HanamiWorld的新人。我已经写了这段代码:moduleWeb::Views::HomeclassIndexincludeWeb::ViewincludeHanami::Helpers::HtmlHelperdeftitlehtml.headerdoh1'Testsearchengine',id:'title'hrdiv(id:'test')dolink_to('Home',"/",class:'mnu_orizontal')link_to('About',"/",class:'mnu_orizontal')endendendendend我在模板上调用了title方法。htm

  5. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  6. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  7. ruby - 在 ASP 页面上 Mechanize 中断 - 2

    require'mechanize'agent=Mechanize.newlogin=agent.get('http://www.schoolnet.ch/DE/HomeDE.htm')agent.clicklogin.link_withtext:/Login/然后我得到Mechanize::UnsupportedSchemeError。 最佳答案 Mechanize不支持javascript但您可以将搜索字段添加到表单并为其分配搜索词并使用mechanize提交表单form=page.forms.firstform.add_fie

  8. ruby - 将n维数组的每个元素乘以Ruby中的数字 - 2

    在Ruby中,是否有一种简单的方法可以将n维数组中的每个元素乘以一个数字?这样:[1,2,3,4,5].multiplied_by2==[2,4,6,8,10]和[[1,2,3],[1,2,3]].multiplied_by2==[[2,4,6],[2,4,6]]?(很明显,我编写了multiplied_by函数以区别于*,它似乎连接了数组的多个副本,不幸的是这不是我需要的)。谢谢! 最佳答案 它的长格式等价物是:[1,2,3,4,5].collect{|n|n*2}其实并没有那么复杂。你总是可以使你的multiply_by方法:c

  9. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

  10. ruby-on-rails - 如何让 Rails View 返回其关联的操作名称? - 2

    我有一个非常简单的Controller来管理我的Rails应用程序中的静态页面:classPagesController我怎样才能让View模板返回它自己的名字,这样我就可以做这样的事情:#pricing.html.erb#-->"Pricing"感谢您的帮助。 最佳答案 4.3RoutingParametersTheparamshashwillalwayscontainthe:controllerand:actionkeys,butyoushouldusethemethodscontroller_nameandaction_nam

随机推荐