mirror of
https://github.com/Second-Hand-Friends/kleinanzeigen-bot.git
synced 2026-03-12 02:31:45 +01:00
ADD ability to select shipping packages and sell directly
This commit is contained in:
committed by
Sebastian Thomschke
parent
664c0dfc7f
commit
e483c003d0
17
README.md
17
README.md
@@ -232,6 +232,7 @@ ad_defaults:
|
||||
price_type: NEGOTIABLE # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE
|
||||
shipping_type: SHIPPING # one of: PICKUP, SHIPPING, NOT_APPLICABLE
|
||||
shipping_costs: # e.g. 2.95
|
||||
sell_directly: false # requires shipping_options to take effect
|
||||
contact:
|
||||
name: ""
|
||||
street: ""
|
||||
@@ -295,6 +296,22 @@ special_attributes:
|
||||
shipping_type: # one of: PICKUP, SHIPPING, NOT_APPLICABLE
|
||||
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
|
||||
# if relative paths are specified, then they are relative to this ad configuration file
|
||||
images:
|
||||
|
||||
@@ -469,13 +469,15 @@ class KleinanzeigenBot(SeleniumMixin):
|
||||
self.__set_category(ad_file, ad_cfg)
|
||||
|
||||
#############################
|
||||
# set shipping type/costs
|
||||
# set shipping type/options/costs
|
||||
#############################
|
||||
if ad_cfg["shipping_type"] == "PICKUP":
|
||||
try:
|
||||
self.web_click(By.XPATH, '//*[contains(@class, "ShippingPickupSelector")]//label[text()[contains(.,"Nur Abholung")]]/input[@type="radio"]')
|
||||
except NoSuchElementException as ex:
|
||||
LOG.debug(ex, exc_info = True)
|
||||
elif ad_cfg["shipping_options"]:
|
||||
self.__set_shipping_options(ad_cfg)
|
||||
elif ad_cfg["shipping_costs"]:
|
||||
try:
|
||||
self.web_click(By.XPATH, '//*[contains(@class, "ShippingOption")]//input[@type="radio"]')
|
||||
@@ -495,6 +497,16 @@ class KleinanzeigenBot(SeleniumMixin):
|
||||
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"])
|
||||
|
||||
#############################
|
||||
# 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
|
||||
#############################
|
||||
@@ -609,6 +621,43 @@ class KleinanzeigenBot(SeleniumMixin):
|
||||
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)
|
||||
|
||||
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]):
|
||||
LOG.info(" -> found %s", pluralize("image", ad_cfg["images"]))
|
||||
image_upload = self.web_find(By.XPATH, "//input[@type='file']")
|
||||
|
||||
@@ -8,6 +8,8 @@ price:
|
||||
price_type: # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE
|
||||
shipping_type: # one of: PICKUP, SHIPPING, NOT_APPLICABLE
|
||||
shipping_costs:
|
||||
shipping_options: [] # see README.md for more information
|
||||
sell_directly: # requires shipping_options to take effect
|
||||
images: []
|
||||
contact:
|
||||
name:
|
||||
|
||||
@@ -10,6 +10,7 @@ ad_defaults:
|
||||
suffix: ""
|
||||
price_type: NEGOTIABLE # one of: FIXED, NEGOTIABLE, GIVE_AWAY, NOT_APPLICABLE
|
||||
shipping_type: SHIPPING # one of: PICKUP, SHIPPING, NOT_APPLICABLE
|
||||
sell_directly: false # requires shipping_options to take effect
|
||||
contact:
|
||||
name: ""
|
||||
street: ""
|
||||
|
||||
Reference in New Issue
Block a user