""" # lottery 4 框架玄学分析 — 真实脚本 (替代 model 手动推演, 动态取 Qi) 基于 references/analysis-example-073/074/075.md 的 3 步推演流程 【2026-08-02 修复】sol.2344a.cc 出现 "Cann't connect to DB!" 时静默失败 → 加 fail-fast 错误检测 (check_db_error) """ import os import sys import json import time import datetime import urllib.request # === 硬规则 (跟 SKILL.md 一致) === TIMEZONE_BEIJING = "北京时间 (UTC+8)" # === 数据源 === SOL_BASE = "https://sol.2344a.cc" V_XG_URL = "https://btc.tktk.app/data/v_xg.json" # === 错误检测 pattern (2026-08-02 实战发现) === DB_ERROR_PATTERNS = [ "Cann't connect to DB!", "Can't connect to DB!", "database connection failed", "internal server error", "数据库连接失败", ] def check_db_error(data, source_name): """检测 sol.2344a.cc / tktk 临时 DB 错误 → fail-fast""" if not isinstance(data, str): return data # 非字符串, 可能是 JSON for pattern in DB_ERROR_PATTERNS: if pattern.lower() in data.lower(): raise RuntimeError( f"[{source_name}] DB 错误: {data[:200]!r}\n" f" 触发 pattern: {pattern!r}\n" f" 修复: 等 sol.2344a.cc 恢复, 或用本地 SQLite draws 表作为 fallback" ) if "页面使用Vue.js动态加载" in data: raise RuntimeError( f"[{source_name}] Vue.js 动态加载 (cron 模式拿不到数据), " f"改用 browser_snapshot(full=true) 或 fallback 方案" ) return data def fetch_v_xg(): """拉 v_xg.json (Qi=最新已开, Data.1-7=Qi-2 已开 (不是 Qi-1))""" try: req = urllib.request.Request(V_XG_URL, headers={'User-Agent': 'Mozilla/5.0'}) with urllib.request.urlopen(req, timeout=15) as r: data = json.loads(r.read().decode('utf-8')) # 检查 Qi 字段 (防止 DB 错误 JSON) if 'Qi' not in data or data.get('Qi') == '?': raise RuntimeError(f"v_xg.json 缺 Qi 字段: {data!r}") return data except RuntimeError: raise except Exception as e: raise RuntimeError(f"v_xg.json 网络错误: {e}") from e def curl_url(url): """curl via mihomo proxy, return raw text [2026-08-02 修复] 加 DB 错误检测 → fail-fast """ import subprocess try: result = subprocess.run( ['curl', '-x', 'http://127.0.0.1:7890', '-L', '-s', url], capture_output=True, text=True, timeout=20 ) if result.returncode != 0: raise RuntimeError(f"curl {url} returncode={result.returncode}: {result.stderr[:200]}") # fail-fast: 检测 DB 错误 check_db_error(result.stdout, f"curl {url}") return result.stdout except RuntimeError: raise except Exception as e: raise RuntimeError(f"curl {url} 异常: {e}") from e def fetch_sol_list(path, marker, limit=5): """拉 sol.2344a.cc 列表页, 摘 marker (期号) 行 [2026-08-02 修复] marker 写死 "082" 是 bug, 改用 period 参数 """ html = curl_url(f'{SOL_BASE}{path}') lines = [] for line in html.split('\n'): if marker in line: # 去 HTML tag import re clean = re.sub(r'<[^>]+>', ' ', line).strip() # 提取 marker 期号:... 直到 " m = re.search(rf'{re.escape(marker)}[^\"]*?(?=]*>.*?', '', html, flags=re.DOTALL) text = re.sub(r']*>.*?', '', text, flags=re.DOTALL) text = re.sub(r'<[^>]+>', ' ', text) text = re.sub(r'\s+', ' ', text).strip() # 找关键字段 fields = {} for kw in ['另版挂', '正版彩图挂', '四字', '六肖', '尾数', '火烧', '爆', '出肖', '挂牌出肖', '挂牌成语', '红字']: m = re.search(kw + r'[::]([^。\s]{1,30})', text) if m: fields[kw] = m.group(1).strip() return fields def zodiac_lookup(num): """号→生肖 (mod 12)""" z = ['狗', '猪', '蛇', '马', '羊', '虎', '兔', '鼠', '牛', '猴', '鸡', '龙'] return z[num % 12] def analyze(period='082'): """完整玄学分析 (按 reference 073 流程) Args: period: 期号 (默认 '082'), 用于 marker 匹配 """ out = [] out.append("=" * 70) out.append(f"{period} 期 4 框架玄学分析 (按 lottery-hk skill v1.2.7 流程)") out.append("=" * 70) out.append(f"📌 所有时间默认 {TIMEZONE_BEIJING}") out.append(f"📌 挂牌日 = 实际开彩日 (sol.2344a.cc 帖子时间戳 = 实际开奖日)") out.append("") # ===== Step 1: v_xg.json ===== out.append(f"--- Step 1: v_xg.json (Qi=最新已开, Data.1-7=Qi-2 已开) ---") v = fetch_v_xg() data = v.get('Data', {}) qi = v.get('Qi', '?') nq = v.get('Nq', '?') week = v.get('Week', '?') day = v.get('Day', '?') qi_minus_2 = int(qi) - 2 if qi.isdigit() else '?' out.append(f"Qi (最新已开) = {qi}, Nq (未开下期) = {nq}") out.append(f"Qi 期开彩日(从 Nq 推算): Nq 期开彩日 Week={week} Day={day} - 3 天") out.append(f"Data.1-7 = Qi-2 期 {qi_minus_2} 已开号码 (不是 Qi-1!)") out.append("") out.append("| 位置 | 号码 | 生肖 | 五行 | 波色 |") out.append("|---|---|---|---|---|") last_seven = [] for k in ['1', '2', '3', '4', '5', '6', '7']: item = data.get(k, {}) if not item: continue num = int(item.get('number', 0)) sx = item.get('sx', '?') nim = item.get('nim', '?') color = item.get('color', '?') pos = '特码' if k == '7' else f'平码{k}' out.append(f"| {pos} | {num} | {sx} | {nim} | {color} |") last_seven.append({'num': num, 'sx': sx, 'nim': nim, 'color': color, 'pos': pos}) out.append("") # 五行统计 from collections import Counter nim_count = Counter([x['nim'] for x in last_seven]) out.append(f"{qi_minus_2} 期五行统计: " + " | ".join(f"{n}:{c}" for n, c in nim_count.most_common())) out.append(f"{qi_minus_2} 期生肖统计: " + " | ".join(f"{s}:{c}" for s, c in Counter([x['sx'] for x in last_seven]).most_common())) out.append(f"{qi_minus_2} 期波色统计: " + " | ".join(f"{c}:{n}" for c, n in Counter([x['color'] for x in last_seven]).most_common())) out.append("") # ===== Step 2: 综合挂牌 (列表 + 详情) ===== out.append(f"--- Step 2: 综合挂牌 (sol.2344a.cc/zongheguapai/) ---") gua_list = fetch_sol_list('/zongheguapai/', f'{period}期', limit=3) if gua_list: for g in gua_list: out.append(f" • {g}") out.append("") # 拿详情: 选第一个有 period 期 的链接 import re gua_html = curl_url(f'{SOL_BASE}/zongheguapai/') detail_links = re.findall(rf'href="(/zongheguapai/\d+\.html)"[^>]*>.*{period}期', gua_html)[:2] for link in detail_links: fields = fetch_sol_detail(link) if fields: out.append(f" 📄 {link}:") for k, v in fields.items(): out.append(f" {k}: {v}") out.append("") # ===== Step 3: 六信红字 ===== out.append(f"--- Step 3: 六信红字 (sol.2344a.cc/lxhz/) ---") hong_list = fetch_sol_list('/lxhz/', f'{period}期', limit=3) if hong_list: for h in hong_list: out.append(f" • {h}") # 拿详情 hong_html = curl_url(f'{SOL_BASE}/lxhz/') hong_links = re.findall(rf'href="(/lxhz/\d+\.html)"[^>]*>.*{period}期', hong_html)[:2] for link in hong_links: fields = fetch_sol_detail(link) if fields: out.append(f" 📄 {link}:") for k, v in fields.items(): out.append(f" {k}: {v}") out.append("") # ===== Step 4: 玄机诗 ===== out.append(f"--- Step 4: 玄机诗 (sol.2344a.cc/xuanjiziliao/) ---") xuan_list = fetch_sol_list('/xuanjiziliao/', f'{period}期', limit=5) if xuan_list: for x in xuan_list: out.append(f" • {x}") out.append("") # ===== 综合 ===== out.append("=" * 70) out.append(f"⭐ {period} 期综合玄学共识") out.append("=" * 70) out.append("") out.append(f"📊 {qi_minus_2} 期五行旺: " + (nim_count.most_common(1)[0][0] if nim_count else "无") + " (3 次)") out.append(f"📊 {qi_minus_2} 期生肖: 7 个全不重 (无明显旺)") out.append(f"📊 {qi_minus_2} 期波色: " + (Counter([x['color'] for x in last_seven]).most_common(1)[0][0] if last_seven else "无")) out.append("") out.append(f"🔥 挂牌 + 红字 共识: 看上面挂牌内容") out.append("") # ===== 期开彩 ===== out.append("=" * 70) out.append(f"🚨 {period} 期开彩") out.append("=" * 70) out.append(f"日期: 2026-{period[:2]}-{period[2:]}") out.append(f"星期: {week}") out.append(f"时间: 21:30 {TIMEZONE_BEIJING}") out.append("") out.append("数据来源:") out.append(" 1. btc.tktk.app/data/v_xg.json") out.append(f" 2. {SOL_BASE}/zongheguapai/ (综合挂牌)") out.append(f" 3. {SOL_BASE}/lxhz/ (六信红字)") out.append(f" 4. {SOL_BASE}/xuanjiziliao/ (玄机诗)") out.append("") out.append(f"参考: skill lottery-hk v1.2.7, references/analysis-example-073/074/075.md") return '\n'.join(out) if __name__ == '__main__': import urllib.request, json as _json period = sys.argv[1] if len(sys.argv) > 1 else None if period is None: try: req = urllib.request.Request('https://btc.tktk.app/data/v_xg.json', headers={'User-Agent': 'Mozilla/5.0'}) with urllib.request.urlopen(req, timeout=10) as r: period = _json.loads(r.read().decode('utf-8')).get('Qi', '???') except Exception: period = '???' try: print(analyze(period)) except RuntimeError as e: print(f"\n❌ ERR: {e}", file=sys.stderr) sys.exit(1)