From 60adf4e0af690df15d32c2ef7f3e6816e7dbea2f Mon Sep 17 00:00:00 2001 From: Remilia Da Costa Faro Date: Sat, 8 Feb 2025 22:31:30 -0500 Subject: [PATCH] Added product page fetching --- .idea/.gitignore | 8 ++ .idea/inspectionProfiles/Project_Default.xml | 16 ++++ .../inspectionProfiles/profiles_settings.xml | 7 ++ .idea/misc.xml | 9 +++ .idea/modules.xml | 8 ++ .idea/surugaya_api.iml | 10 +++ .idea/vcs.xml | 6 ++ surugaya_api/__init__.py | 0 surugaya_api/consts.py | 1 + surugaya_api/product.py | 75 +++++++++++++++++++ 10 files changed, 140 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/surugaya_api.iml create mode 100644 .idea/vcs.xml create mode 100644 surugaya_api/__init__.py create mode 100644 surugaya_api/consts.py create mode 100644 surugaya_api/product.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..d44d6b7 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..dd4c951 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..238295d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..3b71f12 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/surugaya_api.iml b/.idea/surugaya_api.iml new file mode 100644 index 0000000..72e0687 --- /dev/null +++ b/.idea/surugaya_api.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/surugaya_api/__init__.py b/surugaya_api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/surugaya_api/consts.py b/surugaya_api/consts.py new file mode 100644 index 0000000..4a9d210 --- /dev/null +++ b/surugaya_api/consts.py @@ -0,0 +1 @@ +SURU_COOKIE_STRING = "safe_search_option=3; safe_search_expired=2; z_hyoji=0; p_adult=1; p_hyoji=0" \ No newline at end of file diff --git a/surugaya_api/product.py b/surugaya_api/product.py new file mode 100644 index 0000000..d753463 --- /dev/null +++ b/surugaya_api/product.py @@ -0,0 +1,75 @@ +import json +from dataclasses import dataclass +from typing import Optional + +import aiohttp +from bs4 import BeautifulSoup + +from surugaya_api.consts import SURU_COOKIE_STRING + +@dataclass +class ProductStock: + condition: str + stock: str + price: int + on_sale_price: Optional[int] + + @property + def is_on_sale(self) -> bool: + return self.on_sale_price is not None + + @staticmethod + def from_item_price(item_price): + data: dict = json.loads(item_price.select_one("input").attrs["data-zaiko"]) + + return ProductStock( + condition=item_price.select_one("label").attrs["data-label"].strip(), + stock=data["zaiko"], + price=data["baika"], + on_sale_price=data.get("price_sale") + ) + +@dataclass +class Product: + id: int + name: str + main_image_href: str + stock: [ProductStock] + + @property + def in_stock(self): + return not self.stock + + +async def load_product(product_id, aiohttp_session=None): + if not aiohttp_session: + _aiohttp_session = aiohttp.ClientSession() + else: + _aiohttp_session = aiohttp_session + + async with _aiohttp_session.get( + url="https://www.suruga-ya.jp/product/detail/" + str(product_id), + headers={ + "Cookie": SURU_COOKIE_STRING, + }, + ) as response: + page = await response.text() + + page_bs = BeautifulSoup( + page, features="html.parser" + ) + + product = Product( + id=int(product_id), + name=page_bs.select_one("#item_title").text.strip(), + main_image_href=page_bs.select_one(".main-pro-img").attrs["src"], + stock=[ + ProductStock.from_item_price(item_price) + for item_price in page_bs.select(".item-price") + ] + ) + + if not aiohttp_session: + await _aiohttp_session.close() + + return product \ No newline at end of file