modified: amazon/approve.py modified: amazon/chrome_base.py modified: amazon/detail_spider.py modified: amazon/main.py modified: amazon/price_match.py modified: amazon/similar_asin.py modified: amazon/tool.py new file: amazon/user_data/chrome_data/BrowserMetrics-spare.pma new file: amazon/user_data/chrome_data/BrowserMetrics/BrowserMetrics-69FAEF07-558.pma
161 lines
6.0 KiB
Python
161 lines
6.0 KiB
Python
# 导入 webview 用于前端通知
|
||
try:
|
||
import webview
|
||
except ImportError:
|
||
webview = None
|
||
|
||
|
||
import requests
|
||
from urllib.parse import quote
|
||
import re
|
||
|
||
|
||
def show_notification(message: str, message_type: str = "error"):
|
||
"""显示 pywebview 顶层通知(5秒后自动消失)
|
||
|
||
Args:
|
||
message: 通知消息
|
||
message_type: 消息类型 (success/warning/error/info)
|
||
"""
|
||
if webview and webview.windows:
|
||
try:
|
||
# 转义单引号,防止 JavaScript 语法错误
|
||
safe_message = message.replace("'", "\\'").replace('"', '\\"').replace('\n', '\\n')
|
||
|
||
# 设置通知样式颜色
|
||
color_map = {
|
||
'success': '#67C23A',
|
||
'warning': '#E6A23C',
|
||
'error': '#F56C6C',
|
||
'info': '#909399'
|
||
}
|
||
bg_color = color_map.get(message_type, '#F56C6C')
|
||
|
||
# 构建前端通知的 JavaScript 代码 - 创建原生 HTML 通知
|
||
js_code = f"""
|
||
(function() {{
|
||
// 移除已存在的通知
|
||
var existingNotif = document.getElementById('pywebview-notification');
|
||
if (existingNotif) {{
|
||
existingNotif.remove();
|
||
}}
|
||
|
||
// 创建通知容器
|
||
var notif = document.createElement('div');
|
||
notif.id = 'pywebview-notification';
|
||
notif.style.cssText = 'position: fixed; top: 20px; left: 50%; transform: translateX(-50%); ' +
|
||
'background: {bg_color}; color: white; padding: 12px 20px; border-radius: 4px; ' +
|
||
'box-shadow: 0 2px 12px rgba(0,0,0,0.3); z-index: 99999; font-size: 14px; ' +
|
||
'max-width: 600px; word-wrap: break-word; display: flex; align-items: center; gap: 10px;';
|
||
|
||
// 添加消息内容
|
||
var msgSpan = document.createElement('span');
|
||
msgSpan.textContent = '{safe_message}';
|
||
notif.appendChild(msgSpan);
|
||
|
||
// 添加关闭按钮
|
||
var closeBtn = document.createElement('span');
|
||
closeBtn.innerHTML = '×';
|
||
closeBtn.style.cssText = 'cursor: pointer; font-size: 18px; font-weight: bold; margin-left: 10px;';
|
||
closeBtn.onclick = function() {{ notif.remove(); }};
|
||
notif.appendChild(closeBtn);
|
||
|
||
// 添加到页面
|
||
document.body.appendChild(notif);
|
||
|
||
// 5秒后自动消失
|
||
setTimeout(function() {{
|
||
if (notif && notif.parentNode) {{
|
||
notif.style.transition = 'opacity 0.3s';
|
||
notif.style.opacity = '0';
|
||
setTimeout(function() {{ notif.remove(); }}, 300);
|
||
}}
|
||
}}, 5000);
|
||
}})();
|
||
"""
|
||
# 在第一个窗口中执行 JavaScript
|
||
webview.windows[0].evaluate_js(js_code)
|
||
except Exception as e:
|
||
print(f"显示通知失败: {str(e)}")
|
||
|
||
|
||
|
||
|
||
def get_shop_info(shop_name: str, base_url: str = "http://8.136.19.173:18080") -> requests.Response:
|
||
"""
|
||
调用商铺凭证接口
|
||
:param shop_name: 商铺名称,将自动进行 URL 编码
|
||
:param base_url: API 基础地址,默认从 curl 中提取
|
||
:return: requests.Response 对象
|
||
"""
|
||
url = f"{base_url}/api/admin/shop-manages/credential"
|
||
params = {"shopName": shop_name}
|
||
|
||
headers = {
|
||
"Accept": "*/*",
|
||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||
"Cache-Control": "no-cache",
|
||
"Connection": "keep-alive",
|
||
"Pragma": "no-cache",
|
||
"Referer": "http://8.136.19.173:18080/doc.html",
|
||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
||
"X-Internal-Token": "59c6691199917a2095827b5188502029",
|
||
}
|
||
|
||
response = requests.get(
|
||
url,
|
||
params=params,
|
||
headers=headers,
|
||
verify=False,
|
||
timeout=30
|
||
)
|
||
return response
|
||
|
||
|
||
|
||
def remove_special_characters(text: str) -> str:
|
||
"""
|
||
去除字符串中的特殊字符,只保留数字、小数点和负号。
|
||
例如:'£24.55' -> '24.55'
|
||
"""
|
||
# 匹配所有允许的字符:数字、小数点、负号
|
||
# 注意:负号必须位于开头才合法,但这里只做字符保留,不做格式校验
|
||
cleaned = re.sub(r'[^0-9.-]', '', text)
|
||
return cleaned
|
||
|
||
|
||
def split_currency_values(currency_str: str) -> tuple[float, float]:
|
||
"""
|
||
将包含两个货币值的字符串拆分成两个浮点数。
|
||
参数:
|
||
currency_str (str): 格式如 "€22.64 + €0.00" 的字符串,中间以 '+' 分隔,
|
||
每部分可包含任意货币符号或前缀/后缀。
|
||
返回:
|
||
tuple[float, float]: 两个数值,顺序与字符串中的出现顺序一致。
|
||
异常:
|
||
ValueError: 如果字符串不包含正好两个部分,或者任一部分中无法提取到数值。
|
||
"""
|
||
# 按第一个 '+' 分割,最多分为两部分
|
||
parts = currency_str.split('+', 1)
|
||
if len(parts) != 2:
|
||
raise ValueError("字符串必须包含两个由 '+' 分隔的部分")
|
||
|
||
# 匹配整数或浮点数(可选负号)
|
||
number_pattern = r'-?\d+(?:\.\d+)?'
|
||
values = []
|
||
|
||
for part in parts:
|
||
# 去除首尾空格
|
||
part = part.strip()
|
||
match = re.search(number_pattern, part)
|
||
if not match:
|
||
raise ValueError(f"无法从 '{part}' 中提取数值")
|
||
values.append(float(match.group()))
|
||
|
||
return tuple(values)
|
||
|
||
|
||
if __name__ == '__main__':
|
||
cu_str = "€58.44 + €0.00 匹配"
|
||
res = split_currency_values(cu_str)
|
||
print(sum(res)) |