uiautomator2 set_text()方法失效

在微信发送信息输入框输入信息时,使用d(resourceId=\com.tencent.mm:id/o4q\).set_text(\xxxx\)方法失效,后采用强制xpath定位,即d.xpath('//*[@resource-id=\com.tencent.mm:id/o4q\]').set_text(\xxxx\)成功解决问题。

给微信发送信息输入框中输入信息,使用d(resourceId="com.tencent.mm:id/o4q").set_text("xxxx")失效,然后强制使用xpah定位,d.xpath('//*[@resource-id="com.tencent.mm:id/o4q"]').set_text("xxxx")成功。

from appium import webdriver from appium.options.android import UiAutomator2Options from selenium.common.exceptions import ElementClickInterceptedException, StaleElementReferenceException from appium.webdriver.common.appiumby import AppiumBy from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time import hashlib # ==================== 配置 Appium Options ==================== options = UiAutomator2Options() options.set_capability("platformName", "Android") options.set_capability("deviceName", "emulator-5554") options.set_capability("automationName", "UiAutomator2") options.set_capability("noReset", False) options.set_capability("fullReset", False) options.set_capability("autoGrantPermissions", True) options.set_capability("newCommandTimeout", 600) # 指定你要测试的应用 options.set_capability("appPackage", "com.brother.iPrintAndLabel") options.set_capability("appActivity", "com.brother.iPrintAndLabel.MainActivity") driver = webdriver.Remote(command_executor='http://localhost:4723', options=options) # 存储已处理元素和页面状态 processed_elements = set() visited_page_hashes = set() # ================== 工具类:MobileElementActions ================== class MobileElementActions: def __init__(self, driver): self.driver = driver self.processed_inputs = set() def get_element_signature(self, element): """生成唯一标识符,使用 Appium 支持的属性名称""" try: attrs = [ element.get_attribute("resourceId") or "", element.get_attribute("text") or "", element.get_attribute("contentDescription") or "", element.get_attribute("className") or "" ] raw_sig = "||".join(attrs) return hashlib.md5(raw_sig.encode()).hexdigest()[:16] except Exception as e: print(f"⚠️ 获取元素签名失败: {e}") return None def is_interactable(self, element): """判断是否为可交互元素""" try: clickable = element.get_attribute("clickable") == "true" enabled = element.get_attribute("enabled") == "true" focusable = element.get_attribute("focusable") == "true" scrollable = element.get_attribute("scrollable") == "true" return (clickable or focusable) and enabled and not scrollable except Exception as e: print(f"⚠️ 判断可交互性失败: {e}") return False def safe_click(self, element): """安全点击,支持 fallback 到坐标点击""" try: element.click() return True except ElementClickInterceptedException: print("⚠️ 元素被遮挡,尝试通过坐标点击") try: loc = element.location size = element.size x = loc['x'] + size['width'] // 2 y = loc['y'] + size['height'] // 2 self.driver.tap([(x, y)]) return True except Exception as tap_e: print(f"❌ 坐标点击也失败: {tap_e}") return False except Exception as e: print(f"❌ 点击失败: {e}") return False def wait_for_page_load(self, timeout=2): """等待页面加载完成""" time.sleep(timeout) def handle_alerts(self): """自动处理常见弹窗按钮""" alert_texts = ['OK', '确定', 'Cancel', '取消'] for text in alert_texts: try: btn = self.driver.find_element(AppiumBy.XPATH, f"//*[@text='{text}' or @contentDescription='{text}']") if btn.is_displayed() and btn.is_enabled(): btn.click() print(f"✅ 自动关闭弹窗: {text}") return True except: continue return False def handle_input_fields(self): """填写输入框""" try: inputs = self.driver.find_elements( AppiumBy.XPATH, "//android.widget.EditText | //android.widget.TextView[@focusable='true']" ) for inp in inputs: try: if not inp.is_displayed() or not inp.is_enabled(): continue sig = self.get_element_signature(inp) if not sig or sig in self.processed_inputs: continue print(f"📝 发现输入框: {inp.get_attribute('text') or 'No Text'}") inp.clear() inp.send_keys("AutoInputTest") self.processed_inputs.add(sig) except Exception as e: print(f"⚠️ 输入失败: {e}") except Exception as e: print(f"🔍 查找输入框异常: {e}") def get_current_page_hash(self): """获取当前页面结构哈希值,用于检测变化""" try: src = self.driver.page_source return hashlib.md5(src.encode('utf-8')).hexdigest() except Exception as e: print(f"⚠️ 获取页面源码失败: {e}") return None # ================== 主流程:自动化遍历 ================== class MobileAutomationWorkflow: def __init__(self, driver): self.driver = driver self.actions = MobileElementActions(driver) self.max_iterations = 300 self.iteration_count = 0 def run(self): print("📱 开始移动应用自动化遍历...") try: while self.iteration_count < self.max_iterations: print(f"\n🔄 第 {self.iteration_count + 1} 轮:扫描当前页面") # 记录当前页面状态 current_page_hash = self.actions.get_current_page_hash() if current_page_hash in visited_page_hashes: print("🔁 当前页面已访问过,尝试返回") try: self.driver.back() time.sleep(1.5) continue except: break else: visited_page_hashes.add(current_page_hash) # 获取所有元素 try: elements = self.driver.find_elements(AppiumBy.XPATH, "//*") except Exception as e: print(f"❌ 获取元素列表失败: {e}") break print(f"找到 {len(elements)} 个元素") found_new_clickable = False for elem in elements: try: if not self.actions.is_interactable(elem): continue sig = self.actions.get_element_signature(elem) if not sig or sig in processed_elements: continue text = elem.get_attribute("text") or "No Text" clazz = elem.get_attribute("className").split(".")[-1] print(f"👉 尝试点击: [{clazz}] '{text}'") print("Current Activity:", driver.current_activity) if self.actions.safe_click(elem): processed_elements.add(sig) found_new_clickable = True self.actions.wait_for_page_load() # 处理可能出现的弹窗 self.actions.handle_alerts() # 处理输入框 self.actions.handle_input_fields() # 成功点击后跳出循环,重新获取新页面 break except StaleElementReferenceException: print("⚠️ 元素已失效,跳过") continue except Exception as inner_e: # 这里不再因单个元素报错而崩溃 print(f"⚠️ 处理元素时发生非致命错误: {inner_e}") continue if not found_new_clickable: print("✅ 当前页面无可点击的新元素") try: self.driver.back() time.sleep(1.5) back_hash = self.actions.get_current_page_hash() if back_hash in visited_page_hashes: print("🔚 回退后仍无法前进,结束遍历") break except Exception as back_e: print(f"🔙 返回失败或已达根页面: {back_e}") break self.iteration_count += 1 print(f"🏁 自动化完成,共执行 {self.iteration_count} 次操作。") except Exception as e: print(f"🚨 自动化过程发生严重错误: {e}") finally: self.driver.quit() # ================== 启动入口 ================== if __name__ == "__main__": workflow = MobileAutomationWorkflow(driver) workflow.run() 日志 C:\own\app\python_code\.venv\Scripts\python.exe C:\own\app\python_code\work\IBL_click_all\click_all.py Traceback (most recent call last): File "C:\own\app\python_code\work\IBL_click_all\click_all.py", line 23, in <module> driver = webdriver.Remote(command_executor='http://localhost:4723', options=options) File "C:\own\app\python_code\.venv\Lib\site-packages\appium\webdriver\webdriver.py", line 249, in __init__ super().__init__( ~~~~~~~~~~~~~~~~^ command_executor=command_executor, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<3 lines>... client_config=client_config, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "C:\own\app\python_code\.venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 261, in __init__ self.start_session(capabilities) ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^ File "C:\own\app\python_code\.venv\Lib\site-packages\appium\webdriver\webdriver.py", line 342, in start_session response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps) File "C:\own\app\python_code\.venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 454, in execute self.error_handler.check_response(response) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^ File "C:\own\app\python_code\.venv\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 232, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.WebDriverException: Message: Either provide 'app' option to install 'com.brother.iPrintAndLabel' or consider setting 'noReset' to 'true' if 'com.brother.iPrintAndLabel' is supposed to be preinstalled. Stacktrace: UnknownError: Either provide 'app' option to install 'com.brother.iPrintAndLabel' or consider setting 'noReset' to 'true' if 'com.brother.iPrintAndLabel' is supposed to be preinstalled. at getResponseForW3CError (C:\own\app\Node\node_global\node_modules\appium\node_modules\@appium\base-driver\lib\protocol\errors.ts:1103:34) at asyncHandler (C:\own\app\Node\node_global\node_modules\appium\node_modules\@appium\base-driver\lib\protocol\protocol.ts:507:57) The above error is caused by Error: Either provide 'app' option to install 'com.brother.iPrintAndLabel' or consider setting 'noReset' to 'true' if 'com.brother.iPrintAndLabel' is supposed to be preinstalled. at AndroidUiautomator2Driver.resetAUT (C:\Users\qusg\.appium\node_modules\appium-uiautomator2-driver\node_modules\appium-android-driver\lib\commands\app-management.js:410:11) at AndroidUiautomator2Driver.initAUT (C:\Users\qusg\.appium\node_modules\appium-uiautomator2-driver\lib\driver.ts:794:9) Process finished with exit code 1
最新发布
10-16
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值