ADD ability to select shipping packages and sell directly

This commit is contained in:
Jeppy
2022-11-07 19:33:08 +01:00
committed by Sebastian Thomschke
parent 664c0dfc7f
commit e483c003d0
4 changed files with 70 additions and 1 deletions

View File

@@ -232,6 +232,7 @@ ad_defaults:
price_type: NEGOTIABLE # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE price_type: NEGOTIABLE # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE
shipping_type: SHIPPING # one of: PICKUP, SHIPPING, NOT_APPLICABLE shipping_type: SHIPPING # one of: PICKUP, SHIPPING, NOT_APPLICABLE
shipping_costs: # e.g. 2.95 shipping_costs: # e.g. 2.95
sell_directly: false # requires shipping_options to take effect
contact: contact:
name: "" name: ""
street: "" street: ""
@@ -295,6 +296,22 @@ special_attributes:
shipping_type: # one of: PICKUP, SHIPPING, NOT_APPLICABLE shipping_type: # one of: PICKUP, SHIPPING, NOT_APPLICABLE
shipping_costs: # e.g. 2.95 shipping_costs: # e.g. 2.95
# specify shipping options / packages
# it is possible to select multiple packages, but only from one size (S, M, L)!
# possible package types for size S:
# - DHL_2
# - Hermes_Päckchen
# - Hermes_S
# possible package types for size M:
# - DHL_5
# - Hermes_M
# possible package types for size L:
# - DHL_10
# - DHL_31,5
# - Hermes_L
shipping_options: []
sell_directly: # true or false, requires shipping_options to take effect
# list of wildcard patterns to select images # list of wildcard patterns to select images
# if relative paths are specified, then they are relative to this ad configuration file # if relative paths are specified, then they are relative to this ad configuration file
images: images:

View File

