fix: 合并近重叠地址入口候选 (#276)

This commit is contained in:
chengma
2026-08-18 17:42:47 +08:00
parent ff96f652c4
commit 7c56c29032
2 changed files with 90 additions and 3 deletions
+56 -3
View File
@@ -547,17 +547,70 @@ def _pdd_title_back_targets(root: ET.Element) -> list[Bounds]:
]
def _same_address_target(first: Bounds, second: Bounds) -> bool:
"""判断两个边界是否是同一地址卡片的重复无障碍节点。"""
# 使用两倍中心坐标计算,避免浮点数;阈值等价于中心距离每轴 3 像素。
if (
abs((first[0] + first[2]) - (second[0] + second[2])) > 6
or abs((first[1] + first[3]) - (second[1] + second[3])) > 6
):
return False
intersection_width = max(
0, min(first[2], second[2]) - max(first[0], second[0])
)
intersection_height = max(
0, min(first[3], second[3]) - max(first[1], second[1])
)
intersection_area = intersection_width * intersection_height
first_area = (first[2] - first[0]) * (first[3] - first[1])
second_area = (second[2] - second[0]) * (second[3] - second[1])
smaller_area = min(first_area, second_area)
return smaller_area > 0 and intersection_area * 100 >= smaller_area * 98
def _merge_address_targets(targets: list[Bounds]) -> list[Bounds]:
"""严格合并近乎完全重叠的地址候选,并返回共同安全区域。"""
clusters: list[list[Bounds]] = []
for target in sorted(set(targets)):
cluster = next(
(
item
for item in clusters
if all(_same_address_target(target, other) for other in item)
),
None,
)
if cluster is None:
clusters.append([target])
else:
cluster.append(target)
merged: list[Bounds] = []
for cluster in clusters:
intersection = (
max(item[0] for item in cluster),
max(item[1] for item in cluster),
min(item[2] for item in cluster),
min(item[3] for item in cluster),
)
if intersection[2] > intersection[0] and intersection[3] > intersection[1]:
merged.append(intersection)
return sorted(merged)
def _address_entry_targets(root: ET.Element) -> list[Bounds]:
"""通过脱敏手机号结构定位规格面板顶部的收货地址卡片。"""
parents = _parent_nodes(root)
targets = {
targets = [
bounds
for node in root.iter("node")
if _MASKED_PHONE_PATTERN.search(_label(node))
if (bounds := _nearest_clickable_bounds(node, parents)) is not None
}
return sorted(targets)
]
return _merge_address_targets(targets)
def _shipping_address_editor(root: ET.Element) -> Optional[tuple[str, Bounds]]: