import uiautomator2 as u2
import time
import sys
from typing import Optional
class PostalAutomation:
def init(self):
self.d = u2.connect()
self.config = {
'base_delay': 0.02,
'critical_delay': 0.15,
'max_retry': 3,
'id_card_number': '130130199001071868',
'timeout': 2.0
}
self.setup_device()
def setup_device(self):
"""初始化设备设置"""
self.d.implicitly_wait(self.config['timeout'])
self.d.settings['operation_delay'] = (0, 0.5)
def safe_click(self, selector, retry: int = 3) -> bool:
"""安全的点击操作,带重试机制"""
for attempt in range(retry):
try:
if selector.exists:
selector.click()
time.sleep(self.config['base_delay'])
return True
time.sleep(0.5)
except Exception as e:
print(f"点击失败 尝试 {attempt + 1}/{retry}: {str(e)}")
time.sleep(1)
return False
def safe_input(self, selector, text: str, retry: int = 3) -> bool:
"""安全的文本输入,带重试机制"""
for attempt in range(retry):
try:
if selector.exists:
selector.set_text(text)
time.sleep(self.config['base_delay'])
return True
time.sleep(0.5)
except Exception as e:
print(f"输入失败 尝试 {attempt + 1}/{retry}: {str(e)}")
time.sleep(1)
return False
def step1_select_customer(self) -> bool:
"""步骤1: 选择客户"""
if (self.d(text="拼多多揽收").exists and
self.d(text="拼多多退换货物品").exists):
return self.safe_click(self.d(text="客户"))
return False
def step2_input_code(self) -> bool:
"""步骤2: 输入客户代码"""
if self.d(text="常用客户").exists:
return self.safe_input(
self.d(resourceId="cn.chinapost.jdpt.pda.pickup:id/post_code"),
"pddth"
)
return False
def step3_select_client(self) -> bool:
"""步骤3: 选择客户"""
if self.d(text="PDDTH").exists:
return self.safe_click(
self.d(textContains="上海寻梦")
)
return False
def step4_open_menu(self) -> bool:
"""步骤4: 打开菜单"""
if self.d(text="未实名").exists:
return self.safe_click(
self.d(resourceId="cn.chinapost.jdpt.pda.pickup:id/iv_main_menu")
)
return False
def step5_select_verify(self) -> bool:
"""步骤5: 选择实名校验"""
if self.d(text="实名校验").exists:
return self.safe_click(
self.d(text="实名校验")
)
return False
def step6_manual_input(self) -> bool:
"""步骤6: 手工输入"""
if self.d(text="重置/手工输入").exists:
return self.safe_click(
self.d(text="重置/手工输入")
)
return False
def step7_input_id(self) -> bool:
"""步骤7: 输入身份证号"""
id_input = self.d(resourceId="cn.chinapost.jdpt.pda.pickup:id/et_id")
return self.safe_input(id_input, self.config['id_card_number'])
def step8_submit_verify(self) -> bool:
"""步骤8: 提交认证"""
if self.d(resourceId="cn.chinapost.jdpt.pda.pickup:id/et_id").exists:
return self.safe_click(
self.d(text="人脸校验/确定")
)
return False
def step9_complete_post(self) -> bool:
"""步骤9: 完成收寄"""
if self.d(text="已实名").exists:
return self.safe_click(
self.d(text="收寄")
)
return False
def step10_go_back(self) -> bool:
"""步骤10: 返回"""
if self.d(text="打印面单").exists:
self.d.press("back")
time.sleep(self.config['base_delay'])
return True
return False
def step11_return_home(self) -> bool:
"""步骤11: 返回主界面"""
if self.d(text="国内揽收").exists:
return self.safe_click(
self.d(resourceId="cn.chinapost.jdpt.pda.pickup:id/pet_post")
)
return False
def run(self):
"""执行自动化流程"""
while True:
try:
steps = [
self.step1_select_customer,
self.step2_input_code,
self.step3_select_client,
self.step4_open_menu,
self.step5_select_verify,
self.step6_manual_input,
self.step7_input_id,
self.step8_submit_verify,
self.step9_complete_post,
self.step10_go_back,
self.step11_return_home
]
for step in steps:
if not step():
print(f"步骤 {step.__name__} 执行失败")
break
time.sleep(0.5)
except Exception as e:
回答
你提供的代码是使用uiautomator2库的Python脚本,而Hamibot使用的是JavaScript引擎(Rhino 1.7.15),两者API完全不兼容。Hamibot有自己的UI自动化框架,需要使用JavaScript编写脚本。
以下是针对邮政自动化流程的Hamibot实现方式和关键差异说明:
Hamibot脚本实现要点
文档地址 https://docs.hamibot.com/
// 邮政自动化脚本(Hamibot版)
function postalAutomation() {
// 步骤1: 选择客户
function step1_selectCustomer() {
if (text("拼多多揽收").exists() && text("拼多多退换货物品").exists()) {
return text("客户").findOne().click();
}
return false;
}
// 步骤2: 输入客户代码
function step2_inputCode() {
if (text("常用客户").exists()) {
return id("cn.chinapost.jdpt.pda.pickup:id/post_code")
.findOne()
.setText("pddth");
}
return false;
}
// 步骤3: 选择客户
function step3_selectClient() {
if (text("PDDTH").exists()) {
return textContains("上海寻梦").findOne().click();
}
return false;
}
// 步骤4: 打开菜单
function step4_openMenu() {
if (text("未实名").exists()) {
return id("cn.chinapost.jdpt.pda.pickup:id/iv_main_menu")
.findOne()
.click();
}
return false;
}
// 其他步骤类似实现...
// 执行流程
var steps = [
step1_selectCustomer,
step2_inputCode,
step3_selectClient,
step4_openMenu
// 添加其他步骤函数
];
for (var i = 0; i < steps.length; i++) {
var result = steps[i]();
if (!result) {
console.error("步骤执行失败:", steps[i].name);
return false;
}
sleep(200); // 等待操作完成
}
return true;
}
// 启动脚本
launchApp("cn.chinapost.jdpt.pda.pickup");
sleep(1000);
postalAutomation();
关键差异说明
-
选择器语法不同:
- uiautomator2:
d(text="客户") - Hamibot:
text("客户").findOne()
- uiautomator2:
-
控件操作方式:
- Hamibot使用链式调用:
text("客户").click() - 对于输入框:
id("input_field").setText("内容") - 知识库中提到:
setText()用于设置文本框内容,input()用于追加内容
- Hamibot使用链式调用:
-
等待机制:
- Hamibot推荐使用
findOne()自动等待控件出现 - 示例:
id('action_log').findOne(6000)在6秒内查找日志图标
- Hamibot推荐使用
-
返回键操作:
- Hamibot使用
back()函数,而不是d.press("back")
- Hamibot使用
-
超时处理:
- Hamibot的
findOne(timeout)可以设置超时时间 - 如:
id('submit_button').findOne(3000)
- Hamibot的
优化建议
-
添加适当的等待时间:
sleep(200)确保界面稳定 -
使用
waitFor()确保关键控件出现 -
对于关键操作添加重试机制:
function safeClick(selector, retries) { for (var i = 0; i < retries; i++) { try { selector.click(); return true; } catch (e) { sleep(500); } } return false; } -
针对邮政应用的特殊控件,可以使用知识库中提到的组合条件定位:
className("android.widget.EditText").depth(10).findOne().setText("pddth");
如果你需要特定邮政应用界面的详细选择器定位方法,可以提供具体界面截图或控件信息,我可以给出更精确的选择器方案。
ℹ️ 本回答由 AI 生成,内容仅供参考