@@ -469,13 +469,15 @@ class KleinanzeigenBot(SeleniumMixin):
self.__set_category(ad_file, ad_cfg) self.__set_category(ad_file, ad_cfg)
############################# #############################
# set shipping type/costs # set shipping type/options/costs
############################# #############################
if ad_cfg["shipping_type"] == "PICKUP": if ad_cfg["shipping_type"] == "PICKUP":
try: try:
self.web_click(By.XPATH, '//*[contains(@class, "ShippingPickupSelector")]//label[text()[contains(.,"Nur Abholung")]]/input[@type="radio"]') self.web_click(By.XPATH, '//*[contains(@class, "ShippingPickupSelector")]//label[text()[contains(.,"Nur Abholung")]]/input[@type="radio"]')
except NoSuchElementException as ex: except NoSuchElementException as ex:
LOG.debug(ex, exc_info = True) LOG.debug(ex, exc_info = True)
elif ad_cfg["shipping_options"]:
self.__set_shipping_options(ad_cfg)
elif ad_cfg["shipping_costs"]: elif ad_cfg["shipping_costs"]:
try: try:
self.web_click(By.XPATH, '//*[contains(@class, "ShippingOption")]//input[@type="radio"]') self.web_click(By.XPATH, '//*[contains(@class, "ShippingOption")]//input[@type="radio"]')
@@ -495,6 +497,16 @@ class KleinanzeigenBot(SeleniumMixin):
if safe_get(ad_cfg, "price"): if safe_get(ad_cfg, "price"):
self.web_input(By.XPATH, "//input[@id='post-ad-frontend-price' or @id='micro-frontend-price' or @id='pstad-price']", ad_cfg["price"]) self.web_input(By.XPATH, "//input[@id='post-ad-frontend-price' or @id='micro-frontend-price' or @id='pstad-price']", ad_cfg["price"])
#############################
# set sell_directly
#############################
sell_directly = ad_cfg["sell_directly"]
if sell_directly and ad_cfg["shipping_type"] == "SHIPPING" and ad_cfg["shipping_options"] and price_type in {"FIXED", "NEGOTIABLE"}:
try:
self.web_click(By.XPATH, '//*[contains(@class, "BuyNowSection")]//span[contains(@class, "Toggle--Slider")]')
except NoSuchElementException as ex:
LOG.debug(ex, exc_info = True)
############################# #############################
# set description # set description
############################# #############################
@@ -609,6 +621,43 @@ class KleinanzeigenBot(SeleniumMixin):
raise NoSuchElementException(f"Failed to set special attribute [{special_attribute_key}]") from ex raise NoSuchElementException(f"Failed to set special attribute [{special_attribute_key}]") from ex
LOG.debug("Successfully set attribute field [%s] to [%s]...", special_attribute_key, special_attribute_value) LOG.debug("Successfully set attribute field [%s] to [%s]...", special_attribute_key, special_attribute_value)
def __set_shipping_options(self, ad_cfg: dict[str, Any]) -> None:
try:
shipping_option_mapping = {
"DHL_2": ("Klein", "Paket 2 kg"),
"Hermes_Päckchen": ("Klein", "Päckchen"),
"Hermes_S": ("Klein", "S-Paket"),
"DHL_5": ("Mittel", "Paket 5 kg"),
"Hermes_M": ("Mittel", "M-Paket"),
"DHL_10": ("Mittel", "Paket 10 kg"),
"DHL_31,5": ("Groß", "Paket 31,5 kg"),
"Hermes_L": ("Groß", "L-Paket"),
}
try:
mapped_shipping_options = [shipping_option_mapping[option] for option in ad_cfg["shipping_options"]]
shipping_sizes, shipping_packages = zip(*mapped_shipping_options)
except KeyError as ex:
raise KeyError(f"Unknown shipping option(s), please refer to the documentation/README: {ad_cfg['shipping_options']}") from ex
unique_shipping_sizes = set(shipping_sizes)
if len(unique_shipping_sizes) > 1:
raise ValueError("You can only specify shipping options for one package size!")
shipping_size, = unique_shipping_sizes
self.web_click(By.XPATH, f'//*[contains(@class, "ShippingOption")]//input[@type="radio" and @data-testid="{shipping_size}"]')
for shipping_package in shipping_packages:
self.web_click(
By.XPATH,
'//*[contains(@class, "CarrierOptionsPopup")]'
'//*[contains(@class, "CarrierOption")]'
f'//input[@type="checkbox" and @data-testid="{shipping_package}"]'
)
self.web_click(By.XPATH, '//*[contains(@class, "ReactModalPortal")]//button[.//*[text()[contains(.,"Weiter")]]]')
except NoSuchElementException as ex:
LOG.debug(ex, exc_info = True)
def __upload_images(self, ad_cfg: dict[str, Any]): def __upload_images(self, ad_cfg: dict[str, Any]):
LOG.info(" -> found %s", pluralize("image", ad_cfg["images"])) LOG.info(" -> found %s", pluralize("image", ad_cfg["images"]))
image_upload = self.web_find(By.XPATH, "//input[@type='file']") image_upload = self.web_find(By.XPATH, "//input[@type='file']")

View File

@@ -8,6 +8,8 @@ price:
price_type: # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE price_type: # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE
shipping_type: # one of: PICKUP, SHIPPING, NOT_APPLICABLE shipping_type: # one of: PICKUP, SHIPPING, NOT_APPLICABLE
shipping_costs: shipping_costs:
shipping_options: [] # see README.md for more information
sell_directly: # requires shipping_options to take effect
images: [] images: []
contact: contact:
name: name:

View File

@@ -10,6 +10,7 @@ ad_defaults:
suffix: "" suffix: ""
price_type: NEGOTIABLE # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE price_type: NEGOTIABLE # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE
shipping_type: SHIPPING # one of: PICKUP, SHIPPING, NOT_APPLICABLE shipping_type: SHIPPING # one of: PICKUP, SHIPPING, NOT_APPLICABLE
sell_directly: false # requires shipping_options to take effect
contact: contact:
name: "" name: ""
street: "" street: ""