modified: amazon/__pycache__/approve.cpython-39.pyc
modified: amazon/__pycache__/del_brand.cpython-39.pyc modified: amazon/__pycache__/match_action.cpython-39.pyc modified: amazon/approve.py modified: amazon/del_brand.py modified: amazon/match_action.py new file: amazon/price_match.py modified: main.py
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,6 +2,7 @@ import time
|
|||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
from DrissionPage._pages.chromium_tab import ChromiumTab
|
from DrissionPage._pages.chromium_tab import ChromiumTab
|
||||||
|
import pyautogui
|
||||||
|
|
||||||
from config import runing_task, runing_shop
|
from config import runing_task, runing_shop
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -86,10 +87,11 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
def wait_loaded(self):
|
def wait_loaded(self):
|
||||||
# 等待加载完成
|
# 等待加载完成
|
||||||
try:
|
try:
|
||||||
load_ele = self.tab.ele(
|
load_ele = self.tab.eles(
|
||||||
'xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]//div[contains(@class,"Loader-module__loader")]|//kat-panel[@data-testid="kat-panel-ActionPanelContent"]/div[@data-f1-component]//div[contains(@class,"==")]/div[contains(@class,"==")]/span',
|
'xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]//div[contains(@class,"Loader-module__loader")]|//kat-panel[@data-testid="kat-panel-ActionPanelContent"]/div[@data-f1-component]//div[contains(@class,"==")]/div[contains(@class,"==")]/span',
|
||||||
timeout=3)
|
timeout=3)
|
||||||
load_ele.wait.deleted(timeout=5, raise_err=False)
|
if len(load_ele) > 0:
|
||||||
|
load_ele[0].wait.deleted(timeout=5, raise_err=False)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("等待加载中消失出错", e)
|
print("等待加载中消失出错", e)
|
||||||
|
|
||||||
@@ -106,67 +108,317 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
print("当前操作的tab_id",self.tab.tab_id)
|
print("当前操作的tab_id",self.tab.tab_id)
|
||||||
self.browser.close_tabs(close_tab)
|
self.browser.close_tabs(close_tab)
|
||||||
|
|
||||||
def handle_repair_product(self,tab:ChromiumTab):
|
# def handle_repair_product_old(self,tab:ChromiumTab):
|
||||||
def wait_loaded():
|
# def wait_loaded():
|
||||||
|
# # 等待加载完成
|
||||||
|
# try:
|
||||||
|
# load_ele = tab.ele(
|
||||||
|
# 'xpath://div[@class="contentWrapper"]//div[contains(@class,"==")]/span[not(node())]',
|
||||||
|
# timeout=3)
|
||||||
|
# load_ele.wait.deleted(timeout=5, raise_err=False)
|
||||||
|
# except Exception as e:
|
||||||
|
# print("等待加载中消失出错", e)
|
||||||
|
|
||||||
|
# tab.wait.doc_loaded(timeout=60,raise_err=False)
|
||||||
|
# submit_btn_ls = tab.eles('xpath://div[@id="ahd-product-policies-table"]/div//div[@data-testid="nextStepsMetricWrapper"]//kat-button[@label="提交"]',timeout=10)
|
||||||
|
# if len(submit_btn_ls) == 0:
|
||||||
|
# print("未找到提交按钮,可能页面未加载完成或者页面结构发生变化")
|
||||||
|
# # return
|
||||||
|
# for _ in range(3):
|
||||||
|
# try:
|
||||||
|
# # todo 遍历
|
||||||
|
# for index in range(len(submit_btn_ls)):
|
||||||
|
# if index > len(submit_btn_ls)-1:
|
||||||
|
# print("提交按钮数量发生变化,停止处理")
|
||||||
|
# break
|
||||||
|
|
||||||
|
# submit_btn = submit_btn_ls[index]
|
||||||
|
|
||||||
|
# # 关闭按钮
|
||||||
|
# close_x_btn = tab.eles('xpath://div[@class="flyoutPanelContent"]/span',timeout=5)
|
||||||
|
# if len(close_x_btn) > 0:
|
||||||
|
# close_x_btn[0].wait.displayed(timeout=5, raise_err=False)
|
||||||
|
# close_x_btn[0].click()
|
||||||
|
|
||||||
|
# submit_btn.wait.enabled(timeout=5, raise_err=False)
|
||||||
|
# submit_btn.click()
|
||||||
|
# time.sleep(0.5)
|
||||||
|
# self.wait_loaded()
|
||||||
|
|
||||||
|
# wait_loaded()
|
||||||
|
|
||||||
|
# need_input = tab.eles('xpath://div[@class="contentWrapper"]//kat-input[@data-testid="kat-input-dew:ump_epr_resgitration_number_title"]',timeout=5)
|
||||||
|
# if len(need_input) > 0:
|
||||||
|
# print("需要输入注册号,不符合操作要求,跳过...")
|
||||||
|
# continue
|
||||||
|
|
||||||
|
# target_title = tab.eles('xpath://div[@class="contentWrapper"]//section//h4[text()="警告和安全信息"]')
|
||||||
|
# if len(target_title) > 0:
|
||||||
|
# not_start = tab.eles('xpath://div[@class="contentWrapper"]//div[@aria-label="安全证明"]//kat-label[@text="未开始"]')
|
||||||
|
# if len(not_start) == 0:
|
||||||
|
# print("安全证明-不是未开始状态,不需要操作")
|
||||||
|
# continue
|
||||||
|
|
||||||
|
# not_start.wait.displayed(timeout=5, raise_err=False)
|
||||||
|
# not_start.click()
|
||||||
|
|
||||||
|
# wait_loaded()
|
||||||
|
|
||||||
|
# check = tab.ele('xpath://div[@class="contentWrapper"]//kat-checkbox[@name="value"]')
|
||||||
|
# check.wait.displayed(timeout=5, raise_err=False)
|
||||||
|
# check.click()
|
||||||
|
|
||||||
|
# save_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@variant="primary"]')
|
||||||
|
# save_btn.wait.enabled(timeout=5, raise_err=False)
|
||||||
|
# save_btn.click()
|
||||||
|
|
||||||
|
# wait_loaded()
|
||||||
|
|
||||||
|
# close_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@label="关闭"]',timeout=10)
|
||||||
|
# close_btn.wait.displayed(timeout=5, raise_err=False)
|
||||||
|
# close_btn.click()
|
||||||
|
|
||||||
|
# save_btn_ls = tab.eles('xpath://div[@class="contentWrapper"]//kat-button[@variant="primary"]',timeout=5)
|
||||||
|
# if len(save_btn_ls) > 0:
|
||||||
|
# option_selection_ls = tab.eles('xpath://div[@class="contentWrapper"]//div[@role="option"]',timeout=5)
|
||||||
|
# for option in option_selection_ls:
|
||||||
|
# option.click()
|
||||||
|
# time.sleep(0.5)
|
||||||
|
|
||||||
|
# save_btn_ls[0].wait.enabled(timeout=5, raise_err=False)
|
||||||
|
# save_btn_ls[0].click()
|
||||||
|
|
||||||
|
# wait_loaded()
|
||||||
|
|
||||||
|
# close_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@label="关闭"]',timeout=10)
|
||||||
|
# close_btn.wait.displayed(timeout=5, raise_err=False)
|
||||||
|
# close_btn.wait.enabled(timeout=5, raise_err=False)
|
||||||
|
# close_btn.click()
|
||||||
|
|
||||||
|
# submit_btn_ls = tab.eles('xpath://div[@id="ahd-product-policies-table"]/div//div[@data-testid="nextStepsMetricWrapper"]//kat-button[@label="提交"]',timeout=10)
|
||||||
|
# break
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"【handle_repair_product】处理修复商品信息异常", traceback.format_exc())
|
||||||
|
# tab.refresh()
|
||||||
|
# tab.wait.doc_loaded(timeout=60,raise_err=False)
|
||||||
|
# time.sleep(2)
|
||||||
|
|
||||||
|
# print("修复商品信息处理完成!")
|
||||||
|
# tab.close()
|
||||||
|
|
||||||
|
def handle_repair_product(self,tab:ChromiumTab,headle_type=""):
|
||||||
|
def wait_loaded(wait_type="contentWrapper"):
|
||||||
# 等待加载完成
|
# 等待加载完成
|
||||||
try:
|
print("------------【修复商品信息】等待加载完成-----------------")
|
||||||
load_ele = tab.ele(
|
for _ in range(3):
|
||||||
'xpath://div[@class="contentWrapper"]//div[contains(@class,"==")]/span[not(node())]',
|
try:
|
||||||
timeout=3)
|
load_ele = tab.eles(
|
||||||
load_ele.wait.deleted(timeout=5, raise_err=False)
|
'xpath://div[@class="contentWrapper"]//div[contains(@class,"==")]/span[not(node())]|//kat-spinner[@id="ahd-app-page-spinner"]',
|
||||||
except Exception as e:
|
timeout=10)
|
||||||
print("等待加载中消失出错", e)
|
if len(load_ele) > 0:
|
||||||
|
load_ele[0].wait.deleted(timeout=20, raise_err=False)
|
||||||
|
if wait_type == "contentWrapper":
|
||||||
|
contentWrapper = tab.eles('xpath://div[@class="contentWrapper"]//h4',timeout=20)
|
||||||
|
if len(contentWrapper) > 0:
|
||||||
|
contentWrapper[0].wait.displayed(timeout=20, raise_err=True)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(2)
|
||||||
|
break
|
||||||
|
if wait_type == "content":
|
||||||
|
contentWrapper = tab.eles('xpath://div[@class="contentWrapper"]',timeout=20)
|
||||||
|
if len(contentWrapper) > 0:
|
||||||
|
contentWrapper[0].wait.displayed(timeout=20, raise_err=True)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(2)
|
||||||
|
break
|
||||||
|
if wait_type == "section":
|
||||||
|
section = tab.eles('xpath://section[@class="ahd-product-policy__section"]',timeout=20)
|
||||||
|
if len(section) > 0:
|
||||||
|
section[0].wait.displayed(timeout=20, raise_err=True)
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print("等待加载中消失出错", e)
|
||||||
|
print("-----------------------------")
|
||||||
|
|
||||||
|
def close_contentWrapper():
|
||||||
|
# 关闭按钮
|
||||||
|
# close_x_btn = tab.eles('xpath://div[@class="flyoutPanelContent"]/span',timeout=5)
|
||||||
|
# if len(close_x_btn) > 0:
|
||||||
|
# close_x_btn[0].wait.displayed(timeout=5, raise_err=False)
|
||||||
|
# close_x_btn[0].click()
|
||||||
|
# time.sleep(1)
|
||||||
|
# close_x_btn[0].wait.deleted(timeout=5, raise_err=False)
|
||||||
|
close_x_btn = tab.eles('xpath://div[@class="flyoutPanelContent"]/span',timeout=5)
|
||||||
|
contentWrapper = tab.eles('xpath://div[@class="flyoutPanelContent"]/div[@class="contentWrapper"]',timeout=5)
|
||||||
|
if len(close_x_btn) > 0 and len(contentWrapper)>0 :
|
||||||
|
if len(contentWrapper[0].children()) > 0:
|
||||||
|
close_x_btn[0].wait.displayed(timeout=5, raise_err=False)
|
||||||
|
close_x_btn[0].click()
|
||||||
|
|
||||||
tab.wait.doc_loaded(timeout=60,raise_err=False)
|
tab.wait.doc_loaded(timeout=60,raise_err=False)
|
||||||
submit_btn_ls = tab.eles('xpath://div[@id="ahd-product-policies-table"]/div//div[@data-testid="nextStepsMetricWrapper"]//kat-button[@label="提交"]',timeout=10)
|
|
||||||
if len(submit_btn_ls) == 0:
|
wait_loaded(wait_type="section")
|
||||||
print("未找到提交按钮,可能页面未加载完成或者页面结构发生变化")
|
# product_policy = tab.eles('xpath://div[@data-testid="ahd-desktop-product-policy"]')
|
||||||
|
product_policy = tab.eles('xpath://div[@data-testid="ahd-desktop-product-policy" and @class="ahd-product-policy-table-row-wrapper"]|//div[@class="ahd-product-policy-table-row-wrapper-nested" and @data-testid="ahd-desktop-product-policy"]')
|
||||||
|
if len(product_policy) == 0:
|
||||||
|
print("未找到提交处理区域,可能页面未加载完成或者页面结构发生变化")
|
||||||
|
time.sleep(5)
|
||||||
|
# product_policy = tab.eles('xpath://div[@data-testid="ahd-desktop-product-policy"]')
|
||||||
|
product_policy = tab.eles('xpath://div[@data-testid="ahd-desktop-product-policy" and @class="ahd-product-policy-table-row-wrapper"]|//div[@class="ahd-product-policy-table-row-wrapper-nested" and @data-testid="ahd-desktop-product-policy"]')
|
||||||
|
|
||||||
|
print("等待5秒后再次查找提交处理区域:",len(product_policy))
|
||||||
|
|
||||||
|
# submit_btn_ls = tab.eles('xpath://div[@id="ahd-product-policies-table"]/div//div[@data-testid="nextStepsMetricWrapper"]//kat-button[@label="提交"]',timeout=10)
|
||||||
|
# if len(submit_btn_ls) == 0:
|
||||||
# return
|
# return
|
||||||
|
now_index = 0
|
||||||
|
submit_index = 0
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
# 先全部点开
|
||||||
|
chevron_right_ls = tab.eles('xpath://kat-icon[@name="chevron-right"]',timeout=10)
|
||||||
|
for ele in chevron_right_ls:
|
||||||
|
ele.click()
|
||||||
|
time.sleep(0.5)
|
||||||
|
except Exception as e:
|
||||||
|
print("【修复商品信息】全部点开失败",e)
|
||||||
try:
|
try:
|
||||||
# todo 遍历
|
# todo 遍历
|
||||||
for index in range(len(submit_btn_ls)):
|
print("【商品修复产品卡片】数量",len(product_policy))
|
||||||
if index > len(submit_btn_ls)-1:
|
print("【商品修复产品卡片】列表",product_policy)
|
||||||
print("提交按钮数量发生变化,停止处理")
|
for index in range(now_index,len(product_policy)):
|
||||||
|
product_policy = tab.eles('xpath://div[@data-testid="ahd-desktop-product-policy" and @class="ahd-product-policy-table-row-wrapper"]|//div[@class="ahd-product-policy-table-row-wrapper-nested" and @data-testid="ahd-desktop-product-policy"]')
|
||||||
|
now_index = index
|
||||||
|
if index > len(product_policy)-1:
|
||||||
|
print("提交按钮区域发生变化,停止处理")
|
||||||
break
|
break
|
||||||
|
message_link = product_policy[index].eles('xpath:.//a[@data-testid="ahd-reason-message-link"]')
|
||||||
|
message = message_link[0].text
|
||||||
|
|
||||||
submit_btn = submit_btn_ls[index]
|
if headle_type in ['查看冻结原因']:
|
||||||
|
need_heanle = any(i in message for i in ["制造商详细联系信息","警告和安全信息","负责人详细联系信息"])
|
||||||
|
else:
|
||||||
|
need_heanle = True
|
||||||
|
|
||||||
|
if not need_heanle:
|
||||||
|
print(f"【{headle_type}】【{message}】不需要处理,跳过")
|
||||||
|
continue
|
||||||
|
|
||||||
|
spread_btn = product_policy[index].eles('xpath:.//kat-icon[@name="chevron-right"]',timeout=5)
|
||||||
|
print(f"{index},是否存在展开按钮",len(spread_btn))
|
||||||
|
if len(spread_btn) > 0:
|
||||||
|
spread_btn[0].click()
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
submit_btn_ls = product_policy[index].eles('xpath:.//kat-button[@label="提交"]',timeout=5)
|
||||||
|
# try:
|
||||||
|
# submit_btn = product_policy[index].ele('xpath:.//kat-button[@label="提交"]',timeout=5)
|
||||||
|
# except Exception as e:
|
||||||
|
# print(datetime.now().strftime("%Y-%m-%d %H:%M:%S") ,"没有查找到提交按钮,跳过!")
|
||||||
|
# close_contentWrapper()
|
||||||
|
# continue
|
||||||
|
# print("提交按钮数量:",len(submit_btn))
|
||||||
|
print("提交按钮列表:",submit_btn_ls)
|
||||||
|
if len(submit_btn_ls) > 0:
|
||||||
|
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"),"查找到提交按钮")
|
||||||
|
# submit_btn = submit_btn[0]
|
||||||
|
submit_btn = tab.eles('xpath://kat-button[@label="提交"]',timeout=10)[submit_index]
|
||||||
|
submit_index += 1
|
||||||
|
else:
|
||||||
|
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S") ,"没有查找到提交按钮,跳过!")
|
||||||
|
close_contentWrapper()
|
||||||
|
continue
|
||||||
|
# time.sleep(10)
|
||||||
# 关闭按钮
|
# 关闭按钮
|
||||||
close_x_btn = tab.eles('xpath://div[@class="flyoutPanelContent"]/span',timeout=5)
|
close_x_btn = tab.eles('xpath://div[@class="flyoutPanelContent"]/span',timeout=5)
|
||||||
if len(close_x_btn) > 0:
|
contentWrapper = tab.eles('xpath://div[@class="flyoutPanelContent"]/div[@class="contentWrapper"]',timeout=5)
|
||||||
close_x_btn[0].wait.displayed(timeout=5, raise_err=False)
|
if len(close_x_btn) > 0 and len(contentWrapper)>0 :
|
||||||
close_x_btn[0].click()
|
if len(contentWrapper[0].children()) > 0:
|
||||||
|
close_x_btn[0].wait.displayed(timeout=5, raise_err=False)
|
||||||
|
close_x_btn[0].click()
|
||||||
|
|
||||||
|
print("开始操作",submit_btn)
|
||||||
|
print("操作的ID 为:",submit_btn.attr('id'))
|
||||||
submit_btn.wait.enabled(timeout=5, raise_err=False)
|
submit_btn.wait.enabled(timeout=5, raise_err=False)
|
||||||
submit_btn.click()
|
submit_btn.click()
|
||||||
time.sleep(0.5)
|
|
||||||
self.wait_loaded()
|
# 先直接等待contentWrapper出现,不要进行复杂的元素查找
|
||||||
|
try:
|
||||||
|
# 使用简单的等待,避免触发页面事件
|
||||||
|
for check_count in range(10):
|
||||||
|
contentWrapper_exists = tab.eles('xpath://div[@class="contentWrapper"]', timeout=2)
|
||||||
|
if len(contentWrapper_exists) > 0:
|
||||||
|
print(f"【弹窗已出现】第{check_count+1}次检查")
|
||||||
|
time.sleep(2) # 再等待2秒让内容完全加载
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"等待弹窗出现异常: {e}")
|
||||||
|
|
||||||
|
# wait_loaded(wait_type="content")
|
||||||
|
|
||||||
|
for j in range(4):
|
||||||
|
if j == 0:
|
||||||
|
timeout = 5
|
||||||
|
else:
|
||||||
|
timeout = 10
|
||||||
|
contentWrapper = tab.eles('xpath://div[@class="contentWrapper"]//h4',timeout=timeout)
|
||||||
|
print("标题的数量",len(contentWrapper))
|
||||||
|
if len(contentWrapper) > 0:
|
||||||
|
contentWrapper[0].wait.displayed(timeout=20, raise_err=True)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# 关闭按钮
|
||||||
|
close_contentWrapper()
|
||||||
|
time.sleep(2)
|
||||||
|
submit_btn.click()
|
||||||
|
|
||||||
wait_loaded()
|
|
||||||
|
|
||||||
need_input = tab.eles('xpath://div[@class="contentWrapper"]//kat-input[@data-testid="kat-input-dew:ump_epr_resgitration_number_title"]',timeout=5)
|
need_input = tab.eles('xpath://div[@class="contentWrapper"]//kat-input[@data-testid="kat-input-dew:ump_epr_resgitration_number_title"]',timeout=5)
|
||||||
if len(need_input) > 0:
|
if len(need_input) > 0:
|
||||||
print("需要输入注册号,不符合操作要求,跳过...")
|
print("需要输入注册号,不符合操作要求,跳过...")
|
||||||
|
close_contentWrapper()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
target_title = tab.eles('xpath://div[@class="contentWrapper"]//section//h4[text()="警告和安全信息"]')
|
target_title = tab.eles('xpath://div[@class="contentWrapper"]//section//h4[text()="警告和安全信息"]',timeout=10)
|
||||||
|
print(f"序号{index}【警告和安全信息】数量 ->",len(target_title))
|
||||||
if len(target_title) > 0:
|
if len(target_title) > 0:
|
||||||
not_start = tab.eles('xpath://div[@class="contentWrapper"]//div[@aria-label="安全证明"]//kat-label[@text="未开始"]')
|
is_Continue = False
|
||||||
if len(not_start) == 0:
|
for j in range(10):
|
||||||
print("安全证明-不是未开始状态,不需要操作")
|
not_start = tab.eles('xpath://div[@class="contentWrapper"]//div[@aria-label="安全证明"]//kat-label',timeout=2)
|
||||||
|
if len(not_start) > 0:
|
||||||
|
status_lebel = not_start[0].attr("text")
|
||||||
|
print(f"序号{index}【警告和安全信息】状态 ->",status_lebel)
|
||||||
|
if status_lebel and str(status_lebel).strip() != "" and status_lebel != "未开始":
|
||||||
|
print("安全证明-不是未开始状态,不需要操作")
|
||||||
|
close_contentWrapper()
|
||||||
|
continue
|
||||||
|
if status_lebel == "未开始":
|
||||||
|
is_Continue = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(1)
|
||||||
|
# not_start = tab.eles('xpath://div[@class="contentWrapper"]//div[@aria-label="安全证明"]//kat-label[@text="未开始"]',timeout=10)
|
||||||
|
# if len(not_start) == 0:
|
||||||
|
# print("安全证明-不是未开始状态,不需要操作")
|
||||||
|
# close_contentWrapper()
|
||||||
|
# continue
|
||||||
|
print(f"序号{index}【警告和安全信息】是否需要继续 ->",is_Continue)
|
||||||
|
if not is_Continue:
|
||||||
continue
|
continue
|
||||||
|
not_start = not_start[0]
|
||||||
not_start.wait.displayed(timeout=5, raise_err=False)
|
not_start.wait.displayed(timeout=5, raise_err=False)
|
||||||
not_start.click()
|
not_start.click()
|
||||||
|
|
||||||
wait_loaded()
|
wait_loaded()
|
||||||
|
|
||||||
check = tab.ele('xpath://div[@class="contentWrapper"]//kat-checkbox[@name="value"]')
|
check = tab.ele('xpath://div[@class="contentWrapper"]//kat-checkbox[@name="value"]',timeout=10)
|
||||||
check.wait.displayed(timeout=5, raise_err=False)
|
check.wait.displayed(timeout=5, raise_err=False)
|
||||||
check.click()
|
check.click()
|
||||||
|
|
||||||
save_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@variant="primary"]')
|
save_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@variant="primary"]',timeout=10)
|
||||||
save_btn.wait.enabled(timeout=5, raise_err=False)
|
save_btn.wait.enabled(timeout=5, raise_err=False)
|
||||||
save_btn.click()
|
save_btn.click()
|
||||||
|
|
||||||
@@ -175,8 +427,11 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
close_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@label="关闭"]',timeout=10)
|
close_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@label="关闭"]',timeout=10)
|
||||||
close_btn.wait.displayed(timeout=5, raise_err=False)
|
close_btn.wait.displayed(timeout=5, raise_err=False)
|
||||||
close_btn.click()
|
close_btn.click()
|
||||||
|
print(f"序号{index}【警告和安全信息】操作完成")
|
||||||
|
continue
|
||||||
|
|
||||||
save_btn_ls = tab.eles('xpath://div[@class="contentWrapper"]//kat-button[@variant="primary"]',timeout=5)
|
save_btn_ls = tab.eles('xpath://div[@class="contentWrapper"]//kat-button[@variant="primary"]',timeout=10)
|
||||||
|
print(f"序号{index}【选择保存】是否存在->",len(save_btn_ls))
|
||||||
if len(save_btn_ls) > 0:
|
if len(save_btn_ls) > 0:
|
||||||
option_selection_ls = tab.eles('xpath://div[@class="contentWrapper"]//div[@role="option"]',timeout=5)
|
option_selection_ls = tab.eles('xpath://div[@class="contentWrapper"]//div[@role="option"]',timeout=5)
|
||||||
for option in option_selection_ls:
|
for option in option_selection_ls:
|
||||||
@@ -187,29 +442,39 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
save_btn_ls[0].click()
|
save_btn_ls[0].click()
|
||||||
|
|
||||||
wait_loaded()
|
wait_loaded()
|
||||||
|
close_contentWrapper()
|
||||||
|
print(f"序号{index}【选择保存】操作完成")
|
||||||
|
continue
|
||||||
|
|
||||||
close_btn = tab.ele('xpath://div[@class="contentWrapper"]//kat-button[@label="关闭"]',timeout=10)
|
|
||||||
close_btn.wait.displayed(timeout=5, raise_err=False)
|
|
||||||
close_btn.wait.enabled(timeout=5, raise_err=False)
|
|
||||||
close_btn.click()
|
|
||||||
|
|
||||||
submit_btn_ls = tab.eles('xpath://div[@id="ahd-product-policies-table"]/div//div[@data-testid="nextStepsMetricWrapper"]//kat-button[@label="提交"]',timeout=10)
|
submit_btn_ls = tab.eles('xpath://div[@id="ahd-product-policies-table"]/div//div[@data-testid="nextStepsMetricWrapper"]//kat-button[@label="提交"]',timeout=10)
|
||||||
|
if len(submit_btn_ls) > 0:
|
||||||
|
submit_btn_ls[0].click()
|
||||||
|
submit_btn_ls[0].wait.deleted(timeout=5, raise_err=False)
|
||||||
|
wait_loaded()
|
||||||
|
|
||||||
|
close_contentWrapper()
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"【handle_repair_product】处理修复商品信息异常", traceback.format_exc())
|
print(f"【handle_repair_product】处理修复商品信息异常", traceback.format_exc())
|
||||||
tab.refresh()
|
tab.refresh()
|
||||||
tab.wait.doc_loaded(timeout=60,raise_err=False)
|
tab.wait.doc_loaded(timeout=60,raise_err=False)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
wait_loaded(wait_type="section")
|
||||||
|
# product_policy = tab.eles('xpath://div[@data-testid="ahd-desktop-product-policy"]')
|
||||||
|
product_policy = tab.eles('xpath://div[@data-testid="ahd-desktop-product-policy" and @class="ahd-product-policy-table-row-wrapper"]|//div[@class="ahd-product-policy-table-row-wrapper-nested" and @data-testid="ahd-desktop-product-policy"]')
|
||||||
|
|
||||||
|
|
||||||
print("修复商品信息处理完成!")
|
print("修复商品信息处理完成!")
|
||||||
tab.close()
|
tab.close()
|
||||||
|
|
||||||
|
|
||||||
def run_page_action(self):
|
def run_page_action(self):
|
||||||
print("开始执行")
|
print("开始执行")
|
||||||
num = 0
|
num = 0
|
||||||
retry_num = 0
|
retry_num = 0
|
||||||
already_asin = set()
|
already_asin = set()
|
||||||
|
now_page = None
|
||||||
while retry_num < 3: # 最多重试3次
|
while retry_num < 3: # 最多重试3次
|
||||||
# if num > 3: #测试
|
# if num > 3: #测试
|
||||||
# return
|
# return
|
||||||
@@ -235,20 +500,27 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
print(f"当前页码: {current_page} / 总页数: {total_page}")
|
print(f"当前页码: {current_page} / 总页数: {total_page}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("获取页码失败", e)
|
print("获取页码失败", e)
|
||||||
|
print("==========商品风险解决==============")
|
||||||
|
|
||||||
sku_ls = self.tab.eles("xpath://div[@data-sku]",timeout=10)
|
sku_ls = self.tab.eles("xpath://div[@data-sku]",timeout=10)
|
||||||
print(f"获取到 {len(sku_ls)}")
|
print(f"获取到 {len(sku_ls)}")
|
||||||
|
if len(sku_ls) == 0:
|
||||||
|
print(f"搜索不出SKU停止")
|
||||||
|
break
|
||||||
# for sku_ele in sku_ls[0:2]:
|
# for sku_ele in sku_ls[0:2]:
|
||||||
for sku_ele in sku_ls:
|
for sku_ele in sku_ls[1:]:
|
||||||
# solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]')
|
# solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]')
|
||||||
|
|
||||||
asin = sku_ele.ele('xpath:.//div[contains(@class,"JanusSplitBox-module__container")]//div[contains(@class,"JanusSplitBox-module__panel--") and contains(string(.),"ASIN")]/..//div[last()]').text
|
asin = sku_ele.ele('xpath:.//div[contains(@class,"JanusSplitBox-module__container")]//div[contains(@class,"JanusSplitBox-module__panel--") and contains(string(.),"ASIN")]/..//div[last()]').text
|
||||||
|
print(f"*************** {asin} *****************")
|
||||||
print(f"ASIN {asin} 存在问题,正在点击解决...")
|
print(f"ASIN {asin} 存在问题,正在点击解决...")
|
||||||
if asin in already_asin:
|
if asin in already_asin:
|
||||||
print(f"{asin} 已经处理过了,跳过")
|
print(f"{asin} 已经处理过了,跳过")
|
||||||
continue
|
continue
|
||||||
solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]|.//kat-link[@label="修复被禁止显示的商品"]|.//kat-link[@label="解决商品移除风险"]')
|
xp_ls = [f'.//kat-link[@label="{i}"]' for i in ["解决商品信息问题","修复被禁止显示的商品","解决商品移除风险","查看冻结原因"]]
|
||||||
|
xp = "|".join(xp_ls)
|
||||||
|
# solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]|.//kat-link[@label="修复被禁止显示的商品"]|.//kat-link[@label="解决商品移除风险"]')
|
||||||
|
solve_problem = sku_ele.eles(f'xpath:{xp}')
|
||||||
if len(solve_problem) == 0:
|
if len(solve_problem) == 0:
|
||||||
# //a[text0=”添加缺失的商品详情”]
|
# //a[text0=”添加缺失的商品详情”]
|
||||||
lack_info = sku_ele.eles('xpath:.//a[text()="添加缺失的商品详情"]')
|
lack_info = sku_ele.eles('xpath:.//a[text()="添加缺失的商品详情"]')
|
||||||
@@ -264,6 +536,9 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
|
|
||||||
solve_problem[0].click()
|
solve_problem[0].click()
|
||||||
|
|
||||||
|
label = solve_problem[0].attr('label')
|
||||||
|
print("【当前类别】",label)
|
||||||
|
|
||||||
action_panel = self.tab.ele('xpath://kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]')
|
action_panel = self.tab.ele('xpath://kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]')
|
||||||
action_panel.wait.displayed(timeout=5, raise_err=False)
|
action_panel.wait.displayed(timeout=5, raise_err=False)
|
||||||
|
|
||||||
@@ -274,15 +549,34 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
# 如果存在“请求批准”按钮,则直接返回跳过
|
# 如果存在“请求批准”按钮,则直接返回跳过
|
||||||
request_approval_btn = self.tab.eles('xpath://kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]//div[@data-testid="section-header" and contains(string(.),"移除")]',timeout=5)
|
request_approval_btn = self.tab.eles('xpath://kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]//div[@data-testid="section-header" and contains(string(.),"移除")]',timeout=5)
|
||||||
if len(request_approval_btn) > 0:
|
if len(request_approval_btn) > 0:
|
||||||
print(f"ASIN {asin} 存在请求批准按钮,不需要处理,跳过...")
|
# 新增"查看冻结原因" 的情况下,需要点击修复商品详情
|
||||||
panel_close_btn = self.tab.ele('xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]',
|
if "查看冻结原因" in label:
|
||||||
timeout=5).sr('xpath:.//button[@class="close"]')
|
repair_produ_btn_xp = '//kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]//kat-button[@variant="secondary" and @class="action-button" and contains(string(.),"修复商品信息")]'
|
||||||
panel_close_btn.click()
|
repair_produ_btn = self.tab.eles(f'xpath:{repair_produ_btn_xp}',timeout=5)
|
||||||
|
print(f"{asin}【查看冻结原因】修复商品信息数量",len(repair_produ_btn))
|
||||||
|
if len(repair_produ_btn) > 0:
|
||||||
|
print(f"{asin}【查看冻结原因】修复商品信息数量,开始操作")
|
||||||
|
self.clear_tab()
|
||||||
|
repair_produ_btn[0].click()
|
||||||
|
time.sleep(3)
|
||||||
|
# 获取最新的tab
|
||||||
|
new_tab = self.browser.latest_tab
|
||||||
|
if isinstance(new_tab, str):
|
||||||
|
new_tab = self.browser.get_tab(id_or_num=new_tab)
|
||||||
|
|
||||||
action_panel.wait.deleted(timeout=3, raise_err=False)
|
self.handle_repair_product(new_tab,headle_type="查看冻结原因")
|
||||||
yield (asin,"请求批准")
|
else:
|
||||||
already_asin.add(asin)
|
print(f"{i}【查看冻结原因】修复商品信息没有,不需要操作")
|
||||||
continue
|
else:
|
||||||
|
print(f"ASIN {asin} 存在请求批准按钮,不需要处理,跳过...")
|
||||||
|
panel_close_btn = self.tab.ele('xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]',
|
||||||
|
timeout=5).sr('xpath:.//button[@class="close"]')
|
||||||
|
panel_close_btn.click()
|
||||||
|
|
||||||
|
action_panel.wait.deleted(timeout=3, raise_err=False)
|
||||||
|
yield (asin,"请求批准")
|
||||||
|
already_asin.add(asin)
|
||||||
|
continue
|
||||||
|
|
||||||
# 无需采取任何操作
|
# 无需采取任何操作
|
||||||
not_operate = self.tab.eles('xpath://kat-alert[contains(@description,"如果您之前已提交更改,则这些更改当前正在处理中") and not(@dismissed)]',timeout=3)
|
not_operate = self.tab.eles('xpath://kat-alert[contains(@description,"如果您之前已提交更改,则这些更改当前正在处理中") and not(@dismissed)]',timeout=3)
|
||||||
@@ -310,7 +604,7 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
|
|
||||||
# TODO 增加 “出现警告和安全信息时候下滑” 的情况
|
# TODO 增加 “出现警告和安全信息时候下滑” 的情况
|
||||||
safe_handle_ls = self.tab.eles('xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]//div[@aria-label="安全证明"]//kat-label[@text="未开始"]',
|
safe_handle_ls = self.tab.eles('xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]//div[@aria-label="安全证明"]//kat-label[@text="未开始"]',
|
||||||
timeout=5)
|
timeout=15)
|
||||||
if len(safe_handle_ls) > 0:
|
if len(safe_handle_ls) > 0:
|
||||||
print("存在安全证明,正在处理...")
|
print("存在安全证明,正在处理...")
|
||||||
safe_handle_ls[0].click()
|
safe_handle_ls[0].click()
|
||||||
@@ -329,17 +623,19 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# 点击保存
|
# 点击保存
|
||||||
confirm_btn = self.tab.ele('xpath://kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]//kat-button[@variant="primary"]')
|
confirm_btn = self.tab.eles('xpath://kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]//kat-button[@variant="primary"]')
|
||||||
confirm_btn.wait.displayed(timeout=3, raise_err=False)
|
if len(confirm_btn) > 0:
|
||||||
confirm_btn.click()
|
confirm_btn[0].wait.displayed(timeout=3, raise_err=False)
|
||||||
|
confirm_btn[0].click()
|
||||||
|
|
||||||
self.wait_loaded()
|
self.wait_loaded()
|
||||||
|
|
||||||
# 等待关闭按钮出现
|
# 等待关闭按钮出现
|
||||||
try:
|
try:
|
||||||
close_btn = self.tab.ele('xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]//kat-button[@label="关闭"]',
|
close_btn = self.tab.eles('xpath://kat-panel[@data-testid="kat-panel-ActionPanelContent"]//kat-button[@label="关闭"]',
|
||||||
timeout=10)
|
timeout=10)
|
||||||
close_btn.click()
|
if len(close_btn)>0:
|
||||||
|
close_btn[0].click()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("点击关闭按钮失败",e)
|
print("点击关闭按钮失败",e)
|
||||||
|
|
||||||
@@ -351,7 +647,7 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
print(f"ASIN {asin} 存在修复商品信息按钮,正在点击...")
|
print(f"ASIN {asin} 存在修复商品信息按钮,正在点击...")
|
||||||
self.clear_tab()
|
self.clear_tab()
|
||||||
repair_product[0].click()
|
repair_product[0].click()
|
||||||
time.sleep(1)
|
time.sleep(3)
|
||||||
# 获取最新的tab
|
# 获取最新的tab
|
||||||
new_tab = self.browser.latest_tab
|
new_tab = self.browser.latest_tab
|
||||||
if isinstance(new_tab, str):
|
if isinstance(new_tab, str):
|
||||||
@@ -366,6 +662,7 @@ class AmzoneApprove(AmamzonBase):
|
|||||||
|
|
||||||
yield (asin,"处理完成")
|
yield (asin,"处理完成")
|
||||||
already_asin.add(asin)
|
already_asin.add(asin)
|
||||||
|
print(f"*********************{asin} 处理完成*************************")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 全部操作完成,关闭
|
# 全部操作完成,关闭
|
||||||
@@ -556,6 +853,8 @@ class ApproveTask:
|
|||||||
items = data.get("items", [])
|
items = data.get("items", [])
|
||||||
country_codes = data.get("country_codes", [])
|
country_codes = data.get("country_codes", [])
|
||||||
risk_listing_filter = data.get("risk_listing_filter", "")
|
risk_listing_filter = data.get("risk_listing_filter", "")
|
||||||
|
# 测试
|
||||||
|
# risk_listing_filter = "DetailPageRemoved" #data.get("risk_listing_filter", "")
|
||||||
|
|
||||||
if not task_id:
|
if not task_id:
|
||||||
self.log("任务ID为空,跳过", "WARNING")
|
self.log("任务ID为空,跳过", "WARNING")
|
||||||
@@ -993,14 +1292,14 @@ if __name__ == '__main__':
|
|||||||
"username": "自动化_Robot",
|
"username": "自动化_Robot",
|
||||||
"password": "#20zsg25"
|
"password": "#20zsg25"
|
||||||
}
|
}
|
||||||
shop_name = "魏振峰"
|
shop_name = "郭亚芳"
|
||||||
country = "德国"
|
country = "德国"
|
||||||
kill_process('v6')
|
kill_process('v6')
|
||||||
driver = AmzoneApprove(user_info)
|
driver = AmzoneApprove(user_info)
|
||||||
browser = driver.open_shop(shop_name)
|
browser = driver.open_shop(shop_name)
|
||||||
sw_suc = driver.SwitchingCountries(country)
|
sw_suc = driver.SwitchingCountries(country)
|
||||||
driver.SwitchPage()
|
driver.SwitchPage()
|
||||||
risk_listing_filter = "ApprovalRequired"
|
risk_listing_filter = "DetailPageRemoved"
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
try:
|
try:
|
||||||
sku_ls = driver.search(filter_type=risk_listing_filter)
|
sku_ls = driver.search(filter_type=risk_listing_filter)
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ class ZiniaoDriver:
|
|||||||
self.open_launcher_page(ret_json.get("launcherPage"), self.browser)
|
self.open_launcher_page(ret_json.get("launcherPage"), self.browser)
|
||||||
else:
|
else:
|
||||||
print("IP检测不通过")
|
print("IP检测不通过")
|
||||||
|
raise RuntimeError("IP检测不通过,可能是因为网络环境变化导致的,为了店铺安全不打开店铺")
|
||||||
return self.browser
|
return self.browser
|
||||||
|
|
||||||
def close_store(self, browser_oauth=None):
|
def close_store(self, browser_oauth=None):
|
||||||
@@ -499,26 +500,55 @@ class AmamzonBase(ZiniaoDriver):
|
|||||||
|
|
||||||
def login(self,password,username=""):
|
def login(self,password,username=""):
|
||||||
try:
|
try:
|
||||||
pwd_input = self.tab.eles('xpath://input[@type="password"]',timeout=10)
|
self.tab.wait.doc_loaded(timeout=30,raise_err=False)
|
||||||
if len(pwd_input) > 0:
|
for _ in range(4):
|
||||||
pwd_input[0].input(password,clear=True)
|
pwd_input = self.tab.eles('xpath://input[@type="password"]',timeout=5)
|
||||||
submit_btn = self.tab.eles('xpath://input[@id="signInSubmit"]',timeout=10)
|
if len(pwd_input) > 0:
|
||||||
if len(submit_btn) > 0:
|
pwd_input[0].input(password,clear=True)
|
||||||
submit_btn[0].click()
|
submit_btn = self.tab.eles('xpath://input[@id="signInSubmit"]',timeout=5)
|
||||||
self.tab.wait.doc_loaded()
|
if len(submit_btn) > 0:
|
||||||
|
submit_btn[0].click()
|
||||||
|
self.tab.wait.doc_loaded(timeout=30,raise_err=False)
|
||||||
|
|
||||||
opt_code_input = self.tab.ele('xpath://input[@name="otpCode"]',timeout=60)
|
send_code = self.tab.eles('xpath://span[@id="auth-send-code" and contains(string(.),"发送一次性密码")]',timeout=5)
|
||||||
opt_code_input.wait.displayed(timeout=10,raise_err=False)
|
print("发送一次性密码:",len(send_code))
|
||||||
for _ in range(30):
|
if len(send_code) > 0:
|
||||||
if opt_code_input.value is not None and opt_code_input.value.strip() != "":
|
print("检测到 发送一次性密码")
|
||||||
print("检测到验证码输入完成")
|
send_code[0].click()
|
||||||
submit_btn = self.tab.ele('xpath://input[@id="auth-signin-button"]',timeout=10)
|
time.sleep(1)
|
||||||
submit_btn.click()
|
self.tab.wait.doc_loaded(timeout=30,raise_err=False)
|
||||||
self.tab.wait.doc_loaded()
|
else:
|
||||||
return True
|
for j in range(5):
|
||||||
time.sleep(1)
|
opt_code_input = self.tab.eles('xpath://input[@name="otpCode"]',timeout=30)
|
||||||
submit_btn = self.tab.ele('xpath://input[@id="auth-signin-button"]',timeout=10)
|
print("验证码输入框:",len(opt_code_input))
|
||||||
submit_btn.click()
|
if len(opt_code_input) > 0:
|
||||||
|
opt_code_input[0].wait.displayed(timeout=10,raise_err=False)
|
||||||
|
for _ in range(30):
|
||||||
|
if opt_code_input[0].value is not None and opt_code_input[0].value.strip() != "":
|
||||||
|
print("检测到验证码输入完成")
|
||||||
|
submit_btn = self.tab.eles('xpath://input[@id="auth-signin-button"]',timeout=10)
|
||||||
|
if len(submit_btn) > 0:
|
||||||
|
submit_btn[0].click()
|
||||||
|
self.tab.wait.doc_loaded(timeout=20,raise_err=False)
|
||||||
|
# return True
|
||||||
|
error_mes = self.tab.eles('xpath://div[@id="auth-error-message-box"]',timeout=10)
|
||||||
|
if len(error_mes)>0:
|
||||||
|
print("验证码输入错误")
|
||||||
|
print("验证码输入错误提示:",error_mes[0].text)
|
||||||
|
self.tab.refresh()
|
||||||
|
else:
|
||||||
|
print("登入成功")
|
||||||
|
return True
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
submit_btn = self.tab.eles('xpath://input[@id="auth-signin-button"]',timeout=10)
|
||||||
|
if len(submit_btn) > 0:
|
||||||
|
submit_btn[0].click()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("登录过程中发生异常:" + traceback.format_exc())
|
print("登录过程中发生异常:" + traceback.format_exc())
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -127,13 +127,13 @@ class AmzoneMatchAction(AmamzonBase):
|
|||||||
for sku_ele in sku_ls:
|
for sku_ele in sku_ls:
|
||||||
# solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]')
|
# solve_problem = sku_ele.eles('xpath:.//kat-link[@label="解决商品信息问题"]')
|
||||||
|
|
||||||
asin = sku_ele.ele('xpath:.//div[contains(@class,"JanusSplitBox-module__container")]//div[contains(@class,"JanusSplitBox-module__panel--") and contains(string(.),"ASIN")]/..//div[last()]',timeout=10).text
|
asin = sku_ele.ele('xpath:.//div[contains(@class,"JanusSplitBox-module__container")]//div[contains(@class,"JanusSplitBox-module__panel--") and contains(string(.),"ASIN")]/..//div[last()]',timeout=3).text
|
||||||
print(f"【{self.mark_name}】ASIN {asin} 找到....")
|
print(f"【{self.mark_name}】ASIN {asin} 找到....")
|
||||||
if asin in already_asin:
|
if asin in already_asin:
|
||||||
print(f"【{self.mark_name}】{asin} 已经处理过了,跳过")
|
print(f"【{self.mark_name}】{asin} 已经处理过了,跳过")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
price_match = sku_ele.eles('xpath:.//div[@data-test-id="FeaturedOfferPrice"]//a[text()="匹配"]',timeout=5)
|
price_match = sku_ele.eles('xpath:.//div[@data-test-id="FeaturedOfferPrice"]//a[text()="匹配"]',timeout=2)
|
||||||
if len(price_match) == 0:
|
if len(price_match) == 0:
|
||||||
print(f"【{self.mark_name}】{asin},没有推荐价格匹配按钮")
|
print(f"【{self.mark_name}】{asin},没有推荐价格匹配按钮")
|
||||||
yield (asin,"无需处理")
|
yield (asin,"无需处理")
|
||||||
@@ -230,6 +230,9 @@ class MatchTak:
|
|||||||
stage_index = data.get("stage_index")
|
stage_index = data.get("stage_index")
|
||||||
final_stage = bool(data.get("final_stage", True))
|
final_stage = bool(data.get("final_stage", True))
|
||||||
|
|
||||||
|
# 用于测试
|
||||||
|
limit = data.get("limit",None)
|
||||||
|
|
||||||
if not task_id:
|
if not task_id:
|
||||||
self.log("任务ID为空,跳过", "WARNING")
|
self.log("任务ID为空,跳过", "WARNING")
|
||||||
return
|
return
|
||||||
@@ -272,7 +275,7 @@ class MatchTak:
|
|||||||
show_notification(f"开始处理店铺: {shop_name}", "info")
|
show_notification(f"开始处理店铺: {shop_name}", "info")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.process_shop(shop_item, country_codes, task_id, risk_listing_filter, user_id, stage_index, final_stage)
|
self.process_shop(shop_item, country_codes, task_id, risk_listing_filter, user_id, stage_index, final_stage,limit=limit)
|
||||||
|
|
||||||
# self.process_shop(shop_item, country_codes, task_id,risk_listing_filter)
|
# self.process_shop(shop_item, country_codes, task_id,risk_listing_filter)
|
||||||
# 更新已处理店铺数
|
# 更新已处理店铺数
|
||||||
@@ -302,7 +305,8 @@ class MatchTak:
|
|||||||
runing_task[task_id]["error"] = str(e)
|
runing_task[task_id]["error"] = str(e)
|
||||||
|
|
||||||
# def process_shop(self, shop_item: dict, country_codes: list, task_id: int, risk_listing_filter: str):
|
# def process_shop(self, shop_item: dict, country_codes: list, task_id: int, risk_listing_filter: str):
|
||||||
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):
|
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):
|
||||||
"""处理单个店铺
|
"""处理单个店铺
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -420,7 +424,7 @@ class MatchTak:
|
|||||||
break
|
break
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.process_country(driver, country_code, task_id, shop_name,risk_listing_filter)
|
self.process_country(driver, country_code, task_id, shop_name,risk_listing_filter,limit)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
import traceback
|
import traceback
|
||||||
self.log(f"处理国家 {country_code} 失败: {str(e)}", "ERROR")
|
self.log(f"处理国家 {country_code} 失败: {str(e)}", "ERROR")
|
||||||
@@ -449,7 +453,7 @@ class MatchTak:
|
|||||||
del runing_shop[shop_name]
|
del runing_shop[shop_name]
|
||||||
self.log(f"店铺 {shop_name} 已从执行列表中移除")
|
self.log(f"店铺 {shop_name} 已从执行列表中移除")
|
||||||
|
|
||||||
def process_country(self, driver: AmzoneMatchAction, country_code: str, task_id: int, shop_name: str, risk_listing_filter: str):
|
def process_country(self, driver: AmzoneMatchAction, country_code: str, task_id: int, shop_name: str, risk_listing_filter: str,limit:str=None):
|
||||||
"""处理单个国家的审批任务
|
"""处理单个国家的审批任务
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -582,6 +586,7 @@ class MatchTak:
|
|||||||
runing_task[task_id]["processed_countries"] += 1
|
runing_task[task_id]["processed_countries"] += 1
|
||||||
|
|
||||||
self.log(f"国家 {country_name} 处理完成")
|
self.log(f"国家 {country_name} 处理完成")
|
||||||
|
|
||||||
def post_stage_finished(self, task_id: int, user_id, stage_index):
|
def post_stage_finished(self, task_id: int, user_id, stage_index):
|
||||||
import requests
|
import requests
|
||||||
from config import DELETE_BRAND_API_BASE
|
from config import DELETE_BRAND_API_BASE
|
||||||
|
|||||||
333
app/amazon/price_match.py
Normal file
333
app/amazon/price_match.py
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
import time
|
||||||
|
import re
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from config import runing_task, runing_shop
|
||||||
|
from datetime import datetime
|
||||||
|
from amazon.del_brand import AmamzonBase, kill_process
|
||||||
|
|
||||||
|
from amazon.tool import show_notification,get_shop_info
|
||||||
|
|
||||||
|
class ChromeAmzone:
|
||||||
|
mark_name = "亚马逊详情采集"
|
||||||
|
country_info = {
|
||||||
|
"英国": {
|
||||||
|
"url": "https://www.amazon.co.uk/dp/B0CJ8SNXXV",
|
||||||
|
"zip_code": "SW1A 1AA"
|
||||||
|
},
|
||||||
|
"德国": {
|
||||||
|
"url": "https://www.amazon.de/dp/B0CC8CW9G2?th=1",
|
||||||
|
"zip_code": "10115"
|
||||||
|
},
|
||||||
|
"法国": {
|
||||||
|
"url": "https://www.amazon.fr/dp/B0FRG1MJ8H?th=1",
|
||||||
|
"zip_code": "75001"
|
||||||
|
},
|
||||||
|
"西班牙": {
|
||||||
|
"url": "https://www.amazon.es/dp/B08ZXVNYNN",
|
||||||
|
"zip_code": "28001"
|
||||||
|
},
|
||||||
|
"意大利": {
|
||||||
|
"url": "https://www.amazon.it/dp/B0D1P17T2Q",
|
||||||
|
"zip_code": "20121"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
杀死当前谷歌浏览器进程,并使用 drissionpage 启动谷歌浏览器,使用系统安装的浏览器默认用户文件夹
|
||||||
|
"""
|
||||||
|
# 杀死现有的Chrome进程
|
||||||
|
print("正在关闭现有的Chrome浏览器进程...")
|
||||||
|
import os
|
||||||
|
os.system('taskkill /f /t /im chrome.exe')
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 使用 DrissionPage 启动浏览器(使用默认用户数据)
|
||||||
|
from DrissionPage import Chromium, ChromiumOptions
|
||||||
|
print("正在启动Chrome浏览器...")
|
||||||
|
|
||||||
|
# 配置浏览器选项
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# 使用系统默认的用户数据目录
|
||||||
|
# co.set_user_data_path(r'C:\Users\{}\AppData\Local\Google\Chrome\User Data'.format(os.getenv('USERNAME')))
|
||||||
|
|
||||||
|
self.browser = Chromium(co)
|
||||||
|
self.tab = self.browser.latest_tab
|
||||||
|
print("Chrome浏览器启动成功")
|
||||||
|
|
||||||
|
def accept_cookie(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self, country, asin):
|
||||||
|
"""
|
||||||
|
运行亚马逊详情采集任务
|
||||||
|
|
||||||
|
Args:
|
||||||
|
country: 国家名称(如:英国、德国、法国、西班牙、意大利)
|
||||||
|
asin: 亚马逊商品ASIN码
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 包含采集到的数据
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 验证国家是否支持
|
||||||
|
if country not in self.country_info:
|
||||||
|
error_msg = f"不支持的国家: {country},支持的国家有: {list(self.country_info.keys())}"
|
||||||
|
print(error_msg)
|
||||||
|
show_notification(error_msg, "error")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 获取国家配置
|
||||||
|
country_config = self.country_info[country]
|
||||||
|
zip_code = country_config["zip_code"]
|
||||||
|
|
||||||
|
# 1. 根据国家和ASIN拼接链接
|
||||||
|
base_url = country_config["url"]
|
||||||
|
# 提取域名部分
|
||||||
|
domain = base_url.split("/dp/")[0]
|
||||||
|
# 拼接新的URL
|
||||||
|
product_url = f"{domain}/dp/{asin}"
|
||||||
|
print(f"正在访问: {product_url}")
|
||||||
|
|
||||||
|
# 打开链接
|
||||||
|
self.tab.get(product_url)
|
||||||
|
time.sleep(3) # 等待页面初步加载
|
||||||
|
self.tab.wait.doc_loaded(timeout=30, raise_err=False)
|
||||||
|
|
||||||
|
# 2. 切换国家/设置邮编
|
||||||
|
print(f"正在检查并设置邮编: {zip_code}")
|
||||||
|
self._set_zip_code(zip_code)
|
||||||
|
|
||||||
|
# 3. 抓取数据
|
||||||
|
print("正在抓取商品数据...")
|
||||||
|
data = self._scrape_data()
|
||||||
|
|
||||||
|
# 添加基本信息
|
||||||
|
data['country'] = country
|
||||||
|
data['asin'] = asin
|
||||||
|
data['url'] = product_url
|
||||||
|
data['timestamp'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
print(f"数据抓取完成: {data}")
|
||||||
|
return data
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"运行出错: {traceback.format_exc()}"
|
||||||
|
print(error_msg)
|
||||||
|
show_notification(f"采集失败: {str(e)}", "error")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _set_zip_code(self, zip_code):
|
||||||
|
"""
|
||||||
|
设置邮编
|
||||||
|
|
||||||
|
Args:
|
||||||
|
zip_code: 目标邮编
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 检查当前邮编
|
||||||
|
zip_display = self.tab.ele('xpath://div[@id="glow-ingress-block"]', timeout=10)
|
||||||
|
|
||||||
|
if zip_display:
|
||||||
|
current_text = zip_display.text
|
||||||
|
print(f"当前地址信息: {current_text}")
|
||||||
|
|
||||||
|
# 检查是否已经包含目标邮编
|
||||||
|
if zip_code in current_text:
|
||||||
|
print(f"邮编已经设置为: {zip_code},无需修改")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 需要设置邮编
|
||||||
|
print(f"正在设置邮编为: {zip_code}")
|
||||||
|
|
||||||
|
# 点击地址选择按钮
|
||||||
|
location_link = self.tab.ele('xpath://a[@id="nav-global-location-popover-link"]', timeout=10)
|
||||||
|
if not location_link:
|
||||||
|
print("找不到地址设置按钮")
|
||||||
|
return False
|
||||||
|
|
||||||
|
location_link.click()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 等待邮编输入框出现
|
||||||
|
zip_input = self.tab.ele('xpath://input[@id="GLUXZipUpdateInput"]', timeout=10)
|
||||||
|
if not zip_input:
|
||||||
|
print("找不到邮编输入框")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 输入邮编
|
||||||
|
zip_input.input(zip_code, clear=True)
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# 点击提交按钮
|
||||||
|
submit_btn = self.tab.ele('xpath://input[@aria-labelledby="GLUXZipUpdate-announce"]', timeout=10)
|
||||||
|
if not submit_btn:
|
||||||
|
print("找不到提交按钮")
|
||||||
|
return False
|
||||||
|
|
||||||
|
submit_btn.click()
|
||||||
|
|
||||||
|
# 等待提交按钮消失(表示请求已发送)
|
||||||
|
print("等待邮编更新...")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 等待页面加载完成
|
||||||
|
self.tab.wait.doc_loaded(timeout=30, raise_err=False)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 验证邮编是否设置成功
|
||||||
|
zip_display_after = self.tab.ele('xpath://div[@id="glow-ingress-block"]', timeout=10)
|
||||||
|
if zip_display_after:
|
||||||
|
updated_text = zip_display_after.text
|
||||||
|
print(f"更新后的地址信息: {updated_text}")
|
||||||
|
|
||||||
|
if zip_code in updated_text:
|
||||||
|
print(f"邮编设置成功: {zip_code}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"邮编设置可能失败,当前显示: {updated_text}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"设置邮编时出错: {traceback.format_exc()}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _scrape_data(self):
|
||||||
|
"""
|
||||||
|
抓取商品数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 抓取到的数据
|
||||||
|
"""
|
||||||
|
data = {
|
||||||
|
'top_sellers': [], # 前两名卖家信息
|
||||||
|
'cart_seller': None # 购物车所属卖家
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 等待页面加载
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# 1. 获取前两名卖家的价格和库存(来自 sellersprite 插件)
|
||||||
|
print("正在抓取卖家排名数据...")
|
||||||
|
surplus_tables = self.tab.eles(
|
||||||
|
'xpath://div[@id="sellersprite-extension-Inventory-surplus-count"]//div[@class="surplus-table"]',
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
if surplus_tables:
|
||||||
|
print(f"找到 {len(surplus_tables)} 个卖家数据")
|
||||||
|
# 只获取前两个
|
||||||
|
for idx, table in enumerate(surplus_tables[:2]):
|
||||||
|
try:
|
||||||
|
# 提取价格和库存信息
|
||||||
|
# 注意:需要根据实际的HTML结构调整选择器
|
||||||
|
text_content = table.text
|
||||||
|
print(f"第{idx+1}名卖家数据: {text_content}")
|
||||||
|
|
||||||
|
seller_info = {
|
||||||
|
'rank': idx + 1,
|
||||||
|
'raw_data': text_content
|
||||||
|
}
|
||||||
|
|
||||||
|
# 尝试提取更结构化的数据
|
||||||
|
# 这里需要根据实际HTML结构来解析
|
||||||
|
# 可能需要查找子元素
|
||||||
|
try:
|
||||||
|
# 示例:查找价格和库存的具体子节点
|
||||||
|
price_ele = table.ele('xpath:.//span[contains(@class,"price")]', timeout=2)
|
||||||
|
stock_ele = table.ele('xpath:.//span[contains(@class,"stock")]', timeout=2)
|
||||||
|
|
||||||
|
if price_ele:
|
||||||
|
seller_info['price'] = price_ele.text.strip()
|
||||||
|
if stock_ele:
|
||||||
|
seller_info['stock'] = stock_ele.text.strip()
|
||||||
|
except:
|
||||||
|
# 如果找不到具体元素,就使用原始文本
|
||||||
|
pass
|
||||||
|
|
||||||
|
data['top_sellers'].append(seller_info)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"解析第{idx+1}名卖家数据失败: {str(e)}")
|
||||||
|
else:
|
||||||
|
print("未找到 sellersprite 插件数据,可能插件未启用")
|
||||||
|
|
||||||
|
# 2. 获取购物车所属卖家
|
||||||
|
print("正在抓取购物车卖家信息...")
|
||||||
|
cart_seller = self.tab.ele(
|
||||||
|
'xpath://div[@data-csa-c-content-id="desktop-merchant-info"]//a[@id="sellerProfileTriggerId"]',
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
if cart_seller:
|
||||||
|
seller_name = cart_seller.text.strip()
|
||||||
|
print(f"购物车所属卖家: {seller_name}")
|
||||||
|
data['cart_seller'] = seller_name
|
||||||
|
else:
|
||||||
|
print("未找到购物车卖家信息")
|
||||||
|
# 尝试其他可能的选择器
|
||||||
|
try:
|
||||||
|
alt_seller = self.tab.ele('xpath://a[@id="sellerProfileTriggerId"]', timeout=5)
|
||||||
|
if alt_seller:
|
||||||
|
data['cart_seller'] = alt_seller.text.strip()
|
||||||
|
print(f"购物车所属卖家(备用方式): {data['cart_seller']}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"抓取数据时出错: {traceback.format_exc()}")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""关闭浏览器"""
|
||||||
|
try:
|
||||||
|
if self.browser:
|
||||||
|
self.browser.quit()
|
||||||
|
print("浏览器已关闭")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"关闭浏览器时出错: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
class AmzonePriceMatch(AmamzonBase):
|
||||||
|
mark_name = "跟价"
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# 使用示例
|
||||||
|
print("=" * 50)
|
||||||
|
print("亚马逊详情采集示例")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 创建ChromeAmzone实例
|
||||||
|
chrome = ChromeAmzone()
|
||||||
|
|
||||||
|
# 示例1:采集英国站点的商品信息
|
||||||
|
print("\n示例1:采集英国站点商品")
|
||||||
|
result1 = chrome.run(country="英国", asin="B0CJ8SNXXV")
|
||||||
|
if result1:
|
||||||
|
print(f"采集成功: {result1}")
|
||||||
|
|
||||||
|
# 示例2:采集德国站点的商品信息
|
||||||
|
print("\n示例2:采集德国站点商品")
|
||||||
|
result2 = chrome.run(country="德国", asin="B0CC8CW9G2")
|
||||||
|
if result2:
|
||||||
|
print(f"采集成功: {result2}")
|
||||||
|
|
||||||
|
# 关闭浏览器
|
||||||
|
print("\n正在关闭浏览器...")
|
||||||
|
chrome.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"运行出错: {traceback.format_exc()}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
16
app/main.py
16
app/main.py
@@ -19,7 +19,6 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
import atexit
|
|
||||||
|
|
||||||
from amazon.del_brand import kill_process
|
from amazon.del_brand import kill_process
|
||||||
|
|
||||||
@@ -40,21 +39,6 @@ print(f"""
|
|||||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
APP_URL = "http://127.0.0.1:5123"
|
APP_URL = "http://127.0.0.1:5123"
|
||||||
PORT = 5123
|
PORT = 5123
|
||||||
_shutdown_started = False
|
|
||||||
|
|
||||||
|
|
||||||
def cleanup_before_exit():
|
|
||||||
global _shutdown_started
|
|
||||||
if _shutdown_started:
|
|
||||||
return
|
|
||||||
_shutdown_started = True
|
|
||||||
try:
|
|
||||||
kill_process('v6')
|
|
||||||
except Exception as e:
|
|
||||||
print(f"【退出前】关闭紫鸟浏览器进程异常: {str(e)}")
|
|
||||||
|
|
||||||
|
|
||||||
atexit.register(cleanup_before_exit)
|
|
||||||
|
|
||||||
|
|
||||||
def generate_images(params):
|
def generate_images(params):
|
||||||
|
|||||||
Reference in New Issue
Block a user