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

通过元素定位其各种层级关系元素的工具

# element_relation_locator.py
# 通过元素定位其各种层级关系元素的工具from appium.webdriver.common.appiumby import AppiumByclass ElementRelationLocator:"""元素关系定位器类,用于通过元素定位其各种层级关系的元素"""def __init__(self, driver):"""初始化元素关系定位器Args:driver: Appium WebDriver实例"""self.driver = driverdef get_element(self, locator_type, locator_value):"""根据定位器获取目标元素Args:locator_type: 定位器类型,如AppiumBy.ID, AppiumBy.XPATH等locator_value: 定位器值Returns:WebElement: 找到的元素"""return self.driver.find_element(locator_type, locator_value)def get_parent_element(self, element):"""获取元素的父元素Args:element: 当前元素Returns:WebElement: 父元素"""# 获取当前元素的ID或XPathelement_id = element.get_attribute('resource-id')element_class = element.get_attribute('class')element_text = element.get_attribute('text')# 构建XPath来查找父元素if element_id:xpath = f"//*[@resource-id='{element_id}']/.."elif element_text:xpath = f"//*[@text='{element_text}']/.."else:xpath = f"//{element_class}/.."return self.driver.find_element(AppiumBy.XPATH, xpath)def get_grandparent_element(self, element):"""获取元素的祖父元素(父元素的父元素)Args:element: 当前元素Returns:WebElement: 祖父元素"""# 获取当前元素的ID或XPathelement_id = element.get_attribute('resource-id')element_class = element.get_attribute('class')element_text = element.get_attribute('text')# 构建XPath来查找祖父元素if element_id:xpath = f"//*[@resource-id='{element_id}']/../.."elif element_text:xpath = f"//*[@text='{element_text}']/../.."else:xpath = f"//{element_class}/../.."return self.driver.find_element(AppiumBy.XPATH, xpath)def get_sibling_elements(self, element):"""获取元素的所有同级元素(包括自身)Args:element: 当前元素Returns:list: 同级元素列表"""parent = self.get_parent_element(element)# 获取父元素的所有直接子元素children = parent.find_elements(AppiumBy.XPATH, './*')return childrendef get_following_sibling_elements(self, element):"""获取元素之后的同级元素(不包括自身)Args:element: 当前元素Returns:list: 后续同级元素列表"""# 获取当前元素的ID或XPathelement_id = element.get_attribute('resource-id')element_class = element.get_attribute('class')element_text = element.get_attribute('text')# 构建XPath来查找后续同级元素if element_id:xpath = f"//*[@resource-id='{element_id}']/following-sibling::*"elif element_text:xpath = f"//*[@text='{element_text}']/following-sibling::*"else:xpath = f"//{element_class}[1]/following-sibling::*"  # 假设是第一个匹配的元素return self.driver.find_elements(AppiumBy.XPATH, xpath)def get_preceding_sibling_elements(self, element):"""获取元素之前的同级元素(不包括自身)Args:element: 当前元素Returns:list: 之前同级元素列表"""# 获取当前元素的ID或XPathelement_id = element.get_attribute('resource-id')element_class = element.get_attribute('class')element_text = element.get_attribute('text')# 构建XPath来查找之前同级元素if element_id:xpath = f"//*[@resource-id='{element_id}']/preceding-sibling::*"elif element_text:xpath = f"//*[@text='{element_text}']/preceding-sibling::*"else:xpath = f"//{element_class}[1]/preceding-sibling::*"  # 假设是第一个匹配的元素return self.driver.find_elements(AppiumBy.XPATH, xpath)def get_child_elements(self, element):"""获取元素的所有直接子元素Args:element: 当前元素Returns:list: 子元素列表"""return element.find_elements(AppiumBy.XPATH, './*')def get_grandchild_elements(self, element):"""获取元素的所有孙子元素(子元素的子元素)Args:element: 当前元素Returns:list: 孙子元素列表"""return element.find_elements(AppiumBy.XPATH, './*/*')def get_all_descendants(self, element, max_depth=None):"""获取元素的所有后代元素(递归获取所有层级的子元素)Args:element: 当前元素max_depth: 最大递归深度,如果为None则无限递归Returns:list: 所有后代元素列表"""descendants = []def _collect_descendants(current_element, current_depth):# 如果达到最大深度,停止递归if max_depth is not None and current_depth > max_depth:returnchildren = self.get_child_elements(current_element)for child in children:descendants.append(child)_collect_descendants(child, current_depth + 1)_collect_descendants(element, 1)return descendantsdef print_element_info(self, element, prefix=""):"""打印元素信息Args:element: 要打印信息的元素prefix: 前缀字符串,用于缩进显示"""element_id = element.get_attribute('resource-id') or "无"element_class = element.get_attribute('class') or "无"element_text = element.get_attribute('text') or "无"element_desc = element.get_attribute('content-desc') or "无"element_bounds = element.get_attribute('bounds') or "无"print(f"{prefix}元素信息:")print(f"{prefix}  ID: {element_id}")print(f"{prefix}  Class: {element_class}")print(f"{prefix}  Text: {element_text}")print(f"{prefix}  Content-Desc: {element_desc}")print(f"{prefix}  Bounds: {element_bounds}")print(f"{prefix}")def traverse_element_tree(self, start_element, max_depth=None):"""遍历元素树,打印所有层级的元素信息Args:start_element: 开始遍历的元素max_depth: 最大遍历深度,如果为None则无限递归"""def _traverse(element, current_depth, max_depth):# 打印当前元素信息prefix = "  " * current_depthself.print_element_info(element, prefix)# 如果达到最大深度,停止递归if max_depth is not None and current_depth >= max_depth:return# 递归遍历子元素children = self.get_child_elements(element)for child in children:_traverse(child, current_depth + 1, max_depth)print("\n开始遍历元素树:")_traverse(start_element, 0, max_depth)print("元素树遍历完成\n")def find_element_in_hierarchy(self, start_element, target_id=None, target_text=None, target_class=None):"""在元素层级中查找特定元素Args:start_element: 开始查找的元素target_id: 目标元素的resource-idtarget_text: 目标元素的texttarget_class: 目标元素的classReturns:WebElement or None: 找到的元素,如果没找到返回None"""# 先检查当前元素是否匹配if self._element_matches(start_element, target_id, target_text, target_class):return start_element# 递归检查子元素children = self.get_child_elements(start_element)for child in children:result = self.find_element_in_hierarchy(child, target_id, target_text, target_class)if result:return resultreturn Nonedef _element_matches(self, element, target_id=None, target_text=None, target_class=None):"""检查元素是否匹配给定的条件Args:element: 要检查的元素target_id: 目标resource-idtarget_text: 目标texttarget_class: 目标classReturns:bool: 如果元素匹配条件返回True,否则返回False"""if target_id and element.get_attribute('resource-id') != target_id:return Falseif target_text and element.get_attribute('text') != target_text:return Falseif target_class and element.get_attribute('class') != target_class:return Falsereturn True# 使用示例
"""
# 假设driver已经初始化
# driver = webdriver.Remote(...)  
# 
# # 创建ElementRelationLocator实例
# locator = ElementRelationLocator(driver)
# 
# # 定位一个起始元素
# target_element = locator.get_element(AppiumBy.ID, "com.example.app:id/target_element")
# 
# # 打印元素信息
# locator.print_element_info(target_element)
# 
# # 获取并打印父元素信息
# parent = locator.get_parent_element(target_element)
# print("父元素信息:")
# locator.print_element_info(parent)
# 
# # 获取并打印祖父元素信息
# grandparent = locator.get_grandparent_element(target_element)
# print("祖父元素信息:")
# locator.print_element_info(grandparent)
# 
# # 获取并打印同级元素
# siblings = locator.get_sibling_elements(target_element)
# print(f"找到{len(siblings)}个同级元素:")
# for i, sibling in enumerate(siblings):
#     print(f"\n同级元素 #{i+1}:")
#     locator.print_element_info(sibling)
# 
# # 获取并打印后续同级元素
# following_siblings = locator.get_following_sibling_elements(target_element)
# print(f"找到{len(following_siblings)}个后续同级元素:")
# for i, sibling in enumerate(following_siblings):
#     print(f"\n后续同级元素 #{i+1}:")
#     locator.print_element_info(sibling)
# 
# # 获取并打印子元素
# children = locator.get_child_elements(parent)
# print(f"找到{len(children)}个子元素:")
# for i, child in enumerate(children):
#     print(f"\n子元素 #{i+1}:")
#     locator.print_element_info(child)
# 
# # 遍历元素树(限制最大深度为2)
# locator.traverse_element_tree(parent, max_depth=2)
# 
# # 在元素层级中查找特定元素
# found_element = locator.find_element_in_hierarchy(parent, target_text="确定")
# if found_element:
#     print("找到目标元素:")
#     locator.print_element_info(found_element)
# else:
#     print("未找到目标元素")
"""# 注意事项:
# 1. 当元素没有唯一标识符时,定位可能会不准确,特别是在多个相同class的元素情况下
# 2. 遍历大型元素树可能会比较耗时,建议使用max_depth参数限制遍历深度
# 3. XPath定位在某些情况下可能不如原生定位方式高效,可以根据具体场景选择合适的方法
# 4. 在Android系统中,有些元素属性可能不可用或为空,代码中已经做了相应的处理
# 5. 实际使用时,建议根据Appium服务器和设备性能调整超时时间和重试逻辑
http://www.gsyq.cn/news/48853.html

