import timeimport smtplibfrom email.mime.text import MIMETextimport requestsimport refrom datetime import datetime# 配置参数(请替换为您的实际信息)THRESHOLD = 4520.0# 目标价格阈值(例如,跌破 4400 USD/盎司,可自行修改)CHECK_INTERVAL = 60# 检查间隔(秒),建议 300(5分钟)以避免过于频繁查询EMAIL_FROM = '测试邮箱@163.com'# 发送邮箱EMAIL_TO = '测试邮箱@163.com'# 接收邮箱EMAIL_PASSWORD = '测试密码'# 163 应用专用密码(在 163 账号安全设置中生成)SMTP_SERVER = 'smtp.163.com'# 163 SMTP 服务器SMTP_PORT = 25# SSL 端口DEVICE_KEY = 'Bark 设备密钥'# 替换为你的 Bark 设备密钥classSinaGoldParser:"""新浪贵金属数据解析器(简化版)"""def__init__(self): self.headers = {'User-Agent': 'Mozilla/5.0','Referer': 'https://finance.sina.com.cn' }defparse_single(self, symbol: str, data_str: str) -> dict:"""解析单个品种数据""" fields = data_str.split(',')# 基本字段 price = float(fields[0]) if fields[0] else0 bid = float(fields[2]) if fields[2] else price ask = float(fields[3]) if fields[3] else price high = float(fields[4]) if fields[4] else price low = float(fields[5]) if fields[5] else price time_str = fields[6] if fields[6] else"00:00:00" open_price = float(fields[7]) if fields[7] else price prev_close = float(fields[8]) if fields[8] else price date = fields[12] if len(fields) > 12else datetime.now().strftime('%Y-%m-%d')# 品种名称 name = fields[13] if len(fields) > 13else symbol# 计算涨跌 change = price - prev_close change_percent = (change / prev_close * 100) if prev_close > 0else0return {'symbol': symbol,'name': name,'price': price,'change': change,'change_percent': change_percent,'bid': bid,'ask': ask,'high': high,'low': low,'open': open_price,'prev_close': prev_close,'time': time_str,'date': date,'spread': ask - bid }defparse_all(self, raw_text: str) -> dict:"""解析全部数据""" results = {} pattern = r'var hq_str_(\w+)="([^"]+)"'for match in re.findall(pattern, raw_text): symbol, data_str = match# print(symbol,'---',data_str) results[symbol] = self.parse_single(symbol, data_str)return resultsdeffetch_realtime(self, symbols=None):"""获取实时数据"""if symbols isNone: symbols = ['hf_XAU', 'hf_XAG', 'hf_GC', 'hf_SI'] url = f"http://hq.sinajs.cn/list={','.join(symbols)}"try: resp = requests.get(url, headers=self.headers, timeout=5) resp.encoding = 'gb2312'return self.parse_all(resp.text)except Exception as e: print(f"获取数据失败: {e}")return {}defsend_email(price):""" 发送163邮箱提醒 """ subject = 'COMEX 黄金价格警报!' body = f'注意:COMEX黄金期货价格已跌至 {price:.2f} USD/盎司,低于阈值 {THRESHOLD:.2f}!\n' \f'当前时间:{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}' msg = MIMEText(body, 'plain', 'utf-8') msg['Subject'] = subject msg['From'] = EMAIL_FROM msg['To'] = EMAIL_TOtry:with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server: server.starttls() # 启用 TLS server.login(EMAIL_FROM, EMAIL_PASSWORD) server.send_message(msg) print('163邮箱提醒发送成功!')except Exception as e: print(f'邮件发送失败:{e}(检查授权码、网络或SMTP设置)')defsend_bark_message(device_key, title, body, **kwargs):""" 发送 Bark 推送消息 参数: - device_key: Bark 设备密钥 - title: 消息标题 - body: 消息内容 - kwargs: 其他可选参数 """# Bark API 基础 URL base_url = "https://api.day.app"# 构建请求 URL url = f"{base_url}/{device_key}/{title}/{body}"# 可选参数处理 params = {}if'url'in kwargs: params['url'] = kwargs['url']if'group'in kwargs: params['group'] = kwargs['group']if'icon'in kwargs: params['icon'] = kwargs['icon']if'level'in kwargs: params['level'] = kwargs['level'] # active, timeSensitive, passive# 发送请求try: response = requests.get(url, params=params)if response.status_code == 200: result = response.json()if result.get('code') == 200: print("Bark 消息发送成功!")returnTrueelse: print(f"发送失败: {result.get('message')}")returnFalseelse: print(f"HTTP 错误: {response.status_code}")returnFalseexcept Exception as e: print(f"请求异常: {e}")returnFalsedefmain():"""主函数 - 简单使用示例""" parser = SinaGoldParser()## 测试数据# test_data = '''# var hq_str_hf_XAU="4445.35,4456.320,4445.35,4445.70,4466.31,4407.73,23:13:00,4456.32,4460.20,0,0,0,2026-01-08,伦敦金(现货黄金)";# var hq_str_hf_GC="4431.289,,4432.400,4432.800,4475.200,4415.000,21:58:33,4462.500,4467.100,0,2,2,2026-01-08,纽约黄金,0";# '''## print("📊 测试数据解析:")# data = parser.parse_all(test_data)## for symbol, info in data.items():# print(f"\n{symbol} - {info['name']}")# print(f" 价格: ${info['price']:.2f}")# print(f" 涨跌: ${info['change']:+.2f} ({info['change_percent']:+.2f}%)")# print(f" 时间: {info['date']} {info['time']}")## print("\n" + "=" * 50)# # 发送简单消息# send_bark_message(# device_key=DEVICE_KEY,# title="系统通知",# body="这是一条测试消息"# )# # 发送带链接的消息# send_bark_message(# device_key=DEVICE_KEY,# title="监控提醒",# body="服务器 CPU 使用率超过 90%",# url="http://192.168.1.100:3000", # 点击通知跳转的链接# group="系统监控", # 消息分组# level="timeSensitive" # 通知级别# )# 获取实时数据 print("\n🌐 获取实时数据...")try:whileTrue: time.sleep(CHECK_INTERVAL) realtime_data = parser.fetch_realtime(['hf_GC'])if realtime_data:for symbol, info in realtime_data.items(): arrow = "↑"if info['change'] >= 0else"↓" print(f" {info['name']}: ${info['price']:.2f}{arrow} ({info['change_percent']:+.2f}%)")if info['price'] <= THRESHOLD: print(f" ⚠️ 价格已低于 {THRESHOLD}")# 邮件提醒 send_email(info['price'])# Bark 推送 send_bark_message( device_key=DEVICE_KEY, title="黄价监控提醒", body=f"当前黄金价格已低于{THRESHOLD},当前价格为{info['price']:.2f}", group="黄价监控", # 消息分组 )except Exception as e: print(f"获取实时数据失败: {e}")if __name__ == "__main__": main()