This commit is contained in:
super
2026-05-07 16:22:42 +08:00
513 changed files with 7379 additions and 151 deletions

View File

@@ -1,3 +1,4 @@
base_url=http://8.136.19.173:15124
workflow_id=7608812635877900322
mysql_host=8.136.19.173
mysql_user=aiimage

View File

@@ -352,6 +352,8 @@ class AmzoneApprove(AmamzonBase):
print(f"没有获取到 ASIN 商品,重试{retry_num}/{max_retry_num}")
self.tab.refresh()
self.tab.wait.doc_loaded(raise_err=False, timeout=120)
if retry_num == max_retry_num:
raise RuntimeError(f"与页面的连接已断开,没有获取到 ASIN 商品,重试{retry_num}/{max_retry_num}")
continue
# for sku_ele in sku_ls[0:2]:
for sku_ele in sku_ls:

View File

@@ -52,6 +52,7 @@ class ChromeAmzoneBase:
print("正在启动chromium浏览器...")
# 配置浏览器选项
co = ChromiumOptions()
co.no_imgs(True)
user_data_path = os.path.join(base_dir, "user_data", "chrome_data")
if not os.path.exists(user_data_path):
os.makedirs(user_data_path, exist_ok=True)
@@ -80,6 +81,11 @@ class ChromeAmzoneBase:
关闭所有的初始化弹窗
"""
self.tab.wait.doc_loaded(timeout=60, raise_err=True)
continue_shipping = self.tab.eles('xpath://button[@alt="Continue shopping"]',timeout=3)
if len(continue_shipping) > 0:
continue_shipping[0].click()
time.sleep(0.5)
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"]')

View File

@@ -111,15 +111,10 @@ class ChromeAmzone(ChromeAmzoneBase):
class SpiderTask(TaskBase):
task_name = "亚马逊采集"
mark_name = "亚马逊采集"
def __init__(self, user_info: dict = None):
super().__init__(user_info)
self.result_api_module = "appearance-patent"
@staticmethod
class SpiderTask(TaskBase):
task_name = "亚马逊采集"
@staticmethod
def group_by_id_prefix(data):
"""
根据每条数据的 id 字段进行分组:
@@ -164,20 +159,18 @@ class SpiderTask(TaskBase):
})
return normalized
def process_task(self, task_data: dict):
"""处理审批任务主入口
Args:
task_data: 任务数据
"""
task_id = None
try:
data = task_data.get("data", {})
task_id = data.get("taskId")
groups = self.normalize_groups(data)
self.result_api_module = "similar-asin" if task_data.get("type") == "similar-asin-run" else "appearance-patent"
# 用于测试
def process_task(self, task_data: dict):
"""处理审批任务主入口
Args:
task_data: 任务数据
"""
try:
data = task_data.get("data", {})
task_id = data.get("taskId")
groups = self.normalize_groups(data)
# 用于测试
limit = data.get("limit", None)
if not task_id:
@@ -308,22 +301,22 @@ class SpiderTask(TaskBase):
runing_task[task_id]["status"] = "failed"
runing_task[task_id]["error"] = str(e)
def post_result(self, task_id: int, chunkIndex:int,chunkTotal: int, asin: str, error:str="",
item_data=None,
is_done: bool = False):
"""回传处理结果到API
"""
def post_result(self, task_id: int, chunkIndex:int,chunkTotal: int, asin: str, error:str="",
item_data:dict={},
is_done: bool = False):
"""回传处理结果到API
"""
url = f"{DELETE_BRAND_API_BASE}/api/{self.result_api_module}/tasks/{task_id}/result"
url = f"{DELETE_BRAND_API_BASE}/api/appearance-patent/tasks/{task_id}/result"
payload ={
"submissionId": f"{task_id}",
"chunkIndex": chunkIndex,
"chunkTotal": chunkTotal,
"error": error,
"groups": item_data or [],
"done": is_done
}
payload ={
"submissionId": f"{task_id}",
"chunkIndex": chunkIndex,
"chunkTotal": chunkTotal,
"error": error,
"groups": item_data,
"done": is_done
}
max_retries = 3
for retry in range(max_retries):
@@ -333,13 +326,13 @@ class SpiderTask(TaskBase):
self.log(f"尝试回传结果 (第 {retry + 1}/{max_retries} 次)")
self.log(f"回传URL: {url}")
self.log(f"回传数据: {payload}")
response = requests.post(
url,
data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
headers={"Content-Type": "application/json; charset=utf-8"},
timeout=request_timeout,
verify=False
)
response = requests.post(
url,
json=payload,
headers={"Content-Type": "application/json"},
timeout=request_timeout,
verify=False
)
self.log(f"回传结果: {response.text}")
data = response.json() if response.text else {}
if response.status_code == 200 and isinstance(data, dict) and data.get("success"):

View File

@@ -12,7 +12,7 @@ from amazon.price_match import PriceTask
from amazon.asin_status import StatusTask
from amazon.patrol_delete import PatrolDeleteTask
from amazon.detail_spider import SpiderTask
from amazon.similar_asin import SimilarAsinTask
from amazon.amazon_base import kill_process
@@ -62,11 +62,11 @@ class TaskMonitor:
"product-risk-resolve-run" : "产品风险审批",
"shop-match-run" : "匹配价格",
"price-track-run" : "跟价",
"query-asin-run" : "状态查询",
"patrol-delete-run" : "巡店删除",
"appearance-patent-run" : "亚马逊采集",
"similar-asin-run" : "亚马逊采集",
}
"query-asin-run" : "状态查询",
"patrol-delete-run" : "巡店删除",
"appearance-patent-run" : "亚马逊采集",
"similar-asin-run" : "相似ASIN"
}
try:
while self.running:
try:
@@ -140,6 +140,7 @@ class TaskMonitor:
"状态查询" : StatusTask,
"巡店删除" : PatrolDeleteTask,
"亚马逊采集" : SpiderTask,
"相似ASIN" : SimilarAsinTask
}
self.log(f"线程 {id(task_data)} 开始处理产品风险审批任务...")
# 创建ApproveTask实例并处理任务

View File

@@ -37,7 +37,7 @@ class RepricingLogic:
# 0.8 到 10.5 之间全部是在减1
return rank1_price - (diff + 1.0)
else:
return None # 相差10.5以上,跳过
return rank1_price - 10.5 # 相差10.5以上,跳过
@staticmethod
def situation_2_own_buybox(my_price, rank2_price):
@@ -582,6 +582,8 @@ class AmzonePriceMatch(AmamzonBase):
self.log(f"没有获取到 ASIN 商品,重试{retry_num}/{max_retry_num}")
self.tab.refresh()
self.tab.wait.doc_loaded(raise_err=False, timeout=120)
if retry_num == max_retry_num:
raise RuntimeError(f"与页面的连接已断开,没有获取到 ASIN 商品,重试{retry_num}/{max_retry_num}")
continue
# for sku_ele in sku_ls[0:2]:
@@ -977,7 +979,7 @@ class PriceTask(TaskBase):
country_name = self.country_info.get(country_code, country_code)
info_mes = f"开始处理国家: {country_name} ({country_code}),需要跳过的asin {skip_asin}"
self.log(info_mes)
show_notification(info_mes, "info")
show_notification(f"开始处理国家:{country_name}", "info")
# 更新当前处理的国家
if task_id in runing_task:
@@ -1216,7 +1218,7 @@ class PriceTask(TaskBase):
max_retries = 3
for retry in range(max_retries):
try:
print("================【跟价】=====================")
self.log("================【跟价】=====================")
self.log(f"尝试回传结果 (第 {retry + 1}/{max_retries} 次)")
self.log(f"回传URL: {url}")
self.log(f"回传数据: {payload}")
@@ -1234,11 +1236,11 @@ class PriceTask(TaskBase):
return
else:
self.log(f"结果回传失败,状态码: {response.status_code}", "WARNING")
print("=====================================")
self.log("=====================================")
except Exception as e:
self.log(f"调用API异常: {str(e)}", "ERROR")
print("=====================================")
self.log("=====================================")
# 如果还有重试机会,等待后继续
if retry < max_retries - 1:

View File

@@ -1,3 +1,5 @@
# encoding utf-8
import json
from pathlib import Path
import base64
@@ -20,6 +22,17 @@ from amazon.chrome_base import ChromeAmzoneBase
from config import runing_task, runing_shop,base_dir,DELETE_BRAND_API_BASE
try:
from config import proxy_url as CONFIG_PROXY_URL, proxy_mode as CONFIG_PROXY_MODE
except ImportError:
CONFIG_PROXY_URL = None
CONFIG_PROXY_MODE = 1
# Forbidden 后 3 分钟内统一使用代理:记录代理生效截止时间与当前代理
_FORBIDDEN_PROXY_UNTIL = 0.0
_FORBIDDEN_PROXY_DICT = None
_FORBIDDEN_PROXY_MINUTES = 0.5
class ChromeAmzone(ChromeAmzoneBase):
mark_name = "亚马逊相似ASIN"
@@ -81,6 +94,8 @@ class ChromeAmzone(ChromeAmzoneBase):
标题 :
"""
global _FORBIDDEN_PROXY_UNTIL, _FORBIDDEN_PROXY_DICT
headers = {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
@@ -126,11 +141,93 @@ class ChromeAmzone(ChromeAmzoneBase):
data = {
"imageBase64" : imageBase64
}
response = requests.post(url, headers=headers, params=params, json=data, impersonate="chrome101",
cookies=cookie)
response.encoding = "utf-8"
data = response.json()
return data
proxies = None
# 若 3 分钟内曾出现 Forbidden则直接使用当时保存的代理
now = time.time()
if now < _FORBIDDEN_PROXY_UNTIL and _FORBIDDEN_PROXY_DICT:
proxies = _FORBIDDEN_PROXY_DICT
print("处于 Forbidden 代理窗口内,直接使用代理", proxies)
# 发送第一次请求
try:
response = requests_frp.post(url, headers=headers, params=params, json=data, impersonate="chrome101",
cookies=cookie, proxies=proxies)
response.encoding = "utf-8"
# 检查响应状态码和数据有效性
need_retry = False
if response.status_code != 200:
print(f"请求失败,状态码: {response.status_code}")
need_retry = True
else:
try:
result_data = response.json()
# 检查是否获取到有效数据
if not result_data or not isinstance(result_data, dict):
print("返回数据为空或格式不正确")
need_retry = True
elif "Forbidden" in response.text or "Too Many Requests" in response.text:
print("返回Forbidden或Too Many Requests")
need_retry = True
except Exception as e:
print(f"解析响应JSON失败: {e}")
need_retry = True
# 如果需要重试且配置了代理URL
if need_retry and CONFIG_PROXY_URL and not proxies:
try:
proxy_resp = requests.get(CONFIG_PROXY_URL, timeout=10)
print("代理请求结果->", proxy_resp.text)
# 模式 2账号密码代理接口返回 JSON
if CONFIG_PROXY_MODE == 2:
resp_json = proxy_resp.json()
proxy_list = resp_json.get("data", {}).get("list") or []
first_item = proxy_list[0] if proxy_list else None
if first_item:
ip = first_item.get("ip")
port = first_item.get("port")
account = first_item.get("account")
password = first_item.get("password")
if ip and port and account and password:
auth_proxy = f"{account}:{password}@{ip}:{port}"
print("获取到账号密码代理:", auth_proxy)
proxies = {
"http": f"http://{auth_proxy}",
"https": f"http://{auth_proxy}",
}
# 默认模式 1普通 IP:port 文本
if CONFIG_PROXY_MODE != 2:
proxy_ip = (proxy_resp.text or "").strip()
if proxy_ip:
proxies = {
"http": f"http://{proxy_ip}",
"https": f"http://{proxy_ip}",
}
if proxies:
print("使用代理重试请求")
response = requests_frp.post(url, headers=headers, params=params, json=data,
impersonate="chrome101", cookies=cookie, proxies=proxies)
response.encoding = "utf-8"
print("代理重试结果状态码:", response.status_code)
# 记录 3 分钟内都使用该代理
_FORBIDDEN_PROXY_UNTIL = now + _FORBIDDEN_PROXY_MINUTES * 60
_FORBIDDEN_PROXY_DICT = proxies
except Exception as e:
print("获取代理或重试失败:", e)
# 返回最终结果
result_data = response.json()
return result_data
except Exception as e:
print(f"get_aliprice_data 请求异常: {e}")
return {}
def _scrape_data(self):
"""
@@ -276,8 +373,8 @@ class SimilarAsinTask(TaskBase):
return list(grouped.values())
@staticmethod
def normalize_groups(data):
@staticmethod
def normalize_groups(data):
groups = data.get("groups")
if isinstance(groups, list) and len(groups) > 0:
return groups
@@ -299,71 +396,71 @@ class SimilarAsinTask(TaskBase):
"displayId": first.get("displayId") or item_id,
"items": items,
})
return normalized
def fetch_parsed_payload(self, task_id, user_id=1):
url = f"{DELETE_BRAND_API_BASE}/api/similar-asin/tasks/{task_id}/parsed-payload"
response = requests.get(url, params={"user_id": user_id}, timeout=300, verify=False)
response.raise_for_status()
payload = response.json() if response.text else {}
if isinstance(payload, dict) and payload.get("success"):
return payload.get("data") or {}
raise RuntimeError(f"获取货源查询解析载荷失败: {payload}")
return normalized
@staticmethod
def _count_payload_rows(data):
rows = data.get("rows") or data.get("items") or []
if isinstance(rows, list) and rows:
return len(rows)
groups = data.get("groups") or []
if not isinstance(groups, list):
return 0
total = 0
for group in groups:
if isinstance(group, dict) and isinstance(group.get("items"), list):
total += len(group.get("items"))
return total
def _merge_parsed_payload(self, data, parsed_payload):
payload_rows = parsed_payload.get("allItems") or parsed_payload.get("items") or []
merged = {
**data,
"groups": parsed_payload.get("groups") or [],
"rows": payload_rows,
}
if parsed_payload.get("aiPrompt"):
merged["prompt"] = parsed_payload.get("aiPrompt")
if parsed_payload.get("apiKey") and not merged.get("api_key"):
merged["api_key"] = parsed_payload.get("apiKey")
return merged
def process_task(self, task_data: dict):
def fetch_parsed_payload(self, task_id, user_id=1):
url = f"{DELETE_BRAND_API_BASE}/api/similar-asin/tasks/{task_id}/parsed-payload"
response = requests.get(url, params={"user_id": user_id}, timeout=300, verify=False)
response.raise_for_status()
payload = response.json() if response.text else {}
if isinstance(payload, dict) and payload.get("success"):
return payload.get("data") or {}
raise RuntimeError(f"获取货源查询解析载荷失败: {payload}")
@staticmethod
def _count_payload_rows(data):
rows = data.get("rows") or data.get("items") or []
if isinstance(rows, list) and rows:
return len(rows)
groups = data.get("groups") or []
if not isinstance(groups, list):
return 0
total = 0
for group in groups:
if isinstance(group, dict) and isinstance(group.get("items"), list):
total += len(group.get("items"))
return total
def _merge_parsed_payload(self, data, parsed_payload):
payload_rows = parsed_payload.get("allItems") or parsed_payload.get("items") or []
merged = {
**data,
"groups": parsed_payload.get("groups") or [],
"rows": payload_rows,
}
if parsed_payload.get("aiPrompt"):
merged["prompt"] = parsed_payload.get("aiPrompt")
if parsed_payload.get("apiKey") and not merged.get("api_key"):
merged["api_key"] = parsed_payload.get("apiKey")
return merged
def process_task(self, task_data: dict):
"""处理审批任务主入口
Args:
task_data: 任务数据
"""
try:
data = task_data.get("data", {})
task_id = data.get("taskId")
if task_id:
queued_rows = self._count_payload_rows(data)
try:
parsed_payload = self.fetch_parsed_payload(task_id, data.get("user_id") or data.get("userId") or 1)
data = self._merge_parsed_payload(data, parsed_payload)
self.log(
f"similar asin task {task_id} loaded full parsed payload from Java, queuedRows={queued_rows}, fullRows={self._count_payload_rows(data)}"
)
except Exception as e:
if not queued_rows:
raise
self.log(
f"similar asin task {task_id} failed to load full parsed payload, fallback to queued rows={queued_rows}: {e}",
"WARNING"
)
groups = self.normalize_groups(data)
data = task_data.get("data", {})
task_id = data.get("taskId")
if task_id:
queued_rows = self._count_payload_rows(data)
try:
parsed_payload = self.fetch_parsed_payload(task_id, data.get("user_id") or data.get("userId") or 1)
data = self._merge_parsed_payload(data, parsed_payload)
self.log(
f"similar asin task {task_id} loaded full parsed payload from Java, queuedRows={queued_rows}, fullRows={self._count_payload_rows(data)}"
)
except Exception as e:
if not queued_rows:
raise
self.log(
f"similar asin task {task_id} failed to load full parsed payload, fallback to queued rows={queued_rows}: {e}",
"WARNING"
)
groups = self.normalize_groups(data)
if not task_id:
self.log("任务ID为空跳过", "WARNING")
@@ -439,6 +536,8 @@ class SimilarAsinTask(TaskBase):
"country": i.get("country"),
"url": return_data.get("image_url"),
"title": return_data.get("title"),
"done": False,
"urls" : [i.get("ori_picture") for i in return_data.get("similar_data")]
}
for i in items
]
@@ -452,6 +551,7 @@ class SimilarAsinTask(TaskBase):
"displayId": gp.get("displayId"),
"items": group_item
}
print("================")
result.append(res)
print("================")
@@ -500,10 +600,10 @@ class SimilarAsinTask(TaskBase):
"""回传处理结果到API
"""
url = f"{DELETE_BRAND_API_BASE}/api/similar-asin/tasks/{task_id}/result"
url = f"{DELETE_BRAND_API_BASE}/api/similar-asin/tasks/{task_id}/result"
payload ={
"submissionId": f"{int(time.time())}",
"submissionId": f"{task_id}",
"chunkIndex": chunkIndex,
"chunkTotal": chunkTotal,
"error": error,
@@ -519,13 +619,13 @@ class SimilarAsinTask(TaskBase):
self.log(f"尝试回传结果 (第 {retry + 1}/{max_retries} 次)")
self.log(f"回传URL: {url}")
self.log(f"回传数据: {payload}")
response = requests.post(
url,
data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
headers={"Content-Type": "application/json; charset=utf-8"},
timeout=request_timeout,
verify=False
)
response = requests.post(
url,
json=payload,
headers={"Content-Type": "application/json"},
timeout=request_timeout,
verify=False
)
self.log(f"回传结果: {response.text}")
data = response.json() if response.text else {}
if response.status_code == 200 and isinstance(data, dict) and data.get("success"):
@@ -553,6 +653,263 @@ if __name__ == '__main__':
country="英国", asin="B0F79LCB3X", total_page=2
)
print(resp)
# task_data = {
# "type": "similar-asin-run",
# "ts": 1778038688824,
# "data": {
# "taskId": 6850,
# "api_key": "sk-EMcDFg36zCeWUtCbRzKUbrRZyNeC6M4KBhY6fAVcNP7GG4xI",
# "groups": [
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "groupKey": "similar-asin:6850",
# "baseId": "",
# "displayId": "1",
# "items": [
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::2",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::1@2",
# "id": "1",
# "asin": "B0D792ND9V",
# "country": "英国",
# "price": "12.29",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::3",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_1",
# "asin": "B0D14L34S7",
# "country": "英国",
# "price": "14.88",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::4",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_2",
# "asin": "B0D14N8FJY",
# "country": "英国",
# "price": "15.36",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::5",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_3",
# "asin": "B0D14NBL5D",
# "country": "英国",
# "price": "14.87",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::6",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_4",
# "asin": "B0D14M5X4J",
# "country": "英国",
# "price": "14.41",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::7",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::3@7",
# "id": "3_1",
# "asin": "B0CWQFZMGY",
# "country": "英国",
# "price": "17.05",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::8",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::3@7",
# "id": "3_2",
# "asin": "B0CX8D68L3",
# "country": "英国",
# "price": "16.46",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::9",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::4@9",
# "id": "4_1",
# "asin": "B0CX87XXWJ",
# "country": "英国",
# "price": "17.54",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::10",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::5@10",
# "id": "5_1",
# "asin": "B0CR3PMR8L",
# "country": "英国",
# "price": "16.74",
# "url": "",
# "title": "",
# "target_urls": []
# }
# ]
# }
# ],
# "rows": [
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::2",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::1@2",
# "id": "1",
# "asin": "B0D792ND9V",
# "country": "英国",
# "price": "12.29",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::3",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_1",
# "asin": "B0D14L34S7",
# "country": "英国",
# "price": "14.88",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::4",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_2",
# "asin": "B0D14N8FJY",
# "country": "英国",
# "price": "15.36",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::5",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_3",
# "asin": "B0D14NBL5D",
# "country": "英国",
# "price": "14.87",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::6",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::2@3",
# "id": "2_4",
# "asin": "B0D14M5X4J",
# "country": "英国",
# "price": "14.41",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::7",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::3@7",
# "id": "3_1",
# "asin": "B0CWQFZMGY",
# "country": "英国",
# "price": "17.05",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::8",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::3@7",
# "id": "3_2",
# "asin": "B0CX8D68L3",
# "country": "英国",
# "price": "16.46",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::9",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::4@9",
# "id": "4_1",
# "asin": "B0CX87XXWJ",
# "country": "英国",
# "price": "17.54",
# "url": "",
# "title": "",
# "target_urls": []
# },
# {
# "sourceFileKey": "cdfa437df62b40a0bde5682a05c1f6a3",
# "sourceFilename": "17(1) - 副本1.xlsx",
# "rowToken": "cdfa437df62b40a0bde5682a05c1f6a3::row::10",
# "groupKey": "cdfa437df62b40a0bde5682a05c1f6a3::5@10",
# "id": "5_1",
# "asin": "B0CR3PMR8L",
# "country": "英国",
# "price": "16.74",
# "url": "",
# "title": "",
# "target_urls": []
# }
# ]
# }
# }
# sim_asin = SimilarAsinTask({})
# sim_asin.process_task(task_data)

View File

@@ -124,7 +124,6 @@ def remove_special_characters(text: str) -> str:
return cleaned
def split_currency_values(currency_str: str) -> tuple[float, float]:
"""
将包含两个货币值的字符串拆分成两个浮点数。

Binary file not shown.

View File

@@ -0,0 +1,2 @@
{
}

View File

@@ -0,0 +1,12 @@
{
"epochs": [ {
"calculation_time": "13422512990906273",
"config_version": 0,
"model_version": "0",
"padded_top_topics_start_index": 0,
"taxonomy_version": 0,
"top_topics_and_observing_domains": [ ]
} ],
"hex_encoded_hmac_key": "57AA4C4DDB252DC6FA3F442115CBE555E87CBF826CA55E9705992FE3B34B6B58",
"next_scheduled_calculation_time": "13423117790906516"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Some files were not shown because too many files have changed in this diff Show More