fix: 打勾检测改用全局蓝色角标计数,不受列表滚动漂移影响
根因:等待期间列表轻微滚动(约50px),用点击时的旧行坐标检测打勾 位置偏移,导致明明已打勾却检测不到0/6,误判为下载失败。 修复: - 新增 count_checked_badges():扫描整屏蓝色角标总数,不依赖行坐标 - 等待逻辑改为:点击前记基线→等待期间统计当前总数→ 增量>=点击数即完成 - 重试逻辑同步改用全局计数
This commit is contained in:
+45
-24
@@ -346,6 +346,26 @@ def get_checked_cells_dynamic(png_path, row_centers):
|
|||||||
return checked
|
return checked
|
||||||
|
|
||||||
|
|
||||||
|
def count_checked_badges(png_path):
|
||||||
|
"""统计整屏已打勾(蓝色角标)的卡片数量,不依赖行坐标。
|
||||||
|
等待期间列表可能轻微滚动,用绝对坐标检测打勾会偏移,
|
||||||
|
改为直接扫描整屏蓝色角标总数,不受行位置漂移影响。"""
|
||||||
|
try:
|
||||||
|
with Image.open(png_path) as img:
|
||||||
|
img = img.convert("RGB")
|
||||||
|
w, h = img.size
|
||||||
|
cnt = 0
|
||||||
|
# 扫描卡片区域内所有可能的角标位置(3列 × 多行)
|
||||||
|
for gx in THUMB_X:
|
||||||
|
for cy in range(ROW_Y0 + 100, ROW_Y1, ROW_PITCH):
|
||||||
|
bx, by = gx + BADGE_OFFSET[0], cy + BADGE_OFFSET[1]
|
||||||
|
if count_blue_pixels(png_path, bx, by) >= BLUE_THRESHOLD:
|
||||||
|
cnt += 1
|
||||||
|
return cnt
|
||||||
|
except Exception:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def launch_app():
|
def launch_app():
|
||||||
"""从头启动 App,等待 618 开屏广告自动关闭后回到首页。
|
"""从头启动 App,等待 618 开屏广告自动关闭后回到首页。
|
||||||
用 am start -S 强制重启主 Activity(比 monkey 更可靠:避免之前残留的
|
用 am start -S 强制重启主 Activity(比 monkey 更可靠:避免之前残留的
|
||||||
@@ -731,40 +751,40 @@ def tap_all_thumbnails(baseline, max_rounds=300, poll_interval=4, max_wait_per_r
|
|||||||
# 关键:等这一轮点击的卡片全部显示打勾(下载完成)再滚动。这样滚动
|
# 关键:等这一轮点击的卡片全部显示打勾(下载完成)再滚动。这样滚动
|
||||||
# 留下的重叠行必然是打勾状态,下一轮开头 get_checked_cells 会跳过它们,
|
# 留下的重叠行必然是打勾状态,下一轮开头 get_checked_cells 会跳过它们,
|
||||||
# 从根上消除"重叠行还没下完就被重复点击"这个唯一的重复来源。
|
# 从根上消除"重叠行还没下完就被重复点击"这个唯一的重复来源。
|
||||||
print(f" 轮 {r+1}: 等待刚点击的 {len(tapped_cells)} 个卡片全部打勾(最多 {max_wait_per_round}s)...")
|
baseline_checked = count_checked_badges(grid_shot)
|
||||||
|
target_checked = baseline_checked + len(tapped_cells)
|
||||||
|
print(f" 轮 {r+1}: 等待刚点击的 {len(tapped_cells)} 个卡片全部打勾(基线 {baseline_checked},目标 {target_checked})...")
|
||||||
waited = 0
|
waited = 0
|
||||||
pending = list(tapped_cells)
|
done = 0
|
||||||
while waited < max_wait_per_round:
|
while waited < max_wait_per_round:
|
||||||
time.sleep(poll_interval)
|
time.sleep(poll_interval)
|
||||||
waited += poll_interval
|
waited += poll_interval
|
||||||
ensure_not_anr() # 等待期间 App 也可能卡死,同样要检测
|
ensure_not_anr()
|
||||||
wait_shot = screenshot("/tmp/_waitchk.png")
|
wait_shot = screenshot("/tmp/_waitchk.png")
|
||||||
# 等待期间未滚动,行位置不变,复用本轮 row_centers 复检这些格子
|
current_checked = count_checked_badges(wait_shot)
|
||||||
chk = get_checked_cells_dynamic(wait_shot, row_centers)
|
done = current_checked - baseline_checked
|
||||||
pending = [c for c in tapped_cells if not chk.get(c)]
|
if done >= len(tapped_cells):
|
||||||
if not pending:
|
|
||||||
break
|
break
|
||||||
done = len(tapped_cells) - len(pending)
|
pending = len(tapped_cells) - done
|
||||||
total = get_remote_new_file_count(baseline)
|
total = get_remote_new_file_count(baseline)
|
||||||
if pending:
|
if pending:
|
||||||
# 超时未打勾:先不重试点击(队列满时重试无效),再等一轮让正在下载的完成
|
# 第二轮等待:不重试点击,让正在下载的完成
|
||||||
print(f" 轮 {r+1}: 等待 {waited}s 后 {done}/{len(tapped_cells)} 个已打勾,"
|
print(f" 轮 {r+1}: 等待 {waited}s 后 {done}/{len(tapped_cells)} 个已打勾,继续等待...")
|
||||||
f"仍有 {len(pending)} 个未完成,继续等待一轮...")
|
|
||||||
wait2_waited = 0
|
wait2_waited = 0
|
||||||
while wait2_waited < max_wait_per_round:
|
while wait2_waited < max_wait_per_round:
|
||||||
time.sleep(poll_interval)
|
time.sleep(poll_interval)
|
||||||
wait2_waited += poll_interval
|
wait2_waited += poll_interval
|
||||||
ensure_not_anr()
|
ensure_not_anr()
|
||||||
w2_shot = screenshot("/tmp/_wait2.png")
|
w2_shot = screenshot("/tmp/_wait2.png")
|
||||||
w2_chk = get_checked_cells_dynamic(w2_shot, row_centers)
|
current2 = count_checked_badges(w2_shot)
|
||||||
still_pending = [c for c in pending if not w2_chk.get(c)]
|
done = current2 - baseline_checked
|
||||||
if not still_pending:
|
if done >= len(tapped_cells):
|
||||||
break
|
break
|
||||||
if still_pending:
|
pending = len(tapped_cells) - done
|
||||||
# 两轮等待后仍未打勾,可能是点击没生效(落在间隙上)或队列满被拒绝
|
if pending:
|
||||||
# 再重试点击一次,然后等最后一轮
|
# 两轮等待后仍未完成,重试点击所有未完成的卡片
|
||||||
print(f" 轮 {r+1}: 再等 {wait2_waited}s 后仍有 {len(still_pending)} 个未完成,重试点击...")
|
print(f" 轮 {r+1}: 再等 {wait2_waited}s 后仍有 {pending} 个未完成,重试点击...")
|
||||||
for (gx, cy) in still_pending:
|
for (gx, cy) in tapped_cells:
|
||||||
adb("shell", "input", "tap", str(gx), str(cy))
|
adb("shell", "input", "tap", str(gx), str(cy))
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
retry_waited = 0
|
retry_waited = 0
|
||||||
@@ -773,12 +793,13 @@ def tap_all_thumbnails(baseline, max_rounds=300, poll_interval=4, max_wait_per_r
|
|||||||
retry_waited += poll_interval
|
retry_waited += poll_interval
|
||||||
ensure_not_anr()
|
ensure_not_anr()
|
||||||
retry_shot = screenshot("/tmp/_retrywait.png")
|
retry_shot = screenshot("/tmp/_retrywait.png")
|
||||||
retry_chk = get_checked_cells_dynamic(retry_shot, row_centers)
|
current3 = count_checked_badges(retry_shot)
|
||||||
still_pending = [c for c in still_pending if not retry_chk.get(c)]
|
done = current3 - baseline_checked
|
||||||
if not still_pending:
|
if done >= len(tapped_cells):
|
||||||
break
|
break
|
||||||
if still_pending:
|
pending = len(tapped_cells) - done
|
||||||
print(f" 轮 {r+1}: 三轮等待后仍有 {len(still_pending)} 个未完成,照常滚动(靠下游去重兜底)")
|
if pending:
|
||||||
|
print(f" 轮 {r+1}: 三轮等待后仍有 {pending} 个未完成,照常滚动(靠下游去重兜底)")
|
||||||
else:
|
else:
|
||||||
print(f" 轮 {r+1}: 全部打勾完成")
|
print(f" 轮 {r+1}: 全部打勾完成")
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user