相关文章:

  • 2025年11月五金打包机,称重打包机,半自动打包机厂家品牌推荐榜,彰显包装设备技术实力!
  • 力扣 第 475 场周赛(A~C)
  • 搜维尔科技:具身人工智能中的 MANUS:从人类运动到机器人灵巧性
  • 实用指南:百分点科技发布中国首个AI原生GEO产品Generforce,助力品牌决胜AI搜索新时代
  • 考前复习
  • 第三章博文
  • Spring BeanPostProcessor接口
  • NOI2025 游记
  • 网络攻防实战 lab06 靶机 VulnHub hard-socnet2
  • 2025 年 11 月电力金具厂家最新推荐,精准检测与稳定性能深度解析!
  • v4l2用户侧使用流程
  • 题解:P3791 普通数学题
  • 芒格变富的逻辑
  • Numerical results of ar-HTMDFP in AMS 2025
  • 再加个数学专题
  • OpenCVSharp:ArUco 标记检测与透视变换
  • 2024年春招-美团-技术岗-第一批笔试
  • 2025.11.13
  • 一句话奶牛
  • 2025氮化硼陶瓷/高温绝缘体/坩埚/套管/基板/高温构件/中子吸收材料优质厂家推荐榜:福维科五星领跑,多场景制品赋能工业升级
  • 2025健康营养饮品推荐榜:惠植健活力菌仓领衔,5 家品牌凭技术与品质,重塑火麻仁肽爆爆纤维/火麻仁肽/固体饮料与燕麦/西梅/果蔬营养素饮品新生态
  • 详细介绍:Wireshark:HTTP、MQTT、WebSocket 抓包详细教程
  • ai agent 智能体 prompt ragflow langflow n8n dify
  • C++之变量与基本类型(三) - Invinc
  • 深入解析:手写MyBatis第111弹:Spring Boot自定义注解@MybatisMapperScan注解深度解析:从注解定义到接口代理的完整实现
  • 点赞!开幕式背后的云力量!
  • 11.13 比赛总结
  • win7 如何运行cherry studio
  • 《密码系统设计》第十一周预习
  • 松原西林瓶灌装加塞机推荐,适配冻干机半加塞功能