perf: 量化商品页打开耗时并去重检查 (#109)
This commit is contained in:
@@ -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:
|
||||
"""保留首屏结果,并向下浏览补采评价数量和店铺名。"""
|
||||
|
||||
Reference in New Issue
Block a user