Merge branch 'master' of https://gitee.com/TeaCodeNice/crawler-plugin
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 traceback
|
||||
from DrissionPage._pages.chromium_tab import ChromiumTab
|
||||
import pyautogui
|
||||
|
||||
from config import runing_task, runing_shop
|
||||
from datetime import datetime
|
||||
@@ -86,10 +87,11 @@ class AmzoneApprove(AmamzonBase):
|
||||
def wait_loaded(self):
|
||||
# 等待加载完成
|
||||
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',
|
||||
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:
|
||||
print("等待加载中消失出错", e)
|
||||
|
||||
@@ -106,67 +108,317 @@ class AmzoneApprove(AmamzonBase):
|
||||
print("当前操作的tab_id",self.tab.tab_id)
|
||||
self.browser.close_tabs(close_tab)
|
||||
|
||||
def handle_repair_product(self,tab:ChromiumTab):
|
||||
def wait_loaded():
|
||||
# def handle_repair_product_old(self,tab:ChromiumTab):
|
||||
# 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:
|
||||
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)
|
||||
print("------------【修复商品信息】等待加载完成-----------------")
|
||||
for _ in range(3):
|
||||
try:
|
||||
load_ele = tab.eles(
|
||||
'xpath://div[@class="contentWrapper"]//div[contains(@class,"==")]/span[not(node())]|//kat-spinner[@id="ahd-app-page-spinner"]',
|
||||
timeout=10)
|
||||
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)
|
||||
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("未找到提交按钮,可能页面未加载完成或者页面结构发生变化")
|
||||
|
||||
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"]')
|
||||
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
|
||||
now_index = 0
|
||||
submit_index = 0
|
||||
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:
|
||||
# todo 遍历
|
||||
for index in range(len(submit_btn_ls)):
|
||||
if index > len(submit_btn_ls)-1:
|
||||
print("提交按钮数量发生变化,停止处理")
|
||||
print("【商品修复产品卡片】数量",len(product_policy))
|
||||
print("【商品修复产品卡片】列表",product_policy)
|
||||
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
|
||||
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)
|
||||
if len(close_x_btn) > 0:
|
||||
close_x_btn[0].wait.displayed(timeout=5, raise_err=False)
|
||||
close_x_btn[0].click()
|
||||
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()
|
||||
|
||||
print("开始操作",submit_btn)
|
||||
print("操作的ID 为:",submit_btn.attr('id'))
|
||||
submit_btn.wait.enabled(timeout=5, raise_err=False)
|
||||
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)
|
||||
if len(need_input) > 0:
|
||||
print("需要输入注册号,不符合操作要求,跳过...")
|
||||
close_contentWrapper()
|
||||
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:
|
||||
not_start = tab.eles('xpath://div[@class="contentWrapper"]//div[@aria-label="安全证明"]//kat-label[@text="未开始"]')
|
||||
if len(not_start) == 0:
|
||||
print("安全证明-不是未开始状态,不需要操作")
|
||||
is_Continue = False
|
||||
for j in range(10):
|
||||
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
|
||||
|
||||
not_start = not_start[0]
|
||||
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 = tab.ele('xpath://div[@class="contentWrapper"]//kat-checkbox[@name="value"]',timeout=10)
|
||||
check.wait.displayed(timeout=5, raise_err=False)
|
||||
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.click()
|
||||
|
||||
@@ -175,8 +427,11 @@ class AmzoneApprove(AmamzonBase):
|
||||
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()
|
||||
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:
|
||||
option_selection_ls = tab.eles('xpath://div[@class="contentWrapper"]//div[@role="option"]',timeout=5)
|
||||
for option in option_selection_ls:
|
||||
@@ -187,29 +442,39 @@ class AmzoneApprove(AmamzonBase):
|
||||
save_btn_ls[0].click()
|
||||
|
||||
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)
|
||||
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
|
||||
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)
|
||||
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("修复商品信息处理完成!")
|
||||
tab.close()
|
||||
|
||||
|
||||
def run_page_action(self):
|
||||
print("开始执行")
|
||||
num = 0
|
||||
retry_num = 0
|
||||
already_asin = set()
|
||||
|
||||
now_page = None
|
||||
while retry_num < 3: # 最多重试3次
|
||||
# if num > 3: #测试
|
||||
# return
|
||||
@@ -235,20 +500,27 @@ class AmzoneApprove(AmamzonBase):
|
||||
print(f"当前页码: {current_page} / 总页数: {total_page}")
|
||||
except Exception as e:
|
||||
print("获取页码失败", e)
|
||||
|
||||
print("==========商品风险解决==============")
|
||||
|
||||
sku_ls = self.tab.eles("xpath://div[@data-sku]",timeout=10)
|
||||
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:
|
||||
for sku_ele in sku_ls[1:]:
|
||||
# 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
|
||||
print(f"*************** {asin} *****************")
|
||||
print(f"ASIN {asin} 存在问题,正在点击解决...")
|
||||
if asin in already_asin:
|
||||
print(f"{asin} 已经处理过了,跳过")
|
||||
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:
|
||||
# //a[text0=”添加缺失的商品详情”]
|
||||
lack_info = sku_ele.eles('xpath:.//a[text()="添加缺失的商品详情"]')
|
||||
@@ -264,6 +536,9 @@ class AmzoneApprove(AmamzonBase):
|
||||
|
||||
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.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)
|
||||
if len(request_approval_btn) > 0:
|
||||
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()
|
||||
# 新增"查看冻结原因" 的情况下,需要点击修复商品详情
|
||||
if "查看冻结原因" in label:
|
||||
repair_produ_btn_xp = '//kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]//kat-button[@variant="secondary" and @class="action-button" and contains(string(.),"修复商品信息")]'
|
||||
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)
|
||||
yield (asin,"请求批准")
|
||||
already_asin.add(asin)
|
||||
continue
|
||||
self.handle_repair_product(new_tab,headle_type="查看冻结原因")
|
||||
else:
|
||||
print(f"{i}【查看冻结原因】修复商品信息没有,不需要操作")
|
||||
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)
|
||||
@@ -310,7 +604,7 @@ class AmzoneApprove(AmamzonBase):
|
||||
|
||||
# TODO 增加 “出现警告和安全信息时候下滑” 的情况
|
||||
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:
|
||||
print("存在安全证明,正在处理...")
|
||||
safe_handle_ls[0].click()
|
||||
@@ -329,17 +623,19 @@ class AmzoneApprove(AmamzonBase):
|
||||
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.wait.displayed(timeout=3, raise_err=False)
|
||||
confirm_btn.click()
|
||||
confirm_btn = self.tab.eles('xpath://kat-panel-wrapper[@data-testid="kat-panel-wrapper-ActionPanelContent"]//kat-button[@variant="primary"]')
|
||||
if len(confirm_btn) > 0:
|
||||
confirm_btn[0].wait.displayed(timeout=3, raise_err=False)
|
||||
confirm_btn[0].click()
|
||||
|
||||
self.wait_loaded()
|
||||
|
||||
# 等待关闭按钮出现
|
||||
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)
|
||||
close_btn.click()
|
||||
if len(close_btn)>0:
|
||||
close_btn[0].click()
|
||||
except Exception as e:
|
||||
print("点击关闭按钮失败",e)
|
||||
|
||||
@@ -351,7 +647,7 @@ class AmzoneApprove(AmamzonBase):
|
||||
print(f"ASIN {asin} 存在修复商品信息按钮,正在点击...")
|
||||
self.clear_tab()
|
||||
repair_product[0].click()
|
||||
time.sleep(1)
|
||||
time.sleep(3)
|
||||
# 获取最新的tab
|
||||
new_tab = self.browser.latest_tab
|
||||
if isinstance(new_tab, str):
|
||||
@@ -366,6 +662,7 @@ class AmzoneApprove(AmamzonBase):
|
||||
|
||||
yield (asin,"处理完成")
|
||||
already_asin.add(asin)
|
||||
print(f"*********************{asin} 处理完成*************************")
|
||||
|
||||
try:
|
||||
# 全部操作完成,关闭
|
||||
@@ -556,6 +853,8 @@ class ApproveTask:
|
||||
items = data.get("items", [])
|
||||
country_codes = data.get("country_codes", [])
|
||||
risk_listing_filter = data.get("risk_listing_filter", "")
|
||||
# 测试
|
||||
# risk_listing_filter = "DetailPageRemoved" #data.get("risk_listing_filter", "")
|
||||
|
||||
if not task_id:
|
||||
self.log("任务ID为空,跳过", "WARNING")
|
||||
@@ -993,14 +1292,14 @@ if __name__ == '__main__':
|
||||
"username": "自动化_Robot",
|
||||
"password": "#20zsg25"
|
||||
}
|
||||
shop_name = "魏振峰"
|
||||
shop_name = "郭亚芳"
|
||||
country = "德国"
|
||||
kill_process('v6')
|
||||
driver = AmzoneApprove(user_info)
|
||||
browser = driver.open_shop(shop_name)
|
||||
sw_suc = driver.SwitchingCountries(country)
|
||||
driver.SwitchPage()
|
||||
risk_listing_filter = "ApprovalRequired"
|
||||
risk_listing_filter = "DetailPageRemoved"
|
||||
for _ in range(3):
|
||||
try:
|
||||
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)
|
||||
else:
|
||||
print("IP检测不通过")
|
||||
raise RuntimeError("IP检测不通过,可能是因为网络环境变化导致的,为了店铺安全不打开店铺")
|
||||
return self.browser
|
||||
|
||||
def close_store(self, browser_oauth=None):
|
||||
@@ -499,26 +500,55 @@ class AmamzonBase(ZiniaoDriver):
|
||||
|
||||
def login(self,password,username=""):
|
||||
try:
|
||||
pwd_input = self.tab.eles('xpath://input[@type="password"]',timeout=10)
|
||||
if len(pwd_input) > 0:
|
||||
pwd_input[0].input(password,clear=True)
|
||||
submit_btn = self.tab.eles('xpath://input[@id="signInSubmit"]',timeout=10)
|
||||
if len(submit_btn) > 0:
|
||||
submit_btn[0].click()
|
||||
self.tab.wait.doc_loaded()
|
||||
self.tab.wait.doc_loaded(timeout=30,raise_err=False)
|
||||
for _ in range(4):
|
||||
pwd_input = self.tab.eles('xpath://input[@type="password"]',timeout=5)
|
||||
if len(pwd_input) > 0:
|
||||
pwd_input[0].input(password,clear=True)
|
||||
submit_btn = self.tab.eles('xpath://input[@id="signInSubmit"]',timeout=5)
|
||||
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)
|
||||
opt_code_input.wait.displayed(timeout=10,raise_err=False)
|
||||
for _ in range(30):
|
||||
if opt_code_input.value is not None and opt_code_input.value.strip() != "":
|
||||
print("检测到验证码输入完成")
|
||||
submit_btn = self.tab.ele('xpath://input[@id="auth-signin-button"]',timeout=10)
|
||||
submit_btn.click()
|
||||
self.tab.wait.doc_loaded()
|
||||
return True
|
||||
time.sleep(1)
|
||||
submit_btn = self.tab.ele('xpath://input[@id="auth-signin-button"]',timeout=10)
|
||||
submit_btn.click()
|
||||
send_code = self.tab.eles('xpath://span[@id="auth-send-code" and contains(string(.),"发送一次性密码")]',timeout=5)
|
||||
print("发送一次性密码:",len(send_code))
|
||||
if len(send_code) > 0:
|
||||
print("检测到 发送一次性密码")
|
||||
send_code[0].click()
|
||||
time.sleep(1)
|
||||
self.tab.wait.doc_loaded(timeout=30,raise_err=False)
|
||||
else:
|
||||
for j in range(5):
|
||||
opt_code_input = self.tab.eles('xpath://input[@name="otpCode"]',timeout=30)
|
||||
print("验证码输入框:",len(opt_code_input))
|
||||
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:
|
||||
print("登录过程中发生异常:" + traceback.format_exc())
|
||||
return False
|
||||
|
||||
@@ -93,6 +93,7 @@ class AmzoneMatchAction(AmamzonBase):
|
||||
num = 0
|
||||
retry_num = 0
|
||||
already_asin = set()
|
||||
get_page_faild = 0
|
||||
|
||||
while retry_num < 3: # 最多重试3次
|
||||
# if num > 3: #测试
|
||||
@@ -117,9 +118,13 @@ class AmzoneMatchAction(AmamzonBase):
|
||||
else:
|
||||
total_page = 0
|
||||
print(f"【{self.mark_name}】当前页码: {current_page} / 总页数: {total_page}")
|
||||
get_page_faild = 0
|
||||
except Exception as e:
|
||||
print(f"【{self.mark_name}】获取页码失败", e)
|
||||
|
||||
get_page_faild+= 1
|
||||
if get_page_faild > 2:
|
||||
show_notification(f"【{self.mark_name}】获取页码失败超3次停止任务!")
|
||||
break
|
||||
|
||||
sku_ls = self.tab.eles("xpath://div[@data-sku]",timeout=10)
|
||||
print(f"【{self.mark_name}】获取到 {len(sku_ls)}")
|
||||
@@ -127,13 +132,13 @@ class AmzoneMatchAction(AmamzonBase):
|
||||
for sku_ele in sku_ls:
|
||||
# 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} 找到....")
|
||||
if asin in already_asin:
|
||||
print(f"【{self.mark_name}】{asin} 已经处理过了,跳过")
|
||||
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:
|
||||
print(f"【{self.mark_name}】{asin},没有推荐价格匹配按钮")
|
||||
yield (asin,"无需处理")
|
||||
@@ -230,6 +235,9 @@ class MatchTak:
|
||||
stage_index = data.get("stage_index")
|
||||
final_stage = bool(data.get("final_stage", True))
|
||||
|
||||
# 用于测试
|
||||
limit = data.get("limit",None)
|
||||
|
||||
if not task_id:
|
||||
self.log("任务ID为空,跳过", "WARNING")
|
||||
return
|
||||
@@ -272,7 +280,7 @@ class MatchTak:
|
||||
show_notification(f"开始处理店铺: {shop_name}", "info")
|
||||
|
||||
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)
|
||||
# 更新已处理店铺数
|
||||
@@ -302,7 +310,8 @@ class MatchTak:
|
||||
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, 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:
|
||||
@@ -420,7 +429,7 @@ class MatchTak:
|
||||
break
|
||||
|
||||
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:
|
||||
import traceback
|
||||
self.log(f"处理国家 {country_code} 失败: {str(e)}", "ERROR")
|
||||
@@ -449,7 +458,7 @@ class MatchTak:
|
||||
del runing_shop[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:
|
||||
@@ -582,6 +591,7 @@ class MatchTak:
|
||||
runing_task[task_id]["processed_countries"] += 1
|
||||
|
||||
self.log(f"国家 {country_name} 处理完成")
|
||||
|
||||
def post_stage_finished(self, task_id: int, user_id, stage_index):
|
||||
import requests
|
||||
from config import DELETE_BRAND_API_BASE
|
||||
|
||||
364
app/amazon/price_match.py
Normal file
364
app/amazon/price_match.py
Normal file
@@ -0,0 +1,364 @@
|
||||
import time
|
||||
import re
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from DrissionPage import Chromium, ChromiumOptions
|
||||
|
||||
from amazon.del_brand import AmamzonBase, kill_process
|
||||
from amazon.tool import show_notification,get_shop_info
|
||||
|
||||
from config import runing_task, runing_shop,base_dir
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
print("正在启动Chrome浏览器...")
|
||||
# sellersprite_plug_path = os.path.join(base_dir,"app_resource","sellersprite-extension-mv3")
|
||||
sellersprite_plug_path = os.path.join("D:\\私单交付\\maixiang_AI\\","app_resource","sellersprite-extension-mv3")
|
||||
print(sellersprite_plug_path)
|
||||
# 配置浏览器选项
|
||||
co = ChromiumOptions()
|
||||
# co.use_system_user_path(on_off=True)
|
||||
co.set_user_data_path(r"D:\私单交付\maixiang_AI\user_data\chrome_data")
|
||||
co.set_local_port(port=19890)
|
||||
co.add_extension(sellersprite_plug_path)
|
||||
# co.set_argument('--disable-features=DisableLoadExtensionCommandLineSwitch')
|
||||
# co.set_argument('--load-extension',sellersprite_plug_path)
|
||||
co.set_browser_path(r'D:\私单交付\maixiang_AI\app_resource\chrome-win\chrome.exe')
|
||||
|
||||
# 使用系统默认的用户数据目录
|
||||
# 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 close_init_popup(self):
|
||||
"""
|
||||
关闭所有的初始化弹窗
|
||||
"""
|
||||
self.tab.wait.doc_loaded(timeout=60,raise_err=True)
|
||||
footbar = self.tab.eles('xpath://footer[@class="el-dialog__footer"]',timeout=5)
|
||||
if len(footbar) > 0:
|
||||
do_not_remind = footbar[0].eles('xpath:.//input[@class="el-checkbox__original"]')
|
||||
if len(do_not_remind) > 0:
|
||||
do_not_remind[0].check()
|
||||
resume_immediately = footbar[0].eles('xpath:.//button')
|
||||
if len(resume_immediately) > 0:
|
||||
resume_immediately[0].click()
|
||||
|
||||
self.tab.wait.doc_loaded(timeout=60,raise_err=True)
|
||||
accept_btn = self.tab.eles('xpath://input[@id="sp-cc-accept"]',timeout=10)
|
||||
if len(accept_btn) > 0:
|
||||
accept_btn[0].click()
|
||||
|
||||
|
||||
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)
|
||||
|
||||
self.close_init_popup()
|
||||
|
||||
|
||||
# 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()}")
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ os.environ['APP_UPDATE_URL'] = APP_UPDATE_URL
|
||||
# 队列
|
||||
JSON_TASK_QUEUE = Queue()
|
||||
|
||||
|
||||
base_dir = os.getcwd()
|
||||
|
||||
#删除品牌,正在执行中的任务
|
||||
runing_task = {
|
||||
|
||||
|
||||
16
app/main.py
16
app/main.py
@@ -19,7 +19,6 @@ import threading
|
||||
import time
|
||||
import requests
|
||||
import subprocess
|
||||
import atexit
|
||||
|
||||
from amazon.del_brand import kill_process
|
||||
|
||||
@@ -40,21 +39,6 @@ print(f"""
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
APP_URL = "http://127.0.0.1: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):
|
||||
|
||||
Reference in New Issue
Block a user