fix: 允许颜色缺价后继续采集 (#42)

This commit is contained in:
chengma
2026-08-08 11:25:06 +08:00
parent ccc146cfbe
commit 5aaf0a937e
5 changed files with 52 additions and 25 deletions
+10 -25
View File
@@ -699,18 +699,6 @@ class PddCollectService:
self._wait_spec_panel(device)
color_dimension, color_samples = self._collect_color_prices(device)
missing_prices = [
color.text
for color in color_dimension.values
if color.available
and color_samples[color.text].price_cent is None
]
if missing_prices:
raise PddCollectError(
"PDD_DATA_PRICE_MISSING",
"以下可用颜色没有采集到稳定价格:"
+ "、".join(missing_prices),
)
size_dimension = self._collect_size_dimension(device)
dimensions = (color_dimension,)
if size_dimension is not None:
@@ -723,11 +711,11 @@ class PddCollectService:
skus = self._build_color_price_skus(
dimensions, color_samples
)
has_available_price = any(
item.price_cent is not None for item in skus if item.available
)
if not skus or not has_available_price:
raise PddCollectError("PDD_DATA_PRICE_MISSING", "没有采集到可用 SKU 的价格")
if not skus:
raise PddCollectError(
"PDD_DATA_SPEC_INCOMPLETE",
"规格面板没有生成可提交的规格组合",
)
except PddCollectError as exc:
if not exc.diagnostics and self._last_goods_xml:
artifact = self._save_xml("collect-failed", self._last_goods_xml)
@@ -1207,21 +1195,18 @@ class PddCollectService:
options = {"color": color.text}
if size is not None:
options["size"] = size.text
available = (
color.available
and (size is None or size.available)
and sample.price_cent is not None
)
# 是否可用来自规格控件状态,不能用“是否采到价格”代替。
available = color.available and (size is None or size.available)
results.append(
SkuResult(
options,
sample.price_cent if available else None,
sample.price_cent,
available,
sample.raw_price if available else None,
sample.raw_price,
{"color": color.text}
if sample.price_cent is not None
else {},
sample.list_price_cent if available else None,
sample.list_price_cent,
)
)
return tuple(results)
+33
View File
@@ -232,6 +232,13 @@ class IgnoredColorClickDevice(SnakeColorDevice):
self.clicks.append((x, y))
class AllMissingColorPriceDevice(IgnoredColorClickDevice):
"""所有颜色点击都未生效,模拟全部颜色采价为空。"""
def _spec_xml(self):
return super()._spec_xml().replace('selected="true"', 'selected="false"')
def keep_only_one_sku(xml_data: str) -> str:
"""从脱敏固件中删除蓝色和 L,只保留一个组合。"""
@@ -562,6 +569,32 @@ class PddCollectParserTest(unittest.TestCase):
self.assertIsNone(sample.price_cent)
def test_all_missing_color_prices_still_collects_sizes(self):
device = AllMissingColorPriceDevice(self.home_xml)
service = PddCollectService(
PddDeviceService(lambda _serial: device),
"USB-001",
"client-001",
sleeper=lambda _seconds: None,
)
data = service.collect(
FakeTask("https://mobile.yangkeduo.com/goods.html?goods_id=123")
).to_pdd_data()
self.assertEqual(
[item["text"] for item in data["dimensions"][1]["values"]],
["M", "L"],
)
self.assertTrue(device.sizes_visible)
self.assertTrue(data["skus"])
self.assertTrue(all(item["price_cent"] is None for item in data["skus"]))
self.assertTrue(all(item["raw_price"] is None for item in data["skus"]))
self.assertTrue(
all(item["price_observed_at"] == {} for item in data["skus"])
)
self.assertTrue(all(item["available"] for item in data["skus"]))
def test_missing_goods_id_is_structured_error(self):
service = PddCollectService(
PddDeviceService(lambda _serial: object()),