modified: amazon/__pycache__/approve.cpython-39.pyc

modified:   amazon/__pycache__/asin_status.cpython-39.pyc
	modified:   amazon/__pycache__/del_brand.cpython-39.pyc
	modified:   amazon/__pycache__/match_action.cpython-39.pyc
	modified:   amazon/__pycache__/price_match.cpython-39.pyc
	modified:   amazon/approve.py
	modified:   amazon/asin_status.py
	modified:   amazon/del_brand.py
	modified:   amazon/match_action.py
	modified:   amazon/price_match.py
	modified:   main.py
This commit is contained in:
铭坤
2026-04-30 10:52:52 +08:00
parent 8c5edc6ad6
commit 83bc90ecf2
11 changed files with 473 additions and 297 deletions

View File

@@ -1082,6 +1082,68 @@ class ApproveTask:
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,81 +1170,92 @@ 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:

View File

@@ -537,8 +537,6 @@ class StatusTask:
self.log(f"切换页面失败重试退出", "ERROR")
return
# 处理所有需要审批的商品通过yield获取结果
# 指定 asin

View File

@@ -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):

View File

@@ -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,86 +555,104 @@ 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

View File

@@ -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:
return rank1_price - 0.3
# 逻辑更清晰的写法:第一名价格 - (差价 + 对应阶梯值)
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
return rank1_price - 0.3 # 默认按第一名减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以上跳过
@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)
# 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)

View File

@@ -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
)