fix: 校验 PDD 采集商品链接 (#28)
This commit is contained in:
@@ -507,9 +507,27 @@ def _raise_special_page(labels: Sequence[str]) -> None:
|
||||
raise PddCollectError("PDD_PAGE_LOGIN_REQUIRED", "PDD 登录已失效,需要人工重新登录")
|
||||
|
||||
|
||||
def _goods_id_from_url(goods_url: str) -> str:
|
||||
value = parse_qs(urlparse(goods_url).query).get("goods_id", [""])[0].strip()
|
||||
if not value:
|
||||
def _validate_goods_url(goods_url: str, task_goods_id: str) -> str:
|
||||
parsed = urlparse(goods_url)
|
||||
host = (parsed.hostname or "").lower()
|
||||
allowed_host = host == "yangkeduo.com" or host.endswith(".yangkeduo.com")
|
||||
allowed_host = allowed_host or host == "pinduoduo.com" or host.endswith(
|
||||
".pinduoduo.com"
|
||||
)
|
||||
if parsed.scheme not in ("http", "https") or not allowed_host:
|
||||
raise PddCollectError(
|
||||
"PDD_DATA_GOODS_URL_INVALID",
|
||||
"商品链接不是受支持的 PDD 链接",
|
||||
)
|
||||
|
||||
url_goods_id = parse_qs(parsed.query).get("goods_id", [""])[0].strip()
|
||||
if task_goods_id and url_goods_id and task_goods_id != url_goods_id:
|
||||
raise PddCollectError(
|
||||
"PDD_DATA_GOODS_ID_MISMATCH",
|
||||
"任务商品编号与商品链接中的 goods_id 不一致",
|
||||
)
|
||||
value = task_goods_id or url_goods_id
|
||||
if not value or not value.isdigit():
|
||||
raise PddCollectError("PDD_DATA_GOODS_ID_MISSING", "商品链接中没有 goods_id")
|
||||
return value
|
||||
|
||||
@@ -566,7 +584,7 @@ class PddCollectService:
|
||||
if not goods_url:
|
||||
raise PddCollectError("PDD_DATA_GOODS_URL_MISSING", "采集任务缺少商品链接")
|
||||
goods_id = str(getattr(task, "goods_id", "") or "").strip()
|
||||
goods_id = goods_id or _goods_id_from_url(goods_url)
|
||||
goods_id = _validate_goods_url(goods_url, goods_id)
|
||||
self._check_cancelled()
|
||||
|
||||
try:
|
||||
|
||||
@@ -165,9 +165,34 @@ class PddCollectParserTest(unittest.TestCase):
|
||||
"client-001",
|
||||
)
|
||||
with self.assertRaises(PddCollectError) as raised:
|
||||
service.collect(FakeTask("https://example.com/goods.html"))
|
||||
service.collect(FakeTask("https://mobile.yangkeduo.com/goods.html"))
|
||||
self.assertEqual(raised.exception.code, "PDD_DATA_GOODS_ID_MISSING")
|
||||
|
||||
def test_non_pdd_goods_url_is_rejected_before_opening_device(self):
|
||||
service = PddCollectService(
|
||||
PddDeviceService(lambda _serial: object()),
|
||||
"USB-001",
|
||||
"client-001",
|
||||
)
|
||||
with self.assertRaises(PddCollectError) as raised:
|
||||
service.collect(FakeTask("https://example.com/goods.html?goods_id=123"))
|
||||
self.assertEqual(raised.exception.code, "PDD_DATA_GOODS_URL_INVALID")
|
||||
|
||||
def test_task_goods_id_must_match_url(self):
|
||||
service = PddCollectService(
|
||||
PddDeviceService(lambda _serial: object()),
|
||||
"USB-001",
|
||||
"client-001",
|
||||
)
|
||||
with self.assertRaises(PddCollectError) as raised:
|
||||
service.collect(
|
||||
FakeTask(
|
||||
"https://mobile.yangkeduo.com/goods.html?goods_id=123",
|
||||
goods_id="456",
|
||||
)
|
||||
)
|
||||
self.assertEqual(raised.exception.code, "PDD_DATA_GOODS_ID_MISMATCH")
|
||||
|
||||
def test_page_timeout_has_specific_error_code(self):
|
||||
device = LoadingDevice(self.home_xml, self.spec_xml)
|
||||
ticks = iter((0.0, 2.0))
|
||||
|
||||
Reference in New Issue
Block a user