Added marketplace availability listing
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class JapanesePrefectures(Enum):
|
||||||
|
AICHI = "愛知県"
|
||||||
|
AKITA = "秋田県"
|
||||||
|
AOMORI = "青森県"
|
||||||
|
CHIBA = "千葉県"
|
||||||
|
EHIME = "愛媛県"
|
||||||
|
FUKUI = "福井県"
|
||||||
|
FUKUOKA = "福岡県"
|
||||||
|
FUKUSHIMA = "福島県"
|
||||||
|
GIFU = "岐阜県"
|
||||||
|
GUNMA = "群馬県"
|
||||||
|
HIROSHIMA = "広島県"
|
||||||
|
HOKKAIDO = "北海道"
|
||||||
|
HYOGO = "兵庫県"
|
||||||
|
IBARAKI = "茨城県"
|
||||||
|
ISHIKAWA = "石川県"
|
||||||
|
IWATE = "岩手県"
|
||||||
|
KAGAWA = "香川県"
|
||||||
|
KAGOSHIMA = "鹿児島県"
|
||||||
|
KANAGAWA = "神奈川県"
|
||||||
|
KOCHI = "高知県"
|
||||||
|
KUMAMOTO = "熊本県"
|
||||||
|
KYOTO = "京都府"
|
||||||
|
MIE = "三重県"
|
||||||
|
MIYAGI = "宮城県"
|
||||||
|
MIYAZAKI = "宮崎県"
|
||||||
|
NAGANO = "長野県"
|
||||||
|
NAGASAKI = "長崎県"
|
||||||
|
NARA = "奈良県"
|
||||||
|
NIIGATA = "新潟県"
|
||||||
|
OITA = "大分県"
|
||||||
|
OKAYAMA = "岡山県"
|
||||||
|
OKINAWA = "沖縄県"
|
||||||
|
OSAKA = "大阪府"
|
||||||
|
SAGA = "佐賀県"
|
||||||
|
SAITAMA = "埼玉県"
|
||||||
|
SHIGA = "滋賀県"
|
||||||
|
SHIMANE = "島根県"
|
||||||
|
SHIZUOKA = "静岡県"
|
||||||
|
TOCHIGI = "栃木県"
|
||||||
|
TOKUSHIMA = "徳島県"
|
||||||
|
TOKYO = "東京都"
|
||||||
|
TOTTORI = "鳥取県"
|
||||||
|
TOYAMA = "富山県"
|
||||||
|
WAKAYAMA = "和歌山県"
|
||||||
|
YAMAGATA = "山形県"
|
||||||
|
YAMAGUCHI = "山口県"
|
||||||
|
YAMANASHI = "山梨県"
|
||||||
|
@@ -9,6 +9,9 @@ from surugaya_api.consts import SURU_COOKIE_STRING
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
|
from surugaya_api.japan_prefectures import JapanesePrefectures
|
||||||
|
|
||||||
|
|
||||||
def get_or_create_aiohttp_session(func):
|
def get_or_create_aiohttp_session(func):
|
||||||
async def wrapper(*args, **kwargs):
|
async def wrapper(*args, **kwargs):
|
||||||
sig = inspect.signature(func)
|
sig = inspect.signature(func)
|
||||||
@@ -31,6 +34,8 @@ def get_or_create_aiohttp_session(func):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ProductStock:
|
class ProductStock:
|
||||||
condition: str
|
condition: str
|
||||||
@@ -50,9 +55,10 @@ class ProductStock:
|
|||||||
condition=item_price.select_one("label").attrs["data-label"].strip(),
|
condition=item_price.select_one("label").attrs["data-label"].strip(),
|
||||||
stock=data["zaiko"],
|
stock=data["zaiko"],
|
||||||
price=data["baika"],
|
price=data["baika"],
|
||||||
on_sale_price=data.get("price_sale")
|
on_sale_price=data.get("price_sale"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Product:
|
class Product:
|
||||||
id: int
|
id: int
|
||||||
@@ -89,3 +95,115 @@ async def load_product(product_id, aiohttp_session=None):
|
|||||||
return product
|
return product
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MarketplaceListing:
|
||||||
|
product_id: int
|
||||||
|
item_price: int
|
||||||
|
condition: str
|
||||||
|
product_link: str
|
||||||
|
store_name: str
|
||||||
|
store_id: int
|
||||||
|
special_info: str
|
||||||
|
shipping_price: int
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_price(self) -> int:
|
||||||
|
return self.item_price + self.shipping_price
|
||||||
|
|
||||||
|
|
||||||
|
@get_or_create_aiohttp_session
|
||||||
|
async def get_shipping_price_for_store(
|
||||||
|
store_id,
|
||||||
|
to_prefecture=JapanesePrefectures.KANAGAWA,
|
||||||
|
aiohttp_session: Optional[aiohttp.ClientSession] = None,
|
||||||
|
) -> int:
|
||||||
|
response = await aiohttp_session.post(
|
||||||
|
url="https://www.suruga-ya.jp/product-other/shipping-fee",
|
||||||
|
headers={
|
||||||
|
"Accept": "application/json, text/javascript, */*; q=0.01",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
"Origin": "https://www.suruga-ya.jp",
|
||||||
|
"Cookie": SURU_COOKIE_STRING,
|
||||||
|
},
|
||||||
|
data={
|
||||||
|
"tenpo_cd": store_id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
response_json = await response.json()
|
||||||
|
shipping_fees = response_json["data"]
|
||||||
|
|
||||||
|
if not shipping_fees["list_pref_fee"]:
|
||||||
|
shipping_price = shipping_fees["shipping"]["national_fee"]
|
||||||
|
else:
|
||||||
|
shipping_filtered = [
|
||||||
|
x
|
||||||
|
for x in shipping_fees["list_pref_fee"]
|
||||||
|
if x["prefecture"] == to_prefecture.value
|
||||||
|
]
|
||||||
|
|
||||||
|
if not shipping_filtered:
|
||||||
|
shipping_price = shipping_fees["shipping"]["national_fee"]
|
||||||
|
else:
|
||||||
|
shipping_price = shipping_filtered[0]["fee"]
|
||||||
|
|
||||||
|
return int(shipping_price)
|
||||||
|
|
||||||
|
|
||||||
|
@get_or_create_aiohttp_session
|
||||||
|
async def get_marketplace_availability(
|
||||||
|
product_id,
|
||||||
|
shipping_to_prefecture=JapanesePrefectures.KANAGAWA,
|
||||||
|
aiohttp_session: Optional[aiohttp.ClientSession] = None,
|
||||||
|
):
|
||||||
|
async with aiohttp_session.get(
|
||||||
|
f"https://www.suruga-ya.jp/product/other/{product_id}"
|
||||||
|
) as response:
|
||||||
|
if response.status == 301 or response.status == 302:
|
||||||
|
# TODO: Handle redirect to /product/detail if only one store is available
|
||||||
|
return []
|
||||||
|
|
||||||
|
page = await response.text()
|
||||||
|
page_bs = BeautifulSoup(page, features="html.parser")
|
||||||
|
|
||||||
|
items = page_bs.select("#tbl_all tr.item")
|
||||||
|
listings = []
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
if item.select_one("td:nth-child(3) a").attrs["href"] == "/":
|
||||||
|
# Main online store, not processing
|
||||||
|
continue
|
||||||
|
|
||||||
|
item_price = (
|
||||||
|
item.select_one("td:nth-child(1) .title_product > strong")
|
||||||
|
.text.replace(",", "")
|
||||||
|
.replace("円", "")
|
||||||
|
)
|
||||||
|
|
||||||
|
condition = item.select_one("td:nth-child(2) .title_product").text
|
||||||
|
product_link = item.select_one("td:nth-child(2) > a").attrs["href"]
|
||||||
|
|
||||||
|
store_id = item.select_one("td:nth-child(3) a").attrs["href"].split("/")[-1]
|
||||||
|
store_name = item.select_one("td:nth-child(3) a").text
|
||||||
|
shipping_price = await get_shipping_price_for_store(
|
||||||
|
store_id, shipping_to_prefecture, aiohttp_session
|
||||||
|
)
|
||||||
|
|
||||||
|
special_info = "\n".join(
|
||||||
|
[x.text for x in item.select("td:nth-child(4) .padT5 div")]
|
||||||
|
)
|
||||||
|
|
||||||
|
listings.append(
|
||||||
|
MarketplaceListing(
|
||||||
|
product_id=int(product_id),
|
||||||
|
item_price=int(item_price),
|
||||||
|
condition=condition,
|
||||||
|
product_link=product_link,
|
||||||
|
store_name=store_name,
|
||||||
|
store_id=int(store_id),
|
||||||
|
special_info=special_info,
|
||||||
|
shipping_price=shipping_price,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return listings
|
||||||
|
Reference in New Issue
Block a user