fix: 稳定进入收货地址编辑页 (#179)
This commit is contained in:
@@ -245,6 +245,21 @@ def _shipping_address_editor(root: ET.Element) -> Optional[tuple[str, Bounds]]:
|
||||
return matches[0] if len(matches) == 1 and matches[0][0].strip() else None
|
||||
|
||||
|
||||
def _address_page_kind(root: ET.Element) -> str:
|
||||
"""识别地址面板、编辑页和返回后的规格确认页。"""
|
||||
|
||||
labels = _labels(root)
|
||||
if any("修改收货地址" in label.replace(" ", "") for label in labels):
|
||||
return "edit"
|
||||
if _shipping_address_editor(root) is not None:
|
||||
return "edit"
|
||||
if "收货地址" in labels:
|
||||
return "panel"
|
||||
if _page_kind(root, "") == "order_confirmation":
|
||||
return "confirmation"
|
||||
return "unknown"
|
||||
|
||||
|
||||
def _tagged_shipping_address(address: str, purchase_number: str) -> str:
|
||||
"""只替换程序生成的末尾标记,保留完整真实地址主体。"""
|
||||
|
||||
@@ -1247,14 +1262,7 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
||||
)
|
||||
|
||||
panel_root = self._wait_for_address_page("panel")
|
||||
modify_targets = _clickable_text_targets(panel_root, "修改")
|
||||
self._click_unique_address_target(
|
||||
modify_targets,
|
||||
"PURCHASE_ADDRESS_EDIT_AMBIGUOUS",
|
||||
"收货地址页没有唯一可靠的修改按钮",
|
||||
)
|
||||
|
||||
edit_root = self._wait_for_address_page("edit")
|
||||
edit_root = self._open_address_edit_page(panel_root)
|
||||
editor_data = _shipping_address_editor(edit_root)
|
||||
if editor_data is None:
|
||||
raise PddPurchaseError(
|
||||
@@ -1335,16 +1343,101 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
||||
(left + right) // 2, (top + bottom) // 2
|
||||
)
|
||||
|
||||
def _open_address_edit_page(self, panel_root: ET.Element) -> ET.Element:
|
||||
"""稳定识别“修改”按钮;首次点击丢失时最多安全重试一次。"""
|
||||
|
||||
deadline = self._monotonic() + self._panel_timeout
|
||||
root = panel_root
|
||||
observed_page = _address_page_kind(root)
|
||||
candidate_count = 0
|
||||
stable_target: Optional[Bounds] = None
|
||||
stable_reads = 0
|
||||
first_clicked_target: Optional[Bounds] = None
|
||||
click_attempts = 0
|
||||
|
||||
while self._monotonic() < deadline:
|
||||
self._check_cancelled("purchase_update_shipping_address")
|
||||
observed_page = _address_page_kind(root)
|
||||
if observed_page == "edit":
|
||||
return root
|
||||
|
||||
if observed_page == "panel":
|
||||
targets = _clickable_text_targets(root, "修改")
|
||||
candidate_count = len(targets)
|
||||
if candidate_count != 1:
|
||||
raise PddPurchaseError(
|
||||
"PURCHASE_ADDRESS_EDIT_AMBIGUOUS",
|
||||
"收货地址页没有唯一可靠的修改按钮",
|
||||
step="purchase_update_shipping_address",
|
||||
diagnostics={
|
||||
"candidate_count": candidate_count,
|
||||
"click_attempts": click_attempts,
|
||||
"observed_page": observed_page,
|
||||
},
|
||||
)
|
||||
|
||||
current_target = targets[0]
|
||||
retry_target_changed = (
|
||||
first_clicked_target is not None
|
||||
and current_target != first_clicked_target
|
||||
)
|
||||
if retry_target_changed or click_attempts >= 2:
|
||||
stable_target = None
|
||||
stable_reads = 0
|
||||
elif current_target == stable_target:
|
||||
stable_reads += 1
|
||||
else:
|
||||
stable_target = current_target
|
||||
stable_reads = 1
|
||||
|
||||
if stable_reads >= 2:
|
||||
self._click_unique_address_target(
|
||||
targets,
|
||||
"PURCHASE_ADDRESS_EDIT_AMBIGUOUS",
|
||||
"收货地址页没有唯一可靠的修改按钮",
|
||||
)
|
||||
click_attempts += 1
|
||||
if first_clicked_target is None:
|
||||
first_clicked_target = current_target
|
||||
stable_target = None
|
||||
stable_reads = 0
|
||||
else:
|
||||
# 页面状态不明确时不能继续点击,避免误触其他页面。
|
||||
candidate_count = 0
|
||||
stable_target = None
|
||||
stable_reads = 0
|
||||
|
||||
self._sleep(0.2)
|
||||
root = _parse_xml(self._dump_hierarchy())
|
||||
|
||||
diagnostics: dict[str, Any] = {
|
||||
"expected_page": "edit",
|
||||
"observed_page": observed_page,
|
||||
"click_attempts": click_attempts,
|
||||
"candidate_count": candidate_count,
|
||||
}
|
||||
artifact = self._save_last_xml("purchase-address-edit-timeout")
|
||||
if artifact is not None:
|
||||
diagnostics["artifacts"] = [artifact]
|
||||
raise PddPurchaseError(
|
||||
"PURCHASE_ADDRESS_PAGE_TIMEOUT",
|
||||
"收货地址页面切换或保存确认超时,未进入不可逆下单阶段",
|
||||
step="purchase_update_shipping_address",
|
||||
diagnostics=diagnostics,
|
||||
)
|
||||
|
||||
def _wait_for_address_page(
|
||||
self, kind: str, *, expected_address: str = ""
|
||||
) -> ET.Element:
|
||||
"""等待地址页面切换;诊断信息不包含任何地址文字。"""
|
||||
|
||||
deadline = self._monotonic() + self._panel_timeout
|
||||
observed_page = "unknown"
|
||||
while self._monotonic() < deadline:
|
||||
self._check_cancelled("purchase_update_shipping_address")
|
||||
root = _parse_xml(self._dump_hierarchy())
|
||||
labels = _labels(root)
|
||||
observed_page = _address_page_kind(root)
|
||||
if kind == "panel" and "收货地址" in labels:
|
||||
return root
|
||||
if kind == "edit" and any(
|
||||
@@ -1365,11 +1458,18 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
||||
):
|
||||
return root
|
||||
self._sleep(0.2)
|
||||
diagnostics: dict[str, Any] = {
|
||||
"expected_page": kind,
|
||||
"observed_page": observed_page,
|
||||
}
|
||||
artifact = self._save_last_xml(f"purchase-address-{kind}-timeout")
|
||||
if artifact is not None:
|
||||
diagnostics["artifacts"] = [artifact]
|
||||
raise PddPurchaseError(
|
||||
"PURCHASE_ADDRESS_PAGE_TIMEOUT",
|
||||
"收货地址页面切换或保存确认超时,未进入不可逆下单阶段",
|
||||
step="purchase_update_shipping_address",
|
||||
diagnostics={"expected_page": kind},
|
||||
diagnostics=diagnostics,
|
||||
)
|
||||
|
||||
def submit_order_once(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user