perf: 量化商品页打开耗时并去重检查 (#109)

This commit is contained in:
chengma
2026-08-10 17:40:44 +08:00
parent 4c9bf3865b
commit ba0706dc47
13 changed files with 693 additions and 72 deletions
+68 -31
View File
@@ -11,6 +11,7 @@ import math
import re
import time
import xml.etree.ElementTree as ET
from contextlib import nullcontext
from dataclasses import dataclass
from datetime import datetime, timezone
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
@@ -19,6 +20,7 @@ from typing import Any, Callable, Iterable, Mapping, Optional, Sequence
from urllib.parse import parse_qs, urlparse
from .pdd_device_service import PDD_PACKAGE_NAME, PddDeviceError, PddDeviceService
from .performance_timing import current_performance_trace
from .util.get_size_panle_coord import get_size_panel_coord
@@ -691,8 +693,11 @@ class PddCollectService:
self._check_cancelled()
try:
with self._device_service.connect(self._device_address) as device:
self._open_goods(device, goods_url)
session = self._device_service.connect(self._device_address)
with session as device:
self._open_goods(
device, goods_url, session.initial_app_state
)
goods = self._collect_goods_details(device)
if not goods.title:
raise PddCollectError("PDD_DATA_TITLE_MISSING", "商品页没有可识别的标题")
@@ -779,14 +784,32 @@ class PddCollectService:
):
raise PddCollectError("PDD_PAGE_OVERALL_TIMEOUT", "PDD 采集超过 10 分钟")
def _open_goods(self, device: Any, goods_url: str) -> None:
def _open_goods(
self,
device: Any,
goods_url: str,
initial_app_state: Optional[Mapping[str, Any]] = None,
) -> None:
trace = current_performance_trace()
try:
current = device.app_current()
current = (
dict(initial_app_state)
if initial_app_state is not None
else device.app_current()
)
if current.get("package") != PDD_PACKAGE_NAME:
device.app_start(PDD_PACKAGE_NAME)
if not device.app_wait(PDD_PACKAGE_NAME, timeout=10):
raise PddCollectError("DEVICE_APP_START_FAILED", "PDD 应用启动失败")
device.open_url(goods_url)
stage = trace.stage("pdd_start_or_wait") if trace else nullcontext()
with stage:
device.app_start(PDD_PACKAGE_NAME)
if not device.app_wait(PDD_PACKAGE_NAME, timeout=10):
raise PddCollectError(
"DEVICE_APP_START_FAILED", "PDD 应用启动失败"
)
elif trace is not None:
trace.record("pdd_start_or_wait", 0, "already_foreground")
stage = trace.stage("open_url") if trace else nullcontext()
with stage:
device.open_url(goods_url)
except PddCollectError:
raise
except Exception as exc:
@@ -797,30 +820,44 @@ class PddCollectService:
) from exc
raise PddCollectError("DEVICE_APP_START_FAILED", f"无法打开 PDD 商品链接:{exc}") from exc
deadline = self._monotonic() + self._page_timeout
while self._monotonic() < deadline:
self._check_cancelled()
current = device.app_current()
xml_data = self._dump_hierarchy(device)
root = _parse_xml(xml_data)
last_labels = _all_labels(root)
pdd_node_count = sum(
1
for node in root.iter("node")
if node.get("package") == PDD_PACKAGE_NAME
ready_stage = trace.stage("goods_page_ready") if trace else nullcontext()
with ready_stage:
deadline = self._monotonic() + self._page_timeout
first_dump = True
while self._monotonic() < deadline:
self._check_cancelled()
current = device.app_current()
if first_dump and trace is not None:
with trace.stage("first_dump_hierarchy"):
xml_data = self._dump_hierarchy(device)
first_dump = False
else:
xml_data = self._dump_hierarchy(device)
root = _parse_xml(xml_data)
last_labels = _all_labels(root)
pdd_node_count = sum(
1
for node in root.iter("node")
if node.get("package") == PDD_PACKAGE_NAME
)
# 部分 OPPO/ColorOS 设备会一直把无线调试设置页报告为焦点,
# 即使屏幕和无障碍树已经是 PDD。此时以树中真实包名为准。
is_pdd_hierarchy = pdd_node_count >= 3
is_pdd_focused = current.get("package") == PDD_PACKAGE_NAME
if is_pdd_focused or is_pdd_hierarchy:
_raise_special_page(last_labels)
combined = " ".join(last_labels)
loading = "加载中" in combined or "正在加载" in combined
if not loading and any(
marker in combined for marker in _READY_MARKERS
):
if trace is not None:
trace.checkpoint("end_to_end_total")
return
self._sleep(0.5)
raise PddCollectError(
"PDD_PAGE_TIMEOUT", "等待 PDD 商品详情页加载超时"
)
# 部分 OPPO/ColorOS 设备会一直把无线调试设置页报告为焦点,
# 即使屏幕和无障碍树已经是 PDD。此时以树中真实包名为准。
is_pdd_hierarchy = pdd_node_count >= 3
is_pdd_focused = current.get("package") == PDD_PACKAGE_NAME
if is_pdd_focused or is_pdd_hierarchy:
_raise_special_page(last_labels)
combined = " ".join(last_labels)
loading = "加载中" in combined or "正在加载" in combined
if not loading and any(marker in combined for marker in _READY_MARKERS):
return
self._sleep(0.5)
raise PddCollectError("PDD_PAGE_TIMEOUT", "等待 PDD 商品详情页加载超时")
def _collect_goods_details(self, device: Any) -> GoodsSnapshot:
"""保留首屏结果,并向下浏览补采评价数量和店铺名。"""