fix(切号): 等面板/等回读改成轮询(固定 sleep 会把"没加载出来"误判成"本机没登这个号")+ 实测选择器入档

A01(抖音 40.6.0)实测:
· 冷启动后按固定 sleep(1.2s) 找账号列表行 → 列表还没渲染 → 判成"本机没登这个号" → **漏发且不报错**;
  现在两处都轮询到 deadline:等面板出目标行、等回读变成目标名。
· 实测选择器(写进 doc/research/U2_ELEMENT_SELECTORS.md §七 与 .env.example):
  昵称 `resourceId=com.ss.android.ugc.aweme:id/tk+`、切换入口 `descriptionContains=切换账号`、
  切号按名字点行 `textContains=<名字>`(行 TextView 不可点但 u2 按中心坐标点,行容器接住)、
  「我」页签 `descriptionContains=我`(desc 是「我,按钮」)。
· 并记下"为什么不要用 (…b7w)[N]":序号型会随列表行数/顺序错位 → 点错号 = 发到别人号上。
· 冷启动切号 17.2s 成功、热态 12.9s;A01 最终已切回原账号。
This commit is contained in:
2026-10-12 09:12:23 +08:00
parent beda0f3779
commit 1e8b97e386
6 changed files with 112 additions and 33 deletions
+34 -20
View File
@@ -1177,30 +1177,44 @@ class GenericStepsWorker(BaseWorker):
return self._handle_login_page(target, hint, params)
_log.warning(f"[{self.serial}] 切换账号:进不去账号列表(第 {i}/{attempts} 次)")
continue
time.sleep(1.2)
if not self._click_in_list(d, target, timeout=int(max(3, timeout))):
# 可能是列表还没加载出来 —— 再等一次;还没有就是"本机没登这个号"
time.sleep(1.5)
if not self._click_in_list(d, target, timeout=3):
hint = self._page_has_text(d, self._LOGIN_HINTS)
if hint:
return self._handle_login_page(target, hint, params)
_log.warning(f"[{self.serial}] 切换账号:账号列表里没有『{target}』"
f"→ 本机没登这个号,跳过(不重试)")
self.set_action(f"本机没有『{target}』这个号 → 跳过")
self._notify_account("task.account.switch_failed", want=target,
msg="账号列表里没有这个名字(本机没登这个号)")
# 等面板真的打开:**轮询找目标那一行,出现就点**。
# 固定 sleep 不够用(实测:冷启动/慢设备上点了切换入口后列表还没渲染出来,
# 一次找不到就误判成"本机没登这个号" —— 那是会漏发的假故障)。
hit = False
deadline = time.time() + max(6.0, timeout)
while time.time() < deadline:
if self.stopped():
return False
time.sleep(2.5) # 等切换生效(抖音会重载「我」页面)
if self._click_in_list(d, target, timeout=1):
hit = True
break
time.sleep(0.8)
if not hit:
hint = self._page_has_text(d, self._LOGIN_HINTS)
if hint:
return self._handle_login_page(target, hint, params)
_log.warning(f"[{self.serial}] 切换账号:账号列表里没有『{target}』"
f"(等了 {int(max(6.0, timeout))}s)→ 本机没登这个号,跳过(不重试)")
self.set_action(f"本机没有『{target}』这个号 → 跳过")
self._notify_account("task.account.switch_failed", want=target,
msg="账号列表里没有这个名字(本机没登这个号)")
return False
if not want_verify:
self.set_action(f"已点击『{target}』(未校验)")
return True
last_got = self._read_name_now(d, params)
if last_got == target:
_log.info(f"[{self.serial}] 切换账号成功:『{target}』(第 {i} 次)")
self.set_action(f"已切到『{target}』")
self._vars["account_name"] = target
return True
# 等切换生效:抖音会重载「我」页面,几秒内名字才会变 —— 同样轮询,别只读一次
last_got = ""
vdeadline = time.time() + max(6.0, timeout)
while time.time() < vdeadline:
if self.stopped():
return False
last_got = self._read_name_now(d, params)
if last_got == target:
_log.info(f"[{self.serial}] 切换账号成功:『{target}』(第 {i} 次)")
self.set_action(f"已切到『{target}』")
self._vars["account_name"] = target
return True
time.sleep(0.8)
hint = self._page_has_text(d, self._LOGIN_HINTS) if not last_got else ""
if hint:
return self._handle_login_page(target, hint, params)