From ef7eb9dbb1b3704006f665eac14f9ae04049636a Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 10 Jul 2026 20:27:58 +0800 Subject: [PATCH] =?UTF-8?q?branch=5Fnumber=E6=A3=80=E6=B5=8B=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/surugaya_client.py | 24 +++++++++++++++--------- tests/test_other_shop_parser.py | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/app/services/surugaya_client.py b/app/services/surugaya_client.py index b270f7f..8c5e79c 100644 --- a/app/services/surugaya_client.py +++ b/app/services/surugaya_client.py @@ -376,16 +376,22 @@ class SurugayaClient: shipping_note_node = row.css_first("ul.shipping_campaing_info li.padT5") shipping_note = shipping_note_node.text().strip() if shipping_note_node else "" + # branch_number 优先从 detail_url 的查询参数中提取(与 detail_url 保持一致), + # data-zaiko_data 仅作为兜底(极少数情况下 href 未携带 branch_number 时)。 branch_number = "" - campaign_node = row.css_first("li.ajax-campaign-placeholder") - if campaign_node: - zaiko_raw = campaign_node.attributes.get("data-zaiko_data") or "" - if zaiko_raw: - try: - zaiko = json.loads(zaiko_raw) - branch_number = str(zaiko.get("branch_number", "")) - except json.JSONDecodeError: - pass + if detail_href: + branch_number = (parse_qs(urlparse(detail_href).query).get("branch_number") or [""])[0] + + if not branch_number: + campaign_node = row.css_first("li.ajax-campaign-placeholder") + if campaign_node: + zaiko_raw = campaign_node.attributes.get("data-zaiko_data") or "" + if zaiko_raw: + try: + zaiko = json.loads(zaiko_raw) + branch_number = str(zaiko.get("branch_number", "")) + except json.JSONDecodeError: + pass items.append( OtherShopItem( diff --git a/tests/test_other_shop_parser.py b/tests/test_other_shop_parser.py index 04ac283..612ff4a 100644 --- a/tests/test_other_shop_parser.py +++ b/tests/test_other_shop_parser.py @@ -74,17 +74,35 @@ OTHER_SHOP_HTML = """ + +

980円

+ + +

中古

+
+ + +
駿河屋 テスト店
+
+
4.5(10件)
+ + + + + """ def test_parse_other_shop_list_extracts_all_rows() -> None: - """三行分别为:加盟店、官方自营、市场店铺,均应被正确解析。""" + """四行分别为:加盟店、官方自营、市场店铺、无 data-zaiko_data 的加盟店,均应被正确解析。""" tree = HTMLParser(OTHER_SHOP_HTML) items = SurugayaClient._parse_other_shop_list(tree) - assert len(items) == 3 + assert len(items) == 4 def test_parse_other_shop_list_franchise_row() -> None: @@ -133,6 +151,17 @@ def test_parse_other_shop_list_marketplace_row() -> None: assert item.rating_count == 46 +def test_parse_other_shop_list_branch_number_falls_back_to_detail_url() -> None: + """无 ajax-campaign-placeholder(无 data-zaiko_data)时,branch_number 应从 detail_url 查询参数回退提取。""" + tree = HTMLParser(OTHER_SHOP_HTML) + item = SurugayaClient._parse_other_shop_list(tree)[3] + + assert item.branch_number == "0003" + assert item.detail_url == ( + "https://www.suruga-ya.jp/product/detail/602274031?tenpo_cd=400567&branch_number=0003" + ) + + def test_parse_other_shop_list_empty_html_returns_empty_list() -> None: """页面结构不包含 tbl_all 时(如解析失败/改版),应返回空列表而非抛异常。""" tree = HTMLParser("no table here")