当前位置: 首页 > news >正文

自学Python第十八天-自动化测试框架(二):DrissionPage、appium

自学Python第十八天-自动化测试框架(二):DrissionPage、appium

  • DrissionPage
    • 环境和安装配置
    • 准备工作
    • 简单的使用示例
      • 控制浏览器
      • 收发数据包
      • 模式切换
    • 浏览器模式
      • 创建浏览器对象
      • 访问页面
        • 加载模式
          • none 模式技巧
      • 获取页面信息
      • 页面交互
      • 查找元素
        • `ele()` 和 `eles()`
        • `parent()` 、`child()` 和 `children()`
        • `next()`、`nexts()` 和 `prev()`、`prevs()`
        • `after()`、`afters()` 和 `before()`、`befores()`
        • 匹配模式
        • 查找语法
        • 处理 frame
        • 简化写法
      • 获取元素信息
      • 元素交互
  • appium

DrissionPage

由于 selenium 的缺点过多,pyppeteer 使用较为复杂,也可以使用 DrissionPage 库来进行自动化测试。

DrissionPage 官方文档

DrissionPage 的优点有:

  • 极简的语法规则,定位元素更加容易
  • 无处不在的等待和自动重试功能,使得容错能力大大增加
  • 允许反复使用已经打开的浏览器,方便调试
  • 把 iframe 看作普通元素,无需切入切出,可以直接查找内容
  • 良好的异步支持

环境和安装配置

DrissionPage需要的环境为:

  • 操作系统:Windows、Linux 或 Mac。
  • python 版本:3.6 及以上
  • 支持浏览器:Chromium 内核(如 Chrome 和 Edge)

使用 pip 安装 DrissionPage:
pip install DrissionPage

DrissionPage 包含三种主要页面类。根据需要在其中选择使用。

  • 如果只要控制浏览器,导入ChromiumPagefrom DrissionPage import ChromiumPage
  • 如果只要收发数据包,导入SessionPagefrom DrissionPage import SessionPage
  • WebPage是功能最全面的页面类,既可控制浏览器,也可收发数据包。from DrissionPage import WebPage

另外 DrissionPage 还有一些配置工具类

类名描述引入方式
ChromiumOptions用于设置浏览器启动参数。这些参数只有在启动浏览器时有用,接管已存在的浏览器时是不生效的。from DrissionPage import ChromiumOptions
SessionOptions用于配置SessionPage或WebPages 模式的连接参数。from DrissionPage import SessionOptions
Settings用于设置全局运行配置,如找不到元素时是否抛出异常等。from DrissionPage.common import Settings
Keys键盘按键类,用于键入 ctrl、alt 等按键。from DrissionPage.common import Keys
Actions动作链,用于执行一系列动作。在浏览器页面对象中已有内置,无如特殊需要无需主动导入。from DrissionPage.common import Actions
By与 selenium 一致的By类,便于项目迁移。from DrissionPage.common import By
wait_until可等待传入的方法结果为真from DrissionPage.common import wait_until
make_session_ele从 html 文本生成ChromiumElement对象from DrissionPage.common import make_session_ele
configs_to_here把配置文件复制到当前路径from DrissionPage.common import configs_to_here
get_blob获取指定的 blob 资源from DrissionPage.common import get_blob
ElementNotFoundError异常类,全部在路径DrissionPage.errorsfrom DrissionPage.errors import ElementNotFoundError

另外 DrissionPage 还有一些衍生对象,例如 TabElement 等对象是由 Page 对象生成的,开发过程中需要类型判断时需要导入这些类型。

from DrissionPage.items import SessionElement
from DrissionPage.items import ChromiumElement
from DrissionPage.items import ShadowRoot
from DrissionPage.items import NoneElement
from DrissionPage.items import ChromiumTab
from DrissionPage.items import WebPageTab
from DrissionPage.items import ChromiumFrame

准备工作

如果只使用收发数据包功能,无需任何准备工作。

如果要控制浏览器,需设置浏览器路径。程序默认设置控制 Chrome,所以下面用 Chrome 演示。如果要使用 Edge 或其它 Chromium 内核浏览器,设置方法是一样的。

  1. 尝试启动浏览器
    默认状态下,程序会自动在系统内查找 Chrome 路径。执行以下代码,浏览器启动并且访问了项目文档,说明可直接使用,跳过后面的步骤即可。
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.get('http://g1879.gitee.io/DrissionPageDocs')
  1. 设置路径
    如果上面的步骤提示出错,说明程序没在系统里找到 Chrome 浏览器。可用以下其中一种方法设置,设置会持久化记录到默认配置文件,之后程序会使用该设置启动。
    查找浏览器路径
    设置方法有2种:

方法一:新建一个临时 py 文件,并输入以下代码,填入您电脑里的 Chrome 浏览器可执行文件路径,然后运行。

from DrissionPage import ChromiumOptionspath = r'D:\Chrome\Chrome.exe'  # 请改为你电脑内Chrome可执行文件路径
ChromiumOptions().set_browser_path(path).save()

这段代码会把浏览器路径记录到配置文件,今后启动浏览器皆以新路径为准。另外,如果是想临时切换浏览器路径以尝试运行和操作是否正常,可以去掉 .save(),以如下方式结合第1️⃣步的代码。

from DrissionPage import ChromiumPage, ChromiumOptionspath = r'D:\Chrome\Chrome.exe'  # 请改为你电脑内Chrome可执行文件路径
co = ChromiumOptions().set_browser_path(path)
page = ChromiumPage(co)
page.get('http://g1879.gitee.io/DrissionPageDocs')

方法二:在命令行输入以下命令(路径改成自己电脑里的):
dp -p D:\Chrome\chrome.exe 注意要先使用 cd 命令定位到项目路径

简单的使用示例

DrissionPage 的三个主要的类 ChromiumPageSessionPageWebPage 分别用于主要的三种模式:浏览器模式、数据包模式、混合模式。

控制浏览器

DrissionPage 可以类似于 selenium 一样直接控制浏览器。

from DrissionPage import ChromiumPage# 创建页面对象,并启动或接管浏览器
page = ChromiumPage()
# 跳转到登录页面
page.get('https://gitee.com/login')
# 定位到账号文本框,获取文本框元素
ele = page.ele('#user_login')
# 输入对文本框输入账号
ele.input('您的账号')
# 定位到密码文本框并输入密码
page.ele('#user_password').input('您的密码')
# 点击登录按钮
page.ele('@value=登 录').click()

收发数据包

DrissionPage 可以类似于 requests 一样直接收发数据包获取页面代码,并使用特定的解析语法解析文本获取数据。

from DrissionPage import SessionPage# 创建页面对象
page = SessionPage()# 爬取3页
for i in range(1, 4):# 访问某一页的网页page.get(f'https://gitee.com/explore/all?page={i}')# 获取所有开源库<a>元素列表links = page.eles('.title project-namespace-path')# 遍历所有<a>元素for link in links:# 打印链接信息print(link.text, link.link)

模式切换

DrissionPage 还能在两种模式间切换执行。切换模式是用来应付登录检查很严格的网站,可以用浏览器处理登录,再转换模式用收发数据包的形式来采集数据。

from DrissionPage import WebPage# 创建页面对象
page = WebPage()
# 访问网址
page.get('https://gitee.com/explore')
# 查找文本框元素并输入关键词
page('#q').input('DrissionPage')
# 点击搜索按钮
page('t:button@tx():搜索').click()
# 等待页面加载
page.wait.load_start()
# 切换到收发数据包模式
page.change_mode()
# 获取所有行元素
items = page('#hits-list').eles('.item')
# 遍历获取到的元素
for item in items:# 打印元素文本print(item('.title').text)print(item('.desc').text)print()

浏览器模式

ChromiumPage()创建页面对象。根据不同的配置,可以接管已打开的浏览器,也可以启动新的浏览器。程序结束时,被打开的浏览器不会主动关闭,以便下次运行程序时使用(由VSCode启动的会被关闭)。新手在使用无头模式时需注意,程序关闭后其实浏览器进程还在,只是看不见。

ChromiumPageWebPage对象为单例,每个浏览器只能有一个该对象。对同一个浏览器重复使用ChromiumPage获取的都是同一个对象。

创建浏览器对象

from DrissionPage import ChromiumPagepage = ChromiumPage()

创建ChromiumPage对象时会在指定端口启动浏览器,或接管该端口已有浏览器。默认情况下,程序使用 9222 端口,浏览器可执行文件路径为’chrome’。如路径中没找到浏览器可执行文件,Windows 系统下程序会在注册表中查找路径。
ChromiumPage创建时可接收三个参数:

初始化参数类型默认值说明
addr_or_optsstr int ChromiumOptionsNone浏览器启动配置或接管信息。传入 ‘ip: port’ 字符串、端口数字或ChromiumOptions对象时按配置启动或接管浏览器;为None时使用配置文件配置启动浏览器
tab_idstrNone要控制的标签页 id,为None则控制激活的标签页
timeoutfloatNone整体超时时间,为None则从配置文件中读取,默认10

如果需要已指定方式启动浏览器,可使用ChromiumOptions。它是专门用于设置浏览器初始状态的类,内置了常用的配置。

# 导入 ChromiumOptions
from DrissionPage import ChromiumPage, ChromiumOptions# 创建浏览器配置对象,指定浏览器路径
co = ChromiumOptions().set_browser_path(r'D:\chrome.exe')
# 设置不加载图片、静音、禁用js
co.no_imgs(True).mute(True)no_js(True)
co.incognito()  # 匿名模式(无痕模式)
co.headless()  # 无头模式
# 另外也支持 Chromium 内核浏览器的一系列启动配置参数
co.set_argument('--no-sandbox')  # 无沙盒模式
co.set_argument('--window-size', '800,600')		# 设置初始窗口大小
co.set_argument('--start-maximized')	# 设置启动时最大化
co.set_argument('--guest')	# 使用来宾模式打开浏览器
# 已经配置的参数也可以删除
co.remove_argument('--start-maximized')
co.remove_argument('--window-size')
# 用该配置创建页面对象
page = ChromiumPage(addr_or_opts=co)

访问页面

get() 方法用于跳转到一个网址,

from DrissionPage import ChromiumPagepage = ChromiumPage()
page.get('https://www.baidu.com')

该方法可以接收5个参数,并返回一个 bool 值,表示是否连接成功

参数名称类型默认值说明
urlstr必填目标 url,可指向本地文件路径
show_errmsgboolFalse连接出错时是否显示和抛出异常
retryintNone重试次数,为None时使用页面参数,默认 3
intervalfloatNone重试间隔(秒),为None时使用页面参数,默认 2
timeoutfloatNone加载超时时间(秒)
加载模式

加载模式是指程序在页面加载阶段的行为模式,有以下三种:

  • normal():常规模式,会等待页面加载完毕,超时自动重试或停止,默认使用此模式
  • eager():加载完 DOM 或超时即停止加载,不加载页面资源
  • none():超时也不会自动停止,除非加载完成

前两种模式下,页面加载过程会阻塞程序,直到加载完毕才执行后面的操作。none()模式下,只在连接阶段阻塞程序,加载阶段可自行根据情况执行stop_loading()停止加载。这样提供给用户非常大的自由度,可等到关键数据包或元素出现就主动停止页面加载,大幅提升执行效率。

可以在配置对象中进行设置:

from DrissionPage import ChromiumOptions, ChromiumPageco = ChromiumOptions().set_load_mode('none')
page = ChromiumPage(co)

也可以在运行中设置

from DrissionPage import ChromiumPagepage = ChromiumPage()
page.set.load_mode.eager()
page.get('https://g1879.gitee.io/drissionpagedocs')
none 模式技巧
  • 跟监听器配合,可在获取到需要的数据包时,主动停止加载。
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.set.load_mode.none()  # 设置加载模式为nonepage.listen.start('api/getkeydata')  # 指定监听目标并启动监听
page.get('http://www.hao123.com/')  # 访问网站
packet = page.listen.wait()  # 等待数据包
page.stop_loading()  # 主动停止加载
print(packet.response.body)  # 打印数据包正文
  • 跟元素查找配合,可在获取到某个指定元素时,主动停止加载。
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.set.load_mode.none()  # 设置加载模式为nonepage.get('http://www.hao123.com/')  # 访问网站
ele = page.ele('中国日报')  # 查找text包含“中国日报”的元素
page.stop_loading()  # 主动停止加载
print(ele.text)  # 打印元素text
  • 可等待到页面到达某种状态时,主动停止加载。比如多级跳转的登录,可等待 title 变化到最终目标网址时停止。
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.set.load_mode.none()  # 设置加载模式为nonepage.get('http://www.hao123.com/')  # 访问网站
page.wait.title_change('hao123')  # 等待title变化出现目标文本
page.stop_loading()  # 主动停止加载

获取页面信息

有一些常用的属性和方法能够获取页面的信息

  • html
    此属性返回当前页面 html 文本。返回类型:str
  • json
    此属性把请求内容解析成 json,并把这些数据转换为dict格式。需注意如果是API返回的json字符串,请使用 SessionPage 对象而不是 ChromiumPage
  • title
    此属性返回当前页面title文本。返回类型:str
  • user_agent
    此属性返回当前页面 user agent 信息。返回类型:str
  • save(path:Union[str,Path]=None, name:str=None, as_pdf:bool=False,**kwargs)->Union[str, bytes]
    当前页面保存为文件,同时返回保存的内容。接收 pathnameas_pdf 三个参数。如果pathname参数都为None,只返回内容,不保存文件。path为None保存到当前路径,name为None则使用 title 的值。as_pdfTrue保存为pdf文件,默认False保存为 mhtml。另外如果 as_pdfTrue返回值为文件字节数据。
  • url
    此属性返回当前访问的 url。返回类型:str
  • tab_id
    此属性返回当前标签页的 id。返回类型:str
  • states.is_loading
    此属性返回页面是否正在加载状态。返回类型:bool
  • states.is_alive
    此属性返回页面是否仍然可用,标签页已关闭则返回False
  • states.ready_state
    此属性返回页面当前加载状态,有 4 种:'connecting': 网页连接中,'loading':表示文档还在加载中,'interactive':DOM 已加载,但资源未加载完成,'complete':所有内容已完成加载。
  • states.has_alert
    此属性以布尔值返回页面是否存在弹出框。
  • cookies(as_dict:bool=False, all_domains:bool=False, all_info:bool=False)->Union[dict, list]
    此方法返回 cookies 信息。接收3个参数,默认均为Falseas_dictTrue时返回字典类型,为False返回 cookie 组成的列表;all_domains是否返回所有 cookies,为False只返回当前 url 的;all_info返回的 cookies 是否包含所有信息,False时只包含namevaluedomain信息
  • session_storage(item:str=None)->Union[dict, str]
    此方法用于获取 sessionStorage 信息,可获取全部或单个项。该方法接收一个默认为 None 的 str 型参数,是要获取的项目名称,为None则返回全部项目组成的字典。
  • local_storage(item:str=None)->Union[dict, str]
    此方法用于获取 localStorage 信息,可获取全部或单个项。参数和使用同 session_storage()

页面交互

一个 Tab 对象(ChromiumTabWebPageTab)控制一个浏览器的标签页,是页面控制的主要单位。ChromiumPageWebPage也控制一个标签页,只是它们增加了一些浏览器总体控制功能。

  • get(url:str, show_errmsg:bool=False, retry:int=None, interval:float=None, timeout:float=None)->bool
    该方法用于跳转到一个网址。当连接失败时,程序会进行重试。
  • back(steps:int=1)
    此方法用于在浏览历史中后退若干步。可以接收1个类型为 int 的参数,默认值为1,为后退步数。
  • forward(steps:int=1)
    此方法用于在浏览历史中前进若干步。参数和用法同 back()
  • refresh()
    此方法用于刷新当前页面,可以接收一个默认值为 False 的 bool 参数,刷新时是否忽略缓存。
  • stop_loading()
    此方法用于强制停止当前页面加载。
  • set.blocked_urls(urls:Union[str, list, tuple, None])
    此方法用于设置忽略的连接,接收一个必填的参数,类型可以为 str、list、tuple、None,需要忽略的 url,可以使用通配符'*',传入 None 时清空已设置项。例如不加载css文件:page.set.blocked_urls('*.css*')
  • run_js(script, *args, as_expr:bool=False, timetout:float=None)->Any
    此方法用于执行 js 脚本。参数script是js脚本文本或脚本路径;*args为传入js的参数,按顺序对应为arguments[0]arguments[1]…;as_expr是否作为表达式运行,为Trueargs参数无效;timetout是脚本超时时间,为None则使用页面timeouts.script设置。返回值为脚本执行结果。
  • run_js_loaded(script, *args, as_expr:bool=False, timetout:float=None)->Any
    此方法用于运行 js 脚本,执行前等待页面加载完毕。参数和使用同 run_js()
  • set.cookies(cookies:Union[RequestsCookieJar, list, tuple, str, dict])
    此方法用于设置 cookie。可以接收CookieJarlisttuplestrdict格式的cookies
  • set.cookies.clear()
    清除所有 cookie。
  • set.cookies.remove(name:str, url:str=None, domain:str=None, path:str=None)
    删除一个 cookie。参数分别是cookie的相应字段
  • set.session_storage(item:str, value:Union[str, False])
    设置或删除某项 sessionStorage 信息。item是要设置的项,valuestr时是设置的值,为False时表示删除该项。
  • set.local_storage(item:str, value:Union[str, False])
    设置或删除某项 localStorage 信息。参数和使用同 set.session_storage()
  • scroll.to_top()
    用于滚动页面到顶部,水平位置不变。
  • scroll.to_bottom()
    用于滚动页面到底部,水平位置不变。
  • scroll.to_see(loc_or_ele:Union[str, tuple, ChromiumElement], center:Union[bool, None]=None)
    滚动页面直到元素可见。参数loc_or_ele是元素的定位信息,可以是元素、定位符;参数center是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中。
  • set.scroll.wait_complete(on_off:bool=True)
    设置滚动后是否等待滚动结束。因为滚动时间不确定,容易导致程序不稳定。此项可以等待滚动结束再继续执行。
  • handle_alert(accept:Union[bool, None]=True, send:str=None, timeout:float=None, next_one:bool=False)->Union[str, False]
    处理提示框。能够设置等待时间,等待提示框出现才进行处理,若超时没等到提示框,返回False。也可只获取提示框文本而不处理提示框。 还可以处理下一个出现的提示框。参数accept为提示框的处理方式,True表示确认,False表示取消,None不会按按钮但依然返回文本值;send处理 prompt 提示框时输入文本;timeout等待提示框出现的超时时间,为None时使用页面整体超时时间;next_one是否处理下一个出现的弹窗,为Truetimeout参数无效。返回值为提示框内容文本或False未等到提示框。
  • set.auto_handle_alert(on_off:bool=True, accept:bool=True)
    设置自动处理提示框,使提示框不会弹窗而直接被处理掉。参数on_off表示开关设置,accept表示处理使用确定还是取消。
  • quit(timeout:float=5, force:bool=True)
    关闭浏览器,只能使用于Page对象而不能用于Tag对象。参数timeout为等待浏览器关闭超时时间(秒);force为关闭超时是否强制终止进程。

查找元素

DrissionPage使用了一套简洁的语法用于查找元素,支持内置等待、链式查找,同时也支持 css selector、xpath、selenium 原生的 loc 元组。

ele()eles()

ele() 方法和 eles() 方法类似,区别在于后者返回多个元素列表,前者可以接收一个默认值为 1 的index参数,表示返回获取的第几个匹配元素(可以为负值表示倒数)。

parent()child()children()

这三种方法为查找元素的父子元素,参数中可以接收查询语法。parent() 查询中可以接收数字,表示第几级父元素。child() 接收参数 index,表示返回第几个匹配到的元素。

next()nexts()prev()prevs()

这四种方法用于查找当前元素的前 / 后的同级节点。可以使用查询语法,单个查询也支持查找第几个同级节点。

after()afters()before()befores()

这四种方法用于查找当前元素之前之后的节点,范围不止同级节点,而是整个 DOM 文档。

匹配模式

匹配模式指某个查询中匹配条件的方式,有精确匹配、模糊匹配、匹配开头、匹配结尾四种。大部分查找语法默认使用精确匹配。

  • 精确匹配 =
    表示精确匹配,匹配完全符合的文本或属性。例如获取name属性为’row1’的元素:ele = page.ele('@name=row1')
  • 模糊匹配 :
    表示模糊匹配,匹配含有指定字符串的文本或属性。例如获取name属性包含’row1’的元素:ele = page.ele('@name:row1')
  • 匹配开头 ^
    表示匹配开头,匹配开头为指定字符串的文本或属性。例如获取name属性以’row1’开头的元素:ele = page.ele('@name^ro')
  • 匹配结尾 $
    表示匹配结尾,匹配结尾为指定字符串的文本或属性。例如获取name属性以’w1’结尾的元素:ele = page.ele('@name$w1')
查找语法

DrissionPage 支持css selector、xpath、selenium 原生的 loc 元组,这里只列举单独使用的查找语法。

  • id 匹配符 #
    表示id属性,只在语句最前面且单独使用时生效,可配合匹配模式使用。例如:在页面中查找id属性为one的元素:ele1 = page.ele('#one'),在ele1元素内查找id属性包含ne文本的元素:ele2 = ele1.ele('#:ne')
  • class 匹配符 .
    表示class属性,只在语句最前面且单独使用时生效,可配合匹配模式使用。因为默认精确匹配,所以如果某元素有多个类名,必须写 class 属性的完整值(类名的顺序也不能变);如果需要只匹配多个类名中的一个,可以使用模糊匹配符 .:。例如:查找class属性为p_cls的元素:ele2 = ele1.ele('.p_cls');精确查找class属性为p_cls1 p_cls2 的元素:ele2 = ele1.ele('.p_cls1 p_cls2 ');模糊查找class属性含有类名 ‘p_cls2’ 的元素:ele2 = ele1.ele('.:p_cls2')
  • 单属性匹配符 @
    表示匹配某个属性。例如:查找name属性为row1的元素ele2 = ele1.ele('@name=row1');查找有name属性的元素ele2 = ele1.ele('@name');查找没有任何属性的元素ele2 = ele1.ele('@');查找email属性为abc@def.com的元素,有多个@也不会重复处理ele2 = ele1.ele('@email=abc@def.com');属性中有特殊字符的情形,匹配abc@def属性等于v的元素ele2 = ele1.ele('css:div[abc\@def="v"]')
  • 多属性与匹配符 @@
    匹配同时符合多个条件的元素时使用,每个条件前面添加@@作为开头。例如:查找name属性为row1且class属性包含cls文本的元素ele2 = ele1.ele('@@name=row1@@class:cls')
  • 多属性或匹配符@|
    匹配符合多个条件中任一项的元素时使用,每个条件前面添加@|作为开头。用法与@@一致,需注意不能同 @@ 同时出现在语句中。
  • 属性否定匹配符@!
    用于否定某个条件,可与@@@|混用,也可单独使用。
  • 文本匹配符 text
    要匹配的文本,查询字符串如开头没有任何关键字,也表示根据传入的文本作模糊查找。如果元素内有多个直接的文本节点,精确查找时可匹配所有文本节点拼成的字符串,模糊查找时可匹配每个文本节点。例如:查找文本为“第二行”的元素ele2 = ele1.ele('text=第二行');查找文本包含“第二”的元素ele2 = ele1.ele('text:第二')
  • 文本匹配符 text()
    作为查找属性时使用的文本关键字,必须与@@@配合使用。
  • 类型匹配符 tag
    表示元素的标签,只在语句最前面且单独使用时生效,可与@@@@|配合使用。tag:tag=效果一致,没有tag^tag$语法。
  • css selector 匹配符 css
    表示用 css selector 方式查找元素。css:css=效果一致,没有css^css$语法。
  • xpath 匹配符 xpath
    表示用 xpath 方式查找元素。xpath:xpath=效果一致,没有xpath^xpath$语法。另外,元素对象的ele()支持完整的 xpath 语法,如能使用 xpath 直接获取元素属性(字符串类型)。
  • selenium 的 loc 元组
    查找方法能直接接收 selenium 原生定位元组进行查找,便于项目迁移。例如:page.ele((By.XPATH, '//p[@class="p_cls"]'))
处理 frame

虽然 frame 也能够使用 ele() 方法查找到,并且可以穿透 iframe 标签进行操作(页面对象支持跨级查找,元素对象并不支持),但是不建议这样使用。建议使用 Page 对象的 get_frame() 方法来获取和操作 frame元素。

例如:

  • 获取页面中第一个iframe元素: iframe = page.get_frame(1)
  • 获取页面id为theFrame的iframe元素对象: iframe = page.get_frame('#theFrame')

对于 frame 元素,可以看为一个特殊的元素对象,或页面对象来对待。可以同时操作多个 frame,无需切换。

简化写法

为进一步精简代码,定位语法都可以用简化形式来表示,使语句更短,链式操作时更清晰。

原操作简化后说明
page.ele()page()页面对象定位精简
page.ele(@id=xxx)page(#xxx)id查找精简
page.ele(@class=xxx)page(.xxx)class查找精简
page.ele(text=xxx)page(tx=xxx)text查找精简
page.ele(@text()=xxx)page(@tx()=xxx)text()查找精简
page.ele(tag:img)page(t:img)tag 查找精简
page.ele(xpath://xxxx)page(x://xxxx)xpath查找精简
page.ele(css:xxx)page(c:xxxx)css 查找精简

获取元素信息

一些常用的属性和方法能够获取常用的元素数据信息:

  • tag
    此属性返回元素的标签名
  • text
    此属性返回元素内所有文本组合成的字符串
  • attrs
    此属性以字典形式返回元素所有属性及值
  • attre()
    此方法返回元素某个 attribute 属性值
  • link
    此方法返回元素的 href 属性或 src 属性
  • page
    此属性返回元素所在的页面对象
  • style()
    该方法返回元素 css 样式属性值,可获取伪元素的属性。
  • states.is_checked
    此属性以布尔值返回表单单选或多选元素是否选中。
  • states.is_selected
    此属性以布尔值返回<select>元素中的项是否选中。
  • states.is_enabled
    此属性以布尔值返回元素是否可用。
  • states.is_displayed
    此属性以布尔值返回元素是否可见。
  • src()
    此方法用于返回元素src属性所使用的资源。base64 的可转为bytes返回,其它的以str返回。无资源的返回None

元素交互

  • click()
    用于左键点击元素。
  • click.right()
    此方法实现右键单击元素。
  • click.at()
    此方法用于带偏移量点击元素,偏移量相对于元素左上角坐标。不传入offset_x和offset_y时点击元素中间点。
  • click.to_upload()
    此方法用于点击元素,触发文件选择框并把指定的文件路径添加到网页。参数为文件上传路径
  • click.to_download()
    此方法用于点击元素触发下载,并返回下载任务对象。参数为文件保存路径
  • clear()
    清空元素文本
  • input()
    向元素输入文本或组合键,也可用于输入文件路径到上传控件。可选择输入前是否清空元素。组合键需要导入类 from DrissionPage.common import Keys,例如:ele.input((Keys.CTRL, 'a', Keys.DEL))
  • drag()
    拖拽元素到相对于当前的一个新位置
  • drag_to()
    拖拽元素到另一个元素上或一个坐标上
  • hover()
    模拟鼠标悬停在元素上,可接受偏移量,偏移量相对于元素左上角坐标
  • run_js()
    用于对元素执行 js 代码,代码中用this表示元素自己。类似于页面中的 run_js()

appium

相关文章:

自学Python第十八天-自动化测试框架(二):DrissionPage、appium

自学Python第十八天-自动化测试框架&#xff08;二&#xff09;&#xff1a;DrissionPage、appium DrissionPage环境和安装配置准备工作简单的使用示例控制浏览器收发数据包模式切换 浏览器模式创建浏览器对象访问页面加载模式none 模式技巧 获取页面信息页面交互查找元素ele()…...

云尚办公-0.3.0

5. controller层 import pers.beiluo.yunshangoffice.model.system.SysRole; import pers.beiluo.yunshangoffice.service.SysRoleService;import java.util.List;//RestController&#xff1a;1.该类是控制器&#xff1b;2.方法返回值会被写进响应报文的报文体&#xff0c;而…...

汇编英文全称

mov move mvn Mov Negative ldr LoaD Register str Store Register lsl Logic Shift Left lsr Logic Shift Right asr Arithmetic Shift Right 算数右移 ror Rotate right 循环右移…...

基于虚拟力优化的无线传感器网络覆盖率matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 虚拟力优化算法 4.2 覆盖覆盖率计算 5.完整程序 1.程序功能描述 基于虚拟力优化的无线传感器网络覆盖率&#xff0c;仿真输出优化前后的网络覆盖率&#xff0c;覆盖率优化收敛迭代曲线…...

阿里云-系统盘-磁盘扩容

阿里云系统磁盘扩容 之前是测试环境磁盘用的默认的有 40G&#xff0c;后面升级到正式的 磁盘怕不够用打算升级到 100G&#xff0c; 系统镜像&#xff1a; Alibaba Cloud Linux 3.2104 LTS 64 位 磁盘 ESSD 40G 升级步骤&#xff1a; 扩容与创建快照 在阿里云后台首先去扩容…...

libmmd.dll修复

libmmd.dll 是与Intel Math Kernel Library (MKL) 相关的动态链接库文件&#xff0c;通常用于数学和科学计算。 最常出现的错误信息是&#xff1a; 程序无法启动&#xff0c;因为您的计算机缺少 libmmd.dll 。尝试重新安装程序来解决这个问题。 启动 libmmd.dll 发生错误。无法…...

大数据时代的明星助手:数据可视化引领新风潮

在大数据时代的浪潮中&#xff0c;数据可视化如一位巧夺天工的画师&#xff0c;为我们描绘出庞大而丰富的信息画卷&#xff0c;为我们提供了直观、清晰、高效的数据呈现方式。下面我就以可视化从业者的角度&#xff0c;来简单聊聊这个话题。 数据可视化首先在信息管理和理解方面…...

设计模式--享元模式和组合模式

享元模式 享元模式&#xff08;Flyweight Pattern&#xff09;又称为轻量模式&#xff0c;是对象池的一种实现。类似于线程池&#xff0c;线程池可以避免不停的创建和销毁多个对象&#xff0c;销毁性能。提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒…...

基于Java springmvc+mybatis酒店信息管理系统设计和实现

基于Java springmvcmybatis酒店信息管理系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获…...

leetcode-找不同

389. 找不同 题解&#xff1a; 从题意我们可以知道&#xff0c;虽然 t 是由 s组成&#xff0c;但是 t中又随机添加了一个字符&#xff0c;也就是相当于 t 包含 s,我们使用字典&#xff0c;将 t 转换成字典对应关系t_map&#xff0c;然后遍历 s 中的字符&#xff0c;若存在&am…...

笔记本hp6930p安装Android-x86避坑日记

一、序言 农历癸卯年前大扫除&#xff0c;翻出老机hp6930p&#xff0c;闲来无事&#xff0c;便安装Android-x86玩玩&#xff0c;期间多次入坑&#xff0c;随手记之以避坑。 笔记本配置&#xff1a;T9600,4G内存&#xff0c;120G固态160G机械硬盘 二、Android-x86系统简介 官…...

zabbix监控业务数据

前言 监控系统除了监控os和数据库性能相关的指标外&#xff0c;业务数据也是重点监控的对象。 一线驻场的运维同学应该深有体会&#xff0c;每天需要向甲方或者公司反馈现场的数据情况&#xff0c;正常情况下一天巡检两次&#xff0c;早上上班后和下午下班前各一次。监控项目…...

access数据库泄露与IIS短文件名利用

access数据库 Microsoft Office Access是微软把 数据库引擎 的图形用户界面和 软件开发工具 结合在一起的一个 数据库管理系统 它的数据库是没有库名的&#xff0c;都是表名。 (借用别的up的图)是不是感觉有点像excel access数据库的后缀是.mdb access数据库泄露漏洞 如果…...

MySQL 篇-深入了解 DDL 语言(一)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 MySQL 说明 2.0 DDL 语言 2.1 DDL 语言 - 定义数据库 2.1.1 创建数据库操作 2.1.2 查看数据库操作 2.1.3 使用数据库操作 2.1.4 删除数据库操作 2.2 DDL 语言 …...

MT8788|MTK8788安卓核心板参数_4G联发科MTK模块

MT8788核心板是一款功能强大的4G全网通安卓智能模块。该模块采用了联发科AIOT芯片平台&#xff0c;具有长达8年的生命周期。MT8788模块内置了12nm制程的八核处理器&#xff0c;包括4个Cortex A73和4个Coretex A53&#xff0c;主频最高可达2.0GHZ。标配内存为4GB64GB&#xff0c…...

EXCEL 在列不同单元格之间插入N个空行

1、第一步数据&#xff0c;要求在每个数字之间之间插入3个空格 2、拿数据个数*&#xff08;要插入空格数1&#xff09; 19*4 3、填充 4、复制数据到D列 5、下拉数据&#xff0c;选择复制填充这样1-19就会重复4次 6、全选数据D列排序&#xff0c;这样即完成了插入空格 以…...

Linux快速修改ip地址

Linux修改IP配置 一 、查找ip配置文件 ifcfg-ens33二、编辑 vi ifcfg-ens33文件三、重启网络或者重启系统 一 、查找ip配置文件 ifcfg-ens33 cd /etc/sysconfig/network-scripts/ls //查看network-scripts文件夹下面的文件二、编辑 vi ifcfg-ens33文件 vi ifcfg-ens33注意&…...

采用遗传算法搜索MAC效率最高的矩阵乘规模

如何采用遗传算法搜索MAC效率最高的矩阵乘规模 具体实现MAC效率评估代码(eval.py)遗传算法实现 本文介绍了采用遗传算法搜索MAC效率最高的矩阵乘规模 需求背景: 一些AI加速卡在做矩阵乘时,因硬件或软件的约束,并不是规模越大MAC效率越高在测试AI加卡的实际算力时,采用MAC效率最…...

流计算之Flink

文章目录 概要有界无界流集群JobManagerTaskManagersTasks 和算子链Task Slots 和资源 小结 概要 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模…...

【Linux基础】Linux自动化构建工具make/makefile

背景 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile定义了一系列的规则来指定&#xff0c;哪些文件需要先编译&#xff0c;哪些文件需要后…...

问题慢慢解决-通过android emulator调试android kernel-内核条件断点遇到的问题和临时解决方案

起因 在摸索到这个方案之后&#xff0c;mac m1调试aarch64 android kernel最终方案&#xff0c;就准备调试内核了&#xff0c;预备下断点的地方是 b binder_poll b ep_ptable_queue_proc b remove_wait_queue但是由于是android系统&#xff0c;上面三个函数会被频繁的触发&am…...

社区发现之标签传播算法(LPA)

在Graph领域,社区发现(Community detection)是一个非常热门且广泛的话题,后面会写一个系列,该问题实际上是从子图分割的问题演变而来,在真实的社交网络中,有些用户之间连接非常紧密,有些用户之间的连接较为稀疏,连接紧密的用户群体可以看做一个社区,在风控问题中,可…...

【前端素材】推荐优质后台管理系统Dashy平台模板(附源码)

一、需求分析 后台管理系统&#xff08;或称作管理后台、管理系统、后台管理平台&#xff09;是一种专门用于管理网站、应用程序或系统后台运营的软件系统。它通常由一系列功能模块组成&#xff0c;为管理员提供了管理、监控和控制网站或应用程序的各个方面的工具和界面。以下…...

MFC 配置Halcon

1.新建一个MFC 工程&#xff0c;Halcon 为64位&#xff0c;所以先将工程改为x64 > VC 目录设置包含目录和库目录 包含目录 库目录 c/c ->常规 链接器 ->常规 > 链接器输入 在窗口中添加头文件 #include "HalconCpp.h" #include "Halcon.h"…...

xss-跨站脚本攻击漏洞

前备知识&#xff1a; Cookie和Session是Web开发中用于维持用户状态、跟踪用户会话的核心技术&#xff0c;它们的主要目的是在无状态的HTTP协议基础上实现有状态的用户交互。 **Cookie**&#xff1a; - Cookie是一种由服务器发送到客户端&#xff08;通常是用户的浏览器&#x…...

在MFC对话框中嵌入web网页时事件失效问题

2010-04-20 日志 在MFC对话框中嵌入web网页时&#xff0c;网页初始化中添加事件无效 document.body.onkeydown function () {//onkeydown"keydownbody()" 不能激发alert(event.keyCode);if(event.keyCode 27)//VK_ESCAPE //String.fromcharcode(A);{if (external…...

【Leetcode】235. 二叉搜索树的最近公共祖先

文章目录 题目思路代码结果 题目 题目链接 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度…...

python 基础语法及保留字

编码 默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码&#xff1a; # -*- coding: cp-1252 -*-上述定义允许在源文件中使用 Windows-1252 字符集中的字符编码&#xff0c;对应适合语…...

Parade Series - NVR Stat

获取文件夹占用空间信息 DIR %NVRHOME% /W /SDIR %NVRHOME% /s | tail -n2 | sed s/,//g | awk {if(NR1){key"Used";}else{key"Free";};sum$3/(1024*1024);unit"MB";if(sum^>1024){sumsum/1024;unit"GB";}printf("{\"Ty…...

【shell脚本实战学习笔记】#2

场景描述 你负责一个Web应用的运维工作&#xff0c;该应用部署在一组Linux服务器上。你需要编写一个Shell脚本来自动化以下任务&#xff1a; 检查Web服务器进程&#xff1a; 确保Web服务器&#xff08;例如Apache或Nginx&#xff09;正常运行。如果没有运行&#xff0c;则尝试…...

docker 安装nacos 一脚shell脚本

要创建一个用于安装Nacos的Docker的Shell脚本&#xff0c;你可以按照以下步骤进行。这个脚本会执行以下操作&#xff1a; 拉取Nacos的Docker镜像。创建一个Docker容器并映射必要的端口。设置Nacos的环境变量。如果需要&#xff0c;可以持久化存储数据到本地目录。 以下是一个…...

mysql的隔离级别,和实现

参考链接 https://xiaolincoding.com/mysql/transaction/mvcc.html#%E4%BA%8B%E5%8A%A1%E7%9A%84%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E6%9C%89%E5%93%AA%E4%BA%9B 事务特性&#xff08;ACID&#xff09; 原子性&#xff08;Atomicity&#xff09;&#xff1a; 事务是原子的&…...

Linux的信号

Linux的信号是一种用于进程之间通信的机制。它们用于向进程发送通知&#xff0c;告知进程发生了某种事件或请求进程执行某个操作。信号可以由内核、其他进程或进程自身发送。 信号的作用有以下几个方面&#xff1a; 通知进程某个事件的发生&#xff0c;如进程的终止、挂起、恢…...

Spring数据脱敏实现

在当今的数字化时代&#xff0c;数据安全和个人隐私保护变得日益重要。为了遵守各种数据保护法规&#xff0c;如欧盟的GDPR&#xff08;通用数据保护条例&#xff09;&#xff0c;企业在处理敏感信息时需要格外小心。数据脱敏是一种常见的技术手段&#xff0c;用于隐藏敏感数据…...

Java核心-核心类与API(4)

话接上回&#xff0c;继续核心类与API的学习&#xff0c;最后介绍一下Object类以及与数学、日期/时间有关的类&#xff0c;就结束该部分的学习了&#xff0c;其他的根据需要自行了解。 一、Object类 1、概述 Object 是 Java 类库中的一个特殊类&#xff0c;也是所有类的父类…...

【C语言】详解计算机二级c语言程序题

文章目录 前言资料相关程序题 一&#xff08;字符串&#xff09;程序题 二&#xff08;数组&#xff09;程序题 三&#xff08;基础&#xff09;程序题 四&#xff08;结构体&#xff09;程序题 五&#xff08;结构体&#xff09;程序题 六&#xff08;基础&#xff09; 前言 …...

限流算法

下面对常见的限流算法进行讨论。目前&#xff0c;常用的限流算法主要有三种&#xff1a;计数器法、滑动窗口算法、漏桶算法和令牌桶算法。下面分别介绍其原理。 1. 计数器法 计数器法是通过计数对到来的请求进行选择性处理。如系统限制一秒内最多有X个请求&#xff0c;则在该…...

备战蓝桥杯 Day10(背包dp)

01背包问题 1267&#xff1a;【例9.11】01背包问题 【题目描述】 一个旅行者有一个最多能装 M&#xfffd; 公斤的背包&#xff0c;现在有 n&#xfffd; 件物品&#xff0c;它们的重量分别是W1&#xff0c;W2&#xff0c;...,Wn&#xfffd;1&#xff0c;&#xfffd;2&#…...

Sora 使用教程,新手小白可用

Sora 使用教程&#xff0c;新手小白可用 参考文章&#xff1a;Sora 使用教程&#xff0c;OpenAI 的文生视频模型 为了在激烈的行业竞争中保持领先地位&#xff0c;OpenAI 在 2024 年 2 月 15 日发布了其革命性的文本至视频转换模型——Sora。这个先进的工具能够将文本描述转化…...

【洛谷千题详解】P1031 均分纸牌

目录 题目描述 思路点拨 AC代码 题目描述 题目网址&#xff1a;[NOIP2002 提高组] 均分纸牌 - 洛谷 有 N 堆纸牌&#xff0c;编号分别为 1,2,……,N。每堆上有若干张&#xff0c;但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌&#xff0c;然后移动。 移牌规则为&a…...

基于文本提示和语义分割的快速抠图

基于文本提示和语义分割的快速抠图 1. 介绍2. 效果展示3. 安装模型4. 命令行调用5. 代码调用5.1 模型加载5.2 可视化函数定义5.3 图像语义分割 6. 参考资料7. 结语服务 1. 介绍 传统的图像语义分割模型通常固定类别进行分割&#xff0c;而基于文本提示的语义分割模型则具有更高…...

什么是媒体发稿?发稿媒体分类及发稿流程

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体发稿是一种企业推广和宣传的手段&#xff0c;通过媒体渠道传递企业信息和形象。 媒体发稿的含义在于&#xff0c;当企业有新闻、事件或其他消息需要对外公布时&#xff0c;可以选择…...

安全测试自学手册之软件安全测试基础

安全测试的概念 定义&#xff1a;指有关验证应用程序的安全等级和识别潜在安全性缺陷的过程。】 应用软件的安全性测试&#xff1a;软件自身设计中存在的安全隐患&#xff0c;并检查软件对非法入侵的防御能力。系统级别的安全性测试&#xff1a;确保只有具备系统平台访问权限…...

【LeetCode】升级打怪之路 Day 04:链表 part 2

今日题目&#xff1a; 24. 两两交换链表中的节点19. 删除链表的倒数第 N 个结点160. 相交链表142. 环形链表 II 目录 LeetCode 24. 两两交换链表中的节点 【易错】LeetCode 19. 删除链表的倒数第 N 个结点 【还行】LeetCode 160. 相交链表&#xff08;两个链表是否相交&#xf…...

JAVA编程题系列——涵盖几乎所有java内容

自己定义一个类&#xff0c;有static属性和构造方法&#xff0c;有构造方法重载&#xff0c;有其他方法&#xff08;方法有对String类型操作&#xff09; public class MyClass {// 静态属性public static String staticProperty "Static Property";// 成员变量priv…...

【Android12】Monkey压力测试源码执行流程分析

Monkey压力测试源码执行流程分析 Monkey是Android提供的用于应用程序自动化测试、压力测试的测试工具。 其源码路径(Android12)位于 /development/cmds/monkey/部署形式为Java Binary # development/cmds/monkey/Android.bp // Copyright 2008 The Android Open Source Proj…...

Java架构师之路八、安全技术:Web安全、网络安全、系统安全、数据安全等

目录 Web安全&#xff1a; 网络安全&#xff1a; 系统安全&#xff1a; 数据安全&#xff1a; Java架构师之路七、大数据&#xff1a;Hadoop、Spark、Hive、HBase、Kafka等-CSDN博客Java架构师之路九、设计模式&#xff1a;常见的设计模式&#xff0c;如单例模式、工厂模式…...

Codeforces Round 240 (Div. 1) C. Mashmokh and Reverse Operation(分治+逆序对)

原题链接&#xff1a;C. Mashmokh and Reverse Operation 题目大意&#xff1a; 给出一个长度为 2 n 2^{n} 2n 的正整数数组 a a a &#xff0c;再给出 m m m 次操作。 每次操作给出一个数字 q q q &#xff0c;把数组分为 2 n − q 2^{n-q} 2n−q 个长度为 2 q 2^{q} 2…...

SpringBoot源码解读与原理分析(三十二)SpringBoot整合JDBC(一)JDBC组件的自动装配

文章目录 前言第10章 SpringBoot整合JDBC10.1 SpringBoot整合JDBC的项目搭建10.1.1 初始化数据库10.1.2 整合项目10.1.2.1 导入JDBC和MySQL驱动依赖10.1.2.2 配置数据源 10.1.3 编写业务代码10.1.3.1 编写与t_user表对应的实体类User10.1.3.2 编写Dao层代码10.1.3.3 编写Servic…...

petalinux_zynq7 驱动DAC以及ADC模块之五:nodejs+vue3实现web网页波形显示

前文&#xff1a; petalinux_zynq7 C语言驱动DAC以及ADC模块之一&#xff1a;建立IPhttps://blog.csdn.net/qq_27158179/article/details/136234296petalinux_zynq7 C语言驱动DAC以及ADC模块之二&#xff1a;petalinuxhttps://blog.csdn.net/qq_27158179/article/details/1362…...