diff --git a/app/amazon/__pycache__/approve.cpython-39.pyc b/app/amazon/__pycache__/approve.cpython-39.pyc index d86cdd4..84f4d46 100644 Binary files a/app/amazon/__pycache__/approve.cpython-39.pyc and b/app/amazon/__pycache__/approve.cpython-39.pyc differ diff --git a/app/amazon/__pycache__/asin_status.cpython-39.pyc b/app/amazon/__pycache__/asin_status.cpython-39.pyc index a4ef2a0..370790b 100644 Binary files a/app/amazon/__pycache__/asin_status.cpython-39.pyc and b/app/amazon/__pycache__/asin_status.cpython-39.pyc differ diff --git a/app/amazon/__pycache__/del_brand.cpython-39.pyc b/app/amazon/__pycache__/del_brand.cpython-39.pyc index 213f2a3..6eeeac4 100644 Binary files a/app/amazon/__pycache__/del_brand.cpython-39.pyc and b/app/amazon/__pycache__/del_brand.cpython-39.pyc differ diff --git a/app/amazon/__pycache__/match_action.cpython-39.pyc b/app/amazon/__pycache__/match_action.cpython-39.pyc index 39ebc21..726e545 100644 Binary files a/app/amazon/__pycache__/match_action.cpython-39.pyc and b/app/amazon/__pycache__/match_action.cpython-39.pyc differ diff --git a/app/amazon/__pycache__/price_match.cpython-39.pyc b/app/amazon/__pycache__/price_match.cpython-39.pyc index 6dd70c0..818c7a4 100644 Binary files a/app/amazon/__pycache__/price_match.cpython-39.pyc and b/app/amazon/__pycache__/price_match.cpython-39.pyc differ diff --git a/app/amazon/approve.py b/app/amazon/approve.py index db65147..b18d407 100644 --- a/app/amazon/approve.py +++ b/app/amazon/approve.py @@ -1081,7 +1081,69 @@ class ApproveTask: if shop_name in runing_shop: del runing_shop[shop_name] self.log(f"店铺 {shop_name} 已从执行列表中移除") - + + def action_init(self,driver,country_name,shop_name,risk_listing_filter): + """切换到指定国际 -> 页面 -》 筛选好""" + max_retries = 5 + switch_success = False + switch_success_pg = False + search_success = False + sku_ls = [] + for retry in range(max_retries): + try: + self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") + if retry > 2: + # 刷新不行就重新打开店铺 + self.log("重试前重新打开店铺...") + try: + driver.close_store() + time.sleep(3) + driver.open_shop(shop_name) + except Exception as e: + self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") + # 如果不是第一次尝试,先刷新页面 + if retry > 0: + self.log("重试前刷新页面...") + try: + driver.tab.refresh() + time.sleep(3) + except Exception as e: + self.log(f"刷新页面失败: {str(e)}", "WARNING") + + switch_success = driver.SwitchingCountries(country_name) + if switch_success: + self.log(f"成功切换到国家 {country_name}") + + # 切换到库存管理页面 + driver.SwitchPage() + self.log(f"已切换到库存管理页面") + time.sleep(3) + switch_success_pg = True + + sku_ls = driver.search(filter_type=risk_listing_filter) + search_success = True + self.log(f"国家 {country_name} 搜索出 {len(sku_ls)} 商品,开始处理...") + break + else: + self.log(f"切换到国家 {country_name} 失败", "WARNING") + + except Exception as e: + import traceback + self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") + self.log(traceback.format_exc(), "ERROR") + + # 如果还有重试机会,等待后继续 + if retry < max_retries - 1: + time.sleep(2) + + # 如果切换失败,直接返回 + # if not switch_success or not switch_success_pg or not search_success: + # error_message = f"切换到国家({switch_success})/库存页面({switch_success_pg})/搜索筛选到指定选项({search_success}) {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + # self.log(error_message, "ERROR") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + return switch_success,switch_success_pg,search_success,sku_ls + def process_country(self, driver: AmzoneApprove, country_code: str, task_id: int, shop_name: str, risk_listing_filter: str): """处理单个国家的审批任务 @@ -1108,87 +1170,98 @@ class ApproveTask: max_retries = 3 switch_success = False - for retry in range(max_retries): - try: - self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") - if retry > 1: - # 刷新不行就重新打开店铺 - self.log("重试前重新打开店铺...") - try: - driver.close_store() - time.sleep(3) - driver.open_shop(shop_name) - except Exception as e: - self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") - - # 如果不是第一次尝试,先刷新页面 - if retry > 0: - self.log("重试前刷新页面...") - try: - driver.tab.refresh() - time.sleep(3) - except Exception as e: - self.log(f"刷新页面失败: {str(e)}", "WARNING") - - switch_success = driver.SwitchingCountries(country_name) - if switch_success: - self.log(f"成功切换到国家 {country_name}") - break - else: - self.log(f"切换到国家 {country_name} 失败", "WARNING") - - except Exception as e: - import traceback - self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") - self.log(traceback.format_exc(), "ERROR") - - # 如果还有重试机会,等待后继续 - if retry < max_retries - 1: - time.sleep(2) - + # for retry in range(max_retries): + # try: + # self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") + # if retry > 1: + # # 刷新不行就重新打开店铺 + # self.log("重试前重新打开店铺...") + # try: + # driver.close_store() + # time.sleep(3) + # driver.open_shop(shop_name) + # except Exception as e: + # self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") + # + # # 如果不是第一次尝试,先刷新页面 + # if retry > 0: + # self.log("重试前刷新页面...") + # try: + # driver.tab.refresh() + # time.sleep(3) + # except Exception as e: + # self.log(f"刷新页面失败: {str(e)}", "WARNING") + # + # switch_success = driver.SwitchingCountries(country_name) + # if switch_success: + # self.log(f"成功切换到国家 {country_name}") + # break + # else: + # self.log(f"切换到国家 {country_name} 失败", "WARNING") + # + # except Exception as e: + # import traceback + # self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") + # self.log(traceback.format_exc(), "ERROR") + # + # # 如果还有重试机会,等待后继续 + # if retry < max_retries - 1: + # time.sleep(2) + # + # # 如果切换失败,直接返回 + # if not switch_success: + # error_message = f"切换到国家 {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + # self.log(error_message, "ERROR") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + # return + # + # # 切换到库存管理页面 + # try: + # driver.SwitchPage() + # self.log(f"已切换到库存管理页面") + # except Exception as e: + # import traceback + # self.log(f"切换页面失败: {str(e)}", "ERROR") + # self.log(traceback.format_exc(), "ERROR") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + # return + # + # # 搜索需要审批的商品,最多重试3次 + # sku_ls = [] + # for retry in range(max_retries): + # try: + # self.log(f"尝试搜索需要审批的商品 (第 {retry + 1}/{max_retries} 次)") + # sku_ls = driver.search(filter_type=risk_listing_filter) + # break + # except Exception as e: + # self.log(f"搜索商品异常: {str(e)}", "ERROR") + # if retry < max_retries - 1: + # try: + # driver.tab.refresh() + # time.sleep(3) + # except Exception as refresh_error: + # self.log(f"刷新页面失败: {str(refresh_error)}", "WARNING") + # + max_retries = 5 + switch_success, switch_success_pg, search_success,sku_ls = self.action_init(driver, country_name, shop_name, + risk_listing_filter) # 如果切换失败,直接返回 - if not switch_success: - error_message = f"切换到国家 {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + if not switch_success or not switch_success_pg or not search_success: + error_message = f"切换到国家({switch_success})/库存页面({switch_success_pg})/搜索筛选到指定选项({search_success}) {country_name} 失败,已重试 {max_retries} 次,跳过该国家" self.log(error_message, "ERROR") if task_id in runing_task: runing_task[task_id]["processed_countries"] += 1 return - - # 切换到库存管理页面 - try: - driver.SwitchPage() - self.log(f"已切换到库存管理页面") - except Exception as e: - import traceback - self.log(f"切换页面失败: {str(e)}", "ERROR") - self.log(traceback.format_exc(), "ERROR") - if task_id in runing_task: - runing_task[task_id]["processed_countries"] += 1 - return - - # 搜索需要审批的商品,最多重试3次 - sku_ls = [] - for retry in range(max_retries): - try: - self.log(f"尝试搜索需要审批的商品 (第 {retry + 1}/{max_retries} 次)") - sku_ls = driver.search(filter_type=risk_listing_filter) - break - except Exception as e: - self.log(f"搜索商品异常: {str(e)}", "ERROR") - if retry < max_retries - 1: - try: - driver.tab.refresh() - time.sleep(3) - except Exception as refresh_error: - self.log(f"刷新页面失败: {str(refresh_error)}", "WARNING") - - # 如果没有需要审批的商品,直接返回 + + # # 如果没有需要审批的商品,直接返回 if len(sku_ls) == 0: self.log(f"国家 {country_name} 没有需要审批的商品") if task_id in runing_task: runing_task[task_id]["processed_countries"] += 1 return - + self.log(f"国家 {country_name} 有 {len(sku_ls)} 个需要审批的商品,开始处理...") # 处理所有需要审批的商品(通过yield获取结果) diff --git a/app/amazon/asin_status.py b/app/amazon/asin_status.py index 9160f21..8a5ad46 100644 --- a/app/amazon/asin_status.py +++ b/app/amazon/asin_status.py @@ -537,8 +537,6 @@ class StatusTask: self.log(f"切换页面失败重试退出", "ERROR") return - - # 处理所有需要审批的商品(通过yield获取结果) # 指定 asin diff --git a/app/amazon/del_brand.py b/app/amazon/del_brand.py index af7c8ee..884b093 100644 --- a/app/amazon/del_brand.py +++ b/app/amazon/del_brand.py @@ -8,11 +8,12 @@ import json import os from typing import Literal -from DrissionPage import Chromium +from DrissionPage import Chromium,ChromiumOptions from DrissionPage.common import By from DrissionPage._pages.chromium_tab import ChromiumTab + def kill_process(version: Literal["v5", "v6"]): """杀紫鸟客户端进程(独立函数版本)""" driver = ZiniaoDriver({}) @@ -205,7 +206,11 @@ class ZiniaoDriver: Returns: Chromium: DrissionPage浏览器实例 """ - browser = Chromium(port) + co = ChromiumOptions() + # 设置不加载图片、静音 + co.set_local_port(port) + co.no_imgs(True).mute(True) + browser = Chromium(co) return browser def start_client(self): diff --git a/app/amazon/match_action.py b/app/amazon/match_action.py index 7745f20..07f2516 100644 --- a/app/amazon/match_action.py +++ b/app/amazon/match_action.py @@ -468,6 +468,70 @@ class MatchTak: del runing_shop[shop_name] self.log(f"店铺 {shop_name} 已从执行列表中移除") + def action_init(self,driver,country_name,shop_name,risk_listing_filter): + """切换到指定国际 -> 页面 -》 筛选好""" + max_retries = 5 + switch_success = False + switch_success_pg = False + search_success = False + sku_ls = [] + for retry in range(max_retries): + try: + self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") + if retry > 2: + # 刷新不行就重新打开店铺 + self.log("重试前重新打开店铺...") + try: + driver.close_store() + time.sleep(3) + driver.open_shop(shop_name) + except Exception as e: + self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") + # 如果不是第一次尝试,先刷新页面 + if retry > 0: + self.log("重试前刷新页面...") + try: + driver.tab.refresh() + time.sleep(3) + except Exception as e: + self.log(f"刷新页面失败: {str(e)}", "WARNING") + + switch_success = driver.SwitchingCountries(country_name) + if switch_success: + self.log(f"成功切换到国家 {country_name}") + + # 切换到库存管理页面 + driver.SwitchPage() + self.log(f"已切换到库存管理页面") + time.sleep(3) + switch_success_pg = True + + sku_ls = driver.search(filter_type=risk_listing_filter) + search_success = True + self.log(f"国家 {country_name} 搜索出 {len(sku_ls)} 商品,开始处理...") + break + else: + self.log(f"切换到国家 {country_name} 失败", "WARNING") + + except Exception as e: + import traceback + self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") + self.log(traceback.format_exc(), "ERROR") + + # 如果还有重试机会,等待后继续 + if retry < max_retries - 1: + time.sleep(2) + + # 如果切换失败,直接返回 + # if not switch_success or not switch_success_pg or not search_success: + # error_message = f"切换到国家({switch_success})/库存页面({switch_success_pg})/搜索筛选到指定选项({search_success}) {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + # self.log(error_message, "ERROR") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + return switch_success,switch_success_pg,search_success,sku_ls + + + def process_country(self, driver: AmzoneMatchAction, country_code: str, task_id: int, shop_name: str, risk_listing_filter: str,limit:str=None): """处理单个国家的审批任务 @@ -491,90 +555,108 @@ class MatchTak: runing_task[task_id]["current_country"] = country_name # 切换国家,最多重试3次 - max_retries = 3 - switch_success = False - - for retry in range(max_retries): - try: - self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") - if retry > 1: - # 刷新不行就重新打开店铺 - self.log("重试前重新打开店铺...") - try: - driver.close_store() - time.sleep(3) - driver.open_shop(shop_name) - except Exception as e: - self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") - - # 如果不是第一次尝试,先刷新页面 - if retry > 0: - self.log("重试前刷新页面...") - try: - driver.tab.refresh() - time.sleep(3) - except Exception as e: - self.log(f"刷新页面失败: {str(e)}", "WARNING") - - switch_success = driver.SwitchingCountries(country_name) - if switch_success: - self.log(f"成功切换到国家 {country_name}") - break - else: - self.log(f"切换到国家 {country_name} 失败", "WARNING") - - except Exception as e: - import traceback - self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") - self.log(traceback.format_exc(), "ERROR") - - # 如果还有重试机会,等待后继续 - if retry < max_retries - 1: - time.sleep(2) - + # max_retries = 3 + # switch_success = False + # + # for retry in range(max_retries): + # try: + # self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") + # if retry > 1: + # # 刷新不行就重新打开店铺 + # self.log("重试前重新打开店铺...") + # try: + # driver.close_store() + # time.sleep(3) + # driver.open_shop(shop_name) + # except Exception as e: + # self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") + # + # # 如果不是第一次尝试,先刷新页面 + # if retry > 0: + # self.log("重试前刷新页面...") + # try: + # driver.tab.refresh() + # time.sleep(3) + # except Exception as e: + # self.log(f"刷新页面失败: {str(e)}", "WARNING") + # + # switch_success = driver.SwitchingCountries(country_name) + # if switch_success: + # self.log(f"成功切换到国家 {country_name}") + # break + # else: + # self.log(f"切换到国家 {country_name} 失败", "WARNING") + # + # except Exception as e: + # import traceback + # self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") + # self.log(traceback.format_exc(), "ERROR") + # + # # 如果还有重试机会,等待后继续 + # if retry < max_retries - 1: + # time.sleep(2) + # + # # 如果切换失败,直接返回 + # if not switch_success: + # error_message = f"切换到国家 {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + # self.log(error_message, "ERROR") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + # return + # + # # 切换到库存管理页面 + # try: + # driver.SwitchPage() + # self.log(f"已切换到库存管理页面") + # except Exception as e: + # import traceback + # self.log(f"切换页面失败: {str(e)}", "ERROR") + # self.log(traceback.format_exc(), "ERROR") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + # return + # + # # 搜索需要审批的商品,最多重试3次 + # sku_ls = [] + # for retry in range(max_retries): + # try: + # self.log(f"尝试搜索匹配操作商品 (第 {retry + 1}/{max_retries} 次)") + # sku_ls = driver.search(filter_type=risk_listing_filter) + # break + # except Exception as e: + # self.log(f"搜索商品异常: {str(e)}", "ERROR") + # if retry < max_retries - 1: + # try: + # driver.tab.refresh() + # time.sleep(3) + # except Exception as refresh_error: + # self.log(f"刷新页面失败: {str(refresh_error)}", "WARNING") + # + # # 如果没有需要审批的商品,直接返回 + # if len(sku_ls) == 0: + # self.log(f"国家 {country_name} 没有搜索出的商品") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + # return + # + max_retries = 5 + switch_success, switch_success_pg, search_success, sku_ls = self.action_init(driver, country_name, shop_name, + risk_listing_filter) # 如果切换失败,直接返回 - if not switch_success: - error_message = f"切换到国家 {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + if not switch_success or not switch_success_pg or not search_success: + error_message = f"切换到国家({switch_success})/库存页面({switch_success_pg})/搜索筛选到指定选项({search_success}) {country_name} 失败,已重试 {max_retries} 次,跳过该国家" self.log(error_message, "ERROR") if task_id in runing_task: runing_task[task_id]["processed_countries"] += 1 return - - # 切换到库存管理页面 - try: - driver.SwitchPage() - self.log(f"已切换到库存管理页面") - except Exception as e: - import traceback - self.log(f"切换页面失败: {str(e)}", "ERROR") - self.log(traceback.format_exc(), "ERROR") - if task_id in runing_task: - runing_task[task_id]["processed_countries"] += 1 - return - - # 搜索需要审批的商品,最多重试3次 - sku_ls = [] - for retry in range(max_retries): - try: - self.log(f"尝试搜索匹配操作商品 (第 {retry + 1}/{max_retries} 次)") - sku_ls = driver.search(filter_type=risk_listing_filter) - break - except Exception as e: - self.log(f"搜索商品异常: {str(e)}", "ERROR") - if retry < max_retries - 1: - try: - driver.tab.refresh() - time.sleep(3) - except Exception as refresh_error: - self.log(f"刷新页面失败: {str(refresh_error)}", "WARNING") - - # 如果没有需要审批的商品,直接返回 + + # # 如果没有需要审批的商品,直接返回 if len(sku_ls) == 0: - self.log(f"国家 {country_name} 没有搜索出的商品") + self.log(f"国家 {country_name} 没有需要审批的商品") if task_id in runing_task: runing_task[task_id]["processed_countries"] += 1 return - + self.log(f"国家 {country_name} 搜索出 {len(sku_ls)} 商品,开始处理...") # 处理所有需要审批的商品(通过yield获取结果) diff --git a/app/amazon/price_match.py b/app/amazon/price_match.py index 4ce5d2b..fc57491 100644 --- a/app/amazon/price_match.py +++ b/app/amazon/price_match.py @@ -16,28 +16,32 @@ from amazon.tool import show_notification,get_shop_info,remove_special_character from config import runing_task, runing_shop,base_dir,DELETE_BRAND_API_BASE - class RepricingLogic: @staticmethod def situation_1_general_decrease(my_price, rank1_price, is_first_time=False): """ 情况1:常规递减跟价 (最左侧独立长图块) - 当不是自己购物车时,按总价当作第一名递减。 """ if is_first_time: return rank1_price - 0.3 - diff = my_price - rank1_price + # 这里的 diff 算出的是一个正数,代表“我比第一名低多少” + diff = rank1_price - my_price - # 精简了原图中长串的阶梯逻辑 + # 如果当前价格高于或等于第一名,默认按照第一名减0.3处理 + if diff <= 0: + return rank1_price - 0.3 + + # 逻辑更清晰的写法:第一名价格 - (差价 + 对应阶梯值) + # 例如差价0.7,则相当于 第一名价格 - (0.7 + 0.5) = 第一名价格 - 1.2 if diff <= 0.3: - return rank1_price - 0.5 + return rank1_price - (diff + 0.5) elif diff <= 0.8: - return rank1_price - 0.7 + return rank1_price - (diff + 0.7) elif diff <= 10.5: - # 0.8 到 10.5 之间,原图逻辑全部是“减1” - return rank1_price - 1.0 + # 0.8 到 10.5 之间全部是在减1 + return rank1_price - (diff + 1.0) else: return None # 相差10.5以上,跳过 @@ -45,55 +49,56 @@ class RepricingLogic: def situation_2_own_buybox(my_price, rank2_price): """ 情况2:已经是自己购物车 - 逻辑:判断与第二名的差价,如果拉开足够差距,则稍微降一点点(减0.5)保持优势,防止卖太便宜。 """ diff = rank2_price - my_price - # 1. 绝对差价2欧以上 if diff >= 2.0: return rank2_price - 0.3 - # 2. 产品售价区间判定 (是否要提高价格) if (20 <= my_price < 30 and diff >= 4) or \ (30 <= my_price < 60 and diff >= 8) or \ (60 <= my_price <= 150 and diff >= 15): - return rank2_price - 0.3 # 满足区间大差价,提价至第二名之下 + return rank2_price - 0.3 - return my_price # 不满足条件则保持原价 + return my_price @staticmethod def situation_3_not_own_buybox(my_price, rank1_price): """ - 情况3:不是自己购物车 (常规情况) + 情况3:不是自己购物车 (除Amazon US外) """ - diff = my_price - rank1_price + diff = rank1_price - my_price - if diff <= 0.3: - return rank1_price - 0.5 - elif 0.5 <= diff <= 0.8: - return rank1_price - 0.7 - elif 0.8 < diff <= 2.5: - return rank1_price - 1.0 - elif diff > 2.5: # 2.5-3.5以上跳过 - return None + if diff <= 0: + return rank1_price - 0.3 + + # 逻辑更清晰的写法:第一名价格 - (差价 + 对应阶梯值) + if diff <= 0.3: + return rank1_price - (diff + 0.5) + elif diff <= 0.8: + return rank1_price - (diff + 0.7) + elif diff <= 2.5: + return rank1_price - (diff + 1.0) + else: + return None # 2.5-3.5以上跳过 - return rank1_price - 0.3 # 默认按第一名减0.3 - @staticmethod def situation_4_encounter_amz_us_1st(my_price, amz_us_price): """ - 情况4:第一名是 Amazon US 卖家 + 情况4:遇到第一名是 Amazon US 卖家 """ - diff = my_price - amz_us_price + diff = amz_us_price - my_price - if diff <= 3: - return amz_us_price - 2 - elif 4 <= diff <= 6: + if diff <= 0: return amz_us_price - 3 - elif 8 <= diff <= 12: - return None # 跳过不跟价 - return amz_us_price - 3 # 默认直接按照 Amazon US 减去3 + # 逻辑更清晰的写法:第一名价格 - (差价 + 对应阶梯值) + if diff <= 3: + return amz_us_price - (diff + 2) + elif diff <= 6: + return amz_us_price - (diff + 3) + else: + return None # 超过6直接跳过 @staticmethod def situation_5_im_1st_amz_us_2nd(my_price, amz_us_price): @@ -103,7 +108,7 @@ class RepricingLogic: diff = amz_us_price - my_price if diff <= 7: - return None # 相差5以内跳过 (保持原价) + return None # 相差7以内跳过 (保持原价) else: return amz_us_price - 5 @@ -133,16 +138,6 @@ def calculate_target_price( price_col = recommended_price + recommended_shipping print(f"【紫鸟后台价格】{is_my_buybox} 推荐价格: {recommended_price},推荐运费: {recommended_shipping},总和: {price_col}") return RepricingLogic.situation_1_general_decrease(my_price,price_col,is_my_buybox) - # backend_base_price = recommended_price - # backend_shipping = recommended_shipping - # total_price = backend_base_price + backend_shipping - # - # if is_my_buybox: - # # 🌟【逻辑更新】:如果是自己的购物车,直接跳过,不做任何价格调整 - # return None - # else: - # # 不是自己的购物车:直接将紫鸟的总和作为"第一名"价格,强制抛入阶梯跟价逻辑 - # return calculate_standard_competitor_pricing(my_price, total_price) # # 第一名是自己, 第二名 Amazon US 卖家 的情况 shop_name_1 = front_end_data.get("top_sellers")[0].get("shop_name") @@ -152,13 +147,11 @@ def calculate_target_price( return RepricingLogic.situation_5_im_1st_amz_us_2nd(my_price,price_2) # --- Step 3: 常规核心分流逻辑 (如果没有紫鸟后台数据) --- - # 分支 A:第一名是 Amazon US 卖家 (特殊强敌优先) price_1 = float(front_end_data.get("top_sellers")[0].get("price")) # 实际第一名价格 if "Amazon" in shop_name_1: return RepricingLogic.situation_4_encounter_amz_us_1st(my_price,price_1) - # 分支 B:不是 Amazon US,且目前是自己的购物车 elif is_my_buybox: price_2 = float(front_end_data.get("top_sellers")[1].get("price")) # 实际第二名价格 @@ -650,6 +643,13 @@ class AmzonePriceMatch(AmamzonBase): print(f"【{self.mark_name}】获取到 {len(sku_ls)}") if len(sku_ls) == 0: + if mode == "asin": + print(f"asin 模式查询不到,{asin}") + yield (asin, { + "statu": "查询不到" + }) + break + retry_num += 1 print(f"没有获取到 ASIN 商品,重试{retry_num}/{max_retry_num}") self.tab.refresh() @@ -680,19 +680,16 @@ class AmzonePriceMatch(AmamzonBase): bottom_price = f"{sum(split_currency_values(bottom_price_text))}" except Exception as e: print("最低价提取失败",e) + current_price_ele = sku_ele.eles('xpath:.//b[text()="价格"]/../..//kat-input',timeout=5) if len(current_price_ele) > 0: current_price = current_price_ele[0].attr("value") print("获取到当前价格为 ->",current_price) # 如果紫鸟里当前价格低于最低价则删除,否则跳过 - if mode == "status" and miniprice_info.get(asin): + # if mode == "status" and miniprice_info.get(asin): + if miniprice_info.get(asin): backend_price = float(miniprice_info.get(asin)) if float(current_price) <= backend_price: - # yield (asin, { - # "statu": "删除(当前价格低于最低价)", - # "deleteSkipAsin": True, - # "removeAsin": asin, - # }) yield (asin, { "statu": "跳过(当前价格低于或等于最低价)", "currentPrice": current_price, @@ -764,6 +761,9 @@ class AmzonePriceMatch(AmamzonBase): print(asin,"-->>",f"【逻辑计算后的价格】",adjust_prices) if adjust_prices is not None and adjust_prices != float(current_price): #修改价格 + print("准备填入的原始值:",adjust_prices) + adjust_prices = round(adjust_prices, 2) + print("保留两位小数后的::",adjust_prices) self.tab.actions.click(current_price_ele[0]) time.sleep(1) current_price_ele[0].input(f"{adjust_prices}", clear=True) @@ -784,12 +784,12 @@ class AmzonePriceMatch(AmamzonBase): "statu" : "改价成功", "currentPrice" : current_price, "recommendedPrice" : f"{recommendedPrice}", - "minimumPrice" : bottom_price, #最低价格 + "minimumPrice" : f"{miniprice_info.get(asin)}" if miniprice_info.get(asin) else "",#bottom_price, #最低价格 "firstPlace": price_1, "secondPlace": price_2, "cartShopName" : cartShopName, "shippingFee" : f"{shipping_fee}", - "priceChangeStatus" : f"{adjust_prices}", + "priceChangePrice" : f"{adjust_prices}", "priceChangeStatus" : "改价成功", }) else: @@ -803,12 +803,14 @@ class AmzonePriceMatch(AmamzonBase): "statu": "跳过,无需改价", "currentPrice": current_price, "recommendedPrice": f"{recommendedPrice}", - "minimumPrice": bottom_price, # 最低价格 + # "minimumPrice": bottom_price, # 最低价格 + "minimumPrice": f"{miniprice_info.get(asin)}" if miniprice_info.get(asin) else "", "firstPlace": price_1, "secondPlace": price_2, "cartShopName": cartShopName, "shippingFee": f"{shipping_fee}", "priceChangeStatus": "跳过,无需改价", + "priceChangePrice": f"{adjust_prices}".replace("None",""), }) already_asin.add(asin) @@ -1029,6 +1031,68 @@ class PriceTask: return driver return driver + def action_init(self,driver,country_name,shop_name,risk_listing_filter): + """切换到指定国际 -> 页面 -》 筛选好""" + max_retries = 5 + switch_success = False + switch_success_pg = False + search_success = False + sku_ls = [] + for retry in range(max_retries): + try: + self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") + if retry > 2: + # 刷新不行就重新打开店铺 + self.log("重试前重新打开店铺...") + try: + driver.close_store() + time.sleep(3) + driver.open_shop(shop_name) + except Exception as e: + self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") + # 如果不是第一次尝试,先刷新页面 + if retry > 0: + self.log("重试前刷新页面...") + try: + driver.tab.refresh() + time.sleep(3) + except Exception as e: + self.log(f"刷新页面失败: {str(e)}", "WARNING") + + switch_success = driver.SwitchingCountries(country_name) + if switch_success: + self.log(f"成功切换到国家 {country_name}") + + # 切换到库存管理页面 + driver.SwitchPage() + self.log(f"已切换到库存管理页面") + time.sleep(3) + switch_success_pg = True + + sku_ls = driver.search(filter_type=risk_listing_filter) + search_success = True + self.log(f"国家 {country_name} 搜索出 {len(sku_ls)} 商品,开始处理...") + break + else: + self.log(f"切换到国家 {country_name} 失败", "WARNING") + + except Exception as e: + import traceback + self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") + self.log(traceback.format_exc(), "ERROR") + + # 如果还有重试机会,等待后继续 + if retry < max_retries - 1: + time.sleep(2) + + # 如果切换失败,直接返回 + # if not switch_success or not switch_success_pg or not search_success: + # error_message = f"切换到国家({switch_success})/库存页面({switch_success_pg})/搜索筛选到指定选项({search_success}) {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + # self.log(error_message, "ERROR") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + return switch_success,switch_success_pg,search_success + def process_shop(self, shop_item: dict, country_codes: list, task_id: int, risk_listing_filter: str, user_id=None, stage_index=None, final_stage: bool = True, limit: str = None): @@ -1149,94 +1213,42 @@ class PriceTask: runing_task[task_id]["current_country"] = country_name # 切换国家,最多重试3次 - max_retries = 3 - switch_success = False - - for retry in range(max_retries): - try: - self.log(f"尝试切换到国家 {country_name} (第 {retry + 1}/{max_retries} 次)") - if retry > 1: - # 刷新不行就重新打开店铺 - self.log("重试前重新打开店铺...") - try: - driver.close_store() - time.sleep(3) - driver.open_shop(shop_name) - except Exception as e: - self.log(f"关闭重新打开店铺: {str(e)}", "WARNING") - # 如果不是第一次尝试,先刷新页面 - if retry > 0: - self.log("重试前刷新页面...") - try: - driver.tab.refresh() - time.sleep(3) - except Exception as e: - self.log(f"刷新页面失败: {str(e)}", "WARNING") - - switch_success = driver.SwitchingCountries(country_name) - if switch_success: - self.log(f"成功切换到国家 {country_name}") - break - else: - self.log(f"切换到国家 {country_name} 失败", "WARNING") - - except Exception as e: - import traceback - self.log(f"切换国家 {country_name} 异常: {str(e)}", "ERROR") - self.log(traceback.format_exc(), "ERROR") - - # 如果还有重试机会,等待后继续 - if retry < max_retries - 1: - time.sleep(2) + max_retries = 5 + switch_success,switch_success_pg,search_success = self.action_init( driver, country_name, shop_name, risk_listing_filter) # 如果切换失败,直接返回 - if not switch_success: - error_message = f"切换到国家 {country_name} 失败,已重试 {max_retries} 次,跳过该国家" + if not switch_success or not switch_success_pg or not search_success: + error_message = f"切换到国家({switch_success})/库存页面({switch_success_pg})/搜索筛选到指定选项({search_success}) {country_name} 失败,已重试 {max_retries} 次,跳过该国家" self.log(error_message, "ERROR") if task_id in runing_task: runing_task[task_id]["processed_countries"] += 1 return - # 切换到库存管理页面 - for retry in range(max_retries): - try: - driver.SwitchPage() - self.log(f"已切换到库存管理页面") - except Exception as e: - import traceback - self.log(f"切换页面失败: {str(e)}", "ERROR") - self.log(traceback.format_exc(), "ERROR") - - if retry >= max_retries-1: - if task_id in runing_task: - runing_task[task_id]["processed_countries"] += 1 - self.log(f"切换页面失败重试退出", "ERROR") - return - # 搜索需要审批的商品,最多重试3次 - sku_ls = [] - for retry in range(max_retries): - try: - self.log(f"尝试搜索匹配操作商品 (第 {retry + 1}/{max_retries} 次)") - sku_ls = driver.search(filter_type=risk_listing_filter) - break - except Exception as e: - self.log(f"搜索商品异常: {str(e)}", "ERROR") - if retry < max_retries - 1: - try: - driver.tab.refresh() - time.sleep(3) - except Exception as refresh_error: - self.log(f"刷新页面失败: {str(refresh_error)}", "WARNING") + # sku_ls = [] + # for retry in range(max_retries): + # try: + # self.log(f"尝试搜索匹配操作商品 (第 {retry + 1}/{max_retries} 次)") + # sku_ls = driver.search(filter_type=risk_listing_filter) + # break + # except Exception as e: + # self.log(f"搜索商品异常: {str(e)}", "ERROR") + # if retry < max_retries - 1: + # try: + # driver.tab.refresh() + # driver.tab.wait.doc_loaded() + # time.sleep(3) + # except Exception as refresh_error: + # self.log(f"刷新页面失败: {str(refresh_error)}", "WARNING") + # + # # 如果没有需要审批的商品,直接返回 + # if len(sku_ls) == 0: + # self.log(f"国家 {country_name} 没有搜索出的商品") + # if task_id in runing_task: + # runing_task[task_id]["processed_countries"] += 1 + # return - # 如果没有需要审批的商品,直接返回 - if len(sku_ls) == 0: - self.log(f"国家 {country_name} 没有搜索出的商品") - if task_id in runing_task: - runing_task[task_id]["processed_countries"] += 1 - return - - self.log(f"国家 {country_name} 搜索出 {len(sku_ls)} 商品,开始处理...") + self.log(f"国家 {country_name} ,开始处理...") # 处理所有需要审批的商品(通过yield获取结果) @@ -1350,13 +1362,14 @@ class PriceTask: "firstPlace": status.get("firstPlace") if status.get("firstPlace") else "", "secondPlace": status.get("secondPlace") if status.get("secondPlace") else "", "cartShopName": status.get("cartShopName") if status.get("cartShopName") else "", - "priceChangeStatus": "UPDATED", + # "priceChangeStatus": "UPDATED", "deleteSkipAsin": status.get("deleteSkipAsin",False), "removeAsin": status.get("removeAsin") if status.get("removeAsin") else "", "modifyCount": "1", "shippingFee" : status.get("shippingFee") if status.get("shippingFee") else "", "status": status.get("statu"), "priceChangeStatus" : status.get("priceChangeStatus") if status.get("priceChangeStatus") else "", + "priceChangePrice" : status.get("priceChangePrice") if status.get("priceChangePrice") else "", } ] }, @@ -1405,20 +1418,20 @@ class PriceTask: if __name__ == '__main__': # 使用示例 # user_info = { - # "company": "rongchuang123", + # "company": "尾号5578的公司115", # "username": "自动化_Robot", # "password": "#20zsg25" # } - # shop_name = "郭亚芳" - # country = "德国" + # shop_name = "刘建煌" + # country = "法国" # kill_process('v6') # driver = AmzonePriceMatch(user_info) # browser = driver.open_shop(shop_name) # sw_suc = driver.SwitchingCountries(country) # driver.SwitchPage() # risk_listing_filter = "Active" - # _shopMallName = "yafang123" - # ap_asin ="B0BTHBJDKG" + # _shopMallName = "Jianhuang 888" + # ap_asin ="B0F25Y52PH" # skip_asin = [] # for _ in range(3): # try: @@ -1436,14 +1449,19 @@ if __name__ == '__main__': # print(f"ASIN {asin} 的处理结果: {status}") # print("已完成操作") - front_end_data = {'top_sellers': [{'rank': 1, 'price': '50.24', 'stock': '26', 'shop_name': 'yafang123'}, {'rank': 2, 'price': '44.35', 'stock': '100', 'shop_name': 'QinPimy'}], 'cart_seller': 'Amazon US', 'timestamp': '2026-04-27 16:17:42'} + front_end_data = {'top_sellers': [{'rank': 1, 'price': '52.51', 'stock': '100', 'shop_name': 'Amazon US'}, {'rank': 2, 'price': '62.58', 'stock': '30', 'shop_name': 'Amazon US'}], 'cart_seller': 'Jianhuang 888', 'timestamp': '2026-04-30 09:52:49'} - current_Price = 44.35 - current_shop_name = "yafang123" - recommended_price = 44.35 + current_Price = 52.51 + current_shop_name = "Jianhuang 888" + recommended_price = 52.51 recommended_shipping =0.0 res = calculate_target_price( front_end_data, current_Price, current_shop_name, recommended_price, recommended_shipping ) - print(res) \ No newline at end of file + print(res) + + + # task_data = {'type': 'price-track-run', 'ts': 1777388166302, 'data': {'task_id': 4892, 'result_id': 6685, 'shop_name': '魏振峰', 'shop_id': '27543917795757', 'platform': '亚马逊', 'company_name': 'rongchuang123', 'shop_mall_name': 'WEIZHENFENG168', 'matched': True, 'match_status': 'MATCHED', 'match_message': None, 'success': False, 'error': None, 'output_filename': None, 'download_url': None, 'task_status': 'RUNNING', 'loop_run_id': 168, 'round_index': 1, 'country_codes': ['DE', 'UK', 'FR', 'IT', 'ES'], 'mode': 'asin', 'skip_asins': {}, 'skip_asins_by_country': {}, 'skip_asin_details_by_country': {}, 'minimum_price_by_country_and_asin': {'DE': {'B0CFY5M3XJ': '38', 'B0DSJGJBWV': '9'}, 'UK': {'B0G2LPSGP5': '30', 'B0G1LY2K8L': '10'}}, 'skip_asin_delete_policy': {'enabled': False, 'mode': 'NONE', 'deleteWhenPriceBelowMinimum': False, 'compareField': 'price', 'thresholdField': 'minimumPrice', 'target': 'skip_asin', 'source': 'frontend-price-track'}, 'delete_skip_asin_when_price_below_minimum': False, 'deleteSkipAsinWhenPriceBelowMinimum': False, 'asin_rows_by_country': {'DE': [{'shopMallName': '', 'asin': 'B0CFY5M3XJ', 'price': '', 'recommendedPrice': '', 'minimumPrice': '38', 'firstPlace': '', 'secondPlace': '', 'cartShopName': '', 'priceChangeStatus': '', 'modifyCount': '', 'status': ''}, {'shopMallName': '', 'asin': 'B0DSJGJBWV', 'price': '', 'recommendedPrice': '', 'minimumPrice': '9', 'firstPlace': '', 'secondPlace': '', 'cartShopName': '', 'priceChangeStatus': '', 'modifyCount': '', 'status': ''}], 'UK': [{'shopMallName': '', 'asin': 'B0G2LPSGP5', 'price': '', 'recommendedPrice': '', 'minimumPrice': '30', 'firstPlace': '', 'secondPlace': '', 'cartShopName': '', 'priceChangeStatus': '', 'modifyCount': '', 'status': ''}, {'shopMallName': '', 'asin': 'B0G1LY2K8L', 'price': '', 'recommendedPrice': '', 'minimumPrice': '10', 'firstPlace': '', 'secondPlace': '', 'cartShopName': '', 'priceChangeStatus': '', 'modifyCount': '', 'status': ''}]}, 'taskId': 4892, 'resultId': 6685, 'shopName': '魏振峰', 'shopId': '27543917795757', 'platformName': '亚马逊', 'companyName': 'rongchuang123', 'shopMallName': 'WEIZHENFENG168', 'matchStatus': 'MATCHED', 'matchMessage': None, 'outputFilename': None, 'downloadUrl': None, 'taskStatus': 'RUNNING', 'loopRunId': 168, 'roundIndex': 1}} + # price_cls = PriceTask(user_info) + # price_cls.process_task(task_data) \ No newline at end of file diff --git a/app/main.py b/app/main.py index cd6403f..148cb5f 100644 --- a/app/main.py +++ b/app/main.py @@ -438,7 +438,7 @@ def main(): window.expose(api.close, api.minimize, api.maximize, api.toggle_maximize, generate_images, api.save_image, api.save_image_to_folder, api.select_folder, api.select_brand_xlsx_files, api.select_brand_folder, api.save_file_from_url, api.save_template_xlsx,api.save_template_zip,api.upload_file_to_java,api.open_external_url,api.enqueue_json,api.get_detail_del,api.save_file_from_url_new) webview.start( - debug=False, + debug=True, storage_path=cache_path, private_mode=False )