#!/bin/bash # 核验当前期预测 vs 实际开奖,记录命中率 # 22:30 北京时间(开奖21:30后1小时)跑 # # 流程 (2026-08-13 重写): # 1. curl v_xg.json (带 UA + proxy fallback) → Qi + Data.1-7 (真开彩, 2026-08-04 验证) # 2. 失败 fallback: 已有 draws 表数据 OR 提示用户手填 # 3. draws 表空 → 自动 add_draw (触发 check_hits 更新所有 analysis hit 状态) # 4. 找 Qi 期分析 .md, 输出核验报告 # # ⚠️ Qi→Nq 修复后: cron 11:30 北京 分析 Nq 期 (未开下期), 22:30 北京 verify 时 Qi 已经是新一期, # 分析文件就是 Qi 期 (刚开的那期), 不是 Qi-1 # # 🚨 marksix6.com 真开彩验证源: 必须用 browser (Vue SSR, curl 拿不到), 不在本脚本里跑 # (no_agent 模式没 browser 工具); cron 改 no_agent 时改这里 set -e DB="$HOME/.hermes/trading/lottery.db" OUT_DIR="$HOME/.hermes/cron/output/lottery-verify" mkdir -p "$OUT_DIR" SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)" # === Step 1: 取 v_xg.json (Qi + Data.1-7) === fetch_v_xg() { local out # 优先代理,失败直连(VPS 出口有时被墙) out=$(curl -s --proxy http://127.0.0.1:7890 --max-time 8 \ -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \ "https://btc.tktk.app/data/v_xg.json" 2>/dev/null || true) if [ -z "$out" ] || echo "$out" | grep -q "请求出错\|Cann't connect"; then out=$(curl -s --noproxy '*' --max-time 8 \ -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \ "https://btc.tktk.app/data/v_xg.json" 2>/dev/null || true) fi # 校验是不是 JSON 且有 Qi if echo "$out" | python3 -c "import json,sys; d=json.loads(sys.stdin.read()); assert d.get('Qi')" 2>/dev/null; then echo "$out" fi } V_XG=$(fetch_v_xg || true) NEED_FETCH=0 if [ -z "$V_XG" ]; then NEED_FETCH=1 echo "⚠️ v_xg.json 暂不可用 (DB 故障或网络被墙), 尝试从 draws 表读已有数据" fi # === Step 2: 解析 Qi + 真开彩 === QI="" ACTUAL="" if [ "$NEED_FETCH" = "0" ]; then eval "$(echo "$V_XG" | python3 -c " import json, sys d = json.loads(sys.stdin.read()) qi = d.get('Qi','') data = d.get('Data', {}) nums = [int(data[str(i)]['number']) for i in range(1, 8) if str(i) in data] special = nums[6] if len(nums) >= 7 else 0 print(f'QI={qi!r}') print(f'SPECIAL={special}') print(f'N1={nums[0] if len(nums)>0 else 0}') print(f'N2={nums[1] if len(nums)>1 else 0}') print(f'N3={nums[2] if len(nums)>2 else 0}') print(f'N4={nums[3] if len(nums)>3 else 0}') print(f'N5={nums[4] if len(nums)>4 else 0}') print(f'N6={nums[5] if len(nums)>5 else 0}') ")" if [ -n "$QI" ]; then ACTUAL="$N1,$N2,$N3,$N4,$N5,$N6,$SPECIAL" echo "📡 v_xg.json: Qi=$QI 真开彩=$N1 $N2 $N3 $N4 $N5 $N6 特=$SPECIAL" fi fi # === Step 3: 兜底从 draws 表读 (手填或之前入库) === if [ -z "$ACTUAL" ]; then # v_xg 拿不到, 尝试从最近 Qi 期读 if [ -z "$QI" ]; then QI=$(sqlite3 "$DB" "SELECT period FROM draws ORDER BY period DESC LIMIT 1;" 2>/dev/null || true) fi if [ -n "$QI" ]; then ACTUAL=$(sqlite3 "$DB" "SELECT n1||','||n2||','||n3||','||n4||','||n5||','||n6||','||special FROM draws WHERE period='$QI';" 2>/dev/null || true) fi if [ -z "$ACTUAL" ]; then echo "❌ 无法获取 $QI 期开奖结果 (v_xg.json 宕机 + draws 表空)" echo " 手动填: python3 $SKILL_DIR/scripts/lottery_特码.py add $QI " exit 1 fi echo "📂 draws 表读 $QI 期: $ACTUAL" fi IFS=',' read -r A1 A2 A3 A4 A5 A6 AS <<< "$ACTUAL" ACTUAL_FLAT="$A1 $A2 $A3 $A4 $A5 $A6" ACTUAL_SPECIAL="$AS" # === Step 4: 检查 draws 表, 没数据就入库 (v_xg 真开彩可用时) === EXISTING=$(sqlite3 "$DB" "SELECT special FROM draws WHERE period='$QI';" 2>/dev/null || true) if [ -z "$EXISTING" ] && [ -n "$SPECIAL" ] && [ "$SPECIAL" != "0" ]; then echo "💾 draws 表 $QI 期空, 自动入库..." python3 "$SKILL_DIR/scripts/lottery_特码.py" add "$QI" "$SPECIAL" "$N1" "$N2" "$N3" "$N4" "$N5" "$N6" 2>&1 || echo "⚠️ add_draw 失败" fi # === Step 5: 跑 check_hits (确保所有 analysis 行 hit 状态更新) === python3 "$SKILL_DIR/scripts/lottery_特码.py" hits 2>&1 | tail -3 # === Step 6: 找 Qi 期分析 .md === ANALYSIS_FILE=$(grep -lE "${QI}期" "$HOME/.hermes/cron/output/5bec1f60f77f/"*.md 2>/dev/null | tail -1) # === Step 7: 查 analysis 表最近一条 === ANALYSIS_HIT=$(sqlite3 "$DB" "SELECT actual_special || '|' || hit FROM analysis WHERE period='$QI' ORDER BY id DESC LIMIT 1;" 2>/dev/null || echo "|") # === Step 8: 输出核验报告 === OUT_FILE="$OUT_DIR/$(date +%Y-%m-%d_%H-%M-%S)_${QI}.md" { echo "## 🎯 核验报告 | $QI期" echo "" echo "**开奖时间**: $(date +%Y-%m-%d) 21:30 北京" echo "**核验时间**: $(date +%Y-%m-%d) 22:30 北京" echo "**数据源**: v_xg.json Data.1-7 (2026-08-04 marksix6.com 验证)" echo "" echo "### 实际开奖" echo "| 位置 | 号码 |" echo "|------|------|" echo "| 平码 | $A1 · $A2 · $A3 · $A4 · $A5 · $A6 |" echo "| 特码 | **$AS** |" echo "" if [ -n "$ANALYSIS_FILE" ]; then echo "### 分析文件" echo "📄 \`$ANALYSIS_FILE\`" echo "" # 提取 Top 5 候选 (新格式: "| 🥇 | **42** | 3 | 挂牌 另版挂 (42) |") TOP_CANDIDATES=$(grep -oE '\| \*\*[0-9]+\*\*' "$ANALYSIS_FILE" | head -5 | grep -oE '[0-9]+') echo "### 预测 Top 5" echo "| 排序 | 特码 |" echo "|---|---|" i=1 for c in $TOP_CANDIDATES; do emoji=$([ $i -eq 1 ] && echo "🥇" || ([ $i -eq 2 ] && echo "🥈" || ([ $i -eq 3 ] && echo "🥉" || echo "$i"))) echo "| $emoji | $c |" i=$((i+1)) done echo "" HIT_SPECIAL="❌ 未中" if echo " $TOP_CANDIDATES " | grep -q " $AS "; then HIT_SPECIAL="✅ **特码命中**" fi echo "### 命中" echo "- 特码 $AS: $HIT_SPECIAL" HIT_FLAT="" for n in $A1 $A2 $A3 $A4 $A5 $A6; do if echo " $TOP_CANDIDATES " | grep -q " $n "; then HIT_FLAT="$HIT_FLAT ✅$n" fi done echo "- 平码命中:${HIT_FLAT:- 无}" TOTAL=0 if echo " $TOP_CANDIDATES " | grep -q " $AS "; then TOTAL=$((TOTAL+1)); fi for n in $A1 $A2 $A3 $A4 $A5 $A6; do if echo " $TOP_CANDIDATES " | grep -q " $n "; then TOTAL=$((TOTAL+1)); fi done echo "" echo "**总命中**: Top 5 候选命中 $TOTAL / 7 球 (特码+平码)" else echo "### ⚠️ 未找到分析文件" echo " 查找路径: $HOME/.hermes/cron/output/5bec1f60f77f/" echo " 期号: $QI" fi ACTUAL_FROM_DB=$(echo "$ANALYSIS_HIT" | cut -d'|' -f1) HIT_FROM_DB=$(echo "$ANALYSIS_HIT" | cut -d'|' -f2) if [ -n "$HIT_FROM_DB" ]; then HIT_ICON=$([ "$HIT_FROM_DB" = "1" ] && echo "✅ 中奖" || echo "❌ 未中") echo "" echo "### SQLite analysis 标记" echo "- actual_special: $ACTUAL_FROM_DB" echo "- hit: $HIT_ICON" fi echo "" echo "---" echo "_生成时间: $(date '+%Y-%m-%d %H:%M:%S') 北京_" } > "$OUT_FILE" cat "$OUT_FILE"