号码跟随选号器 - 技术文档
📐 系统架构
整体架构
┌─────────────────────────────────────┐
│ GUI 界面层 (Tkinter) │
│ ┌──────────┬──────────┬──────────┐ │
│ │ 数据更新 │ 参数设置 │ 结果显示 │ │
│ └──────────┴──────────┴──────────┘ │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 业务逻辑层 (Analysis) │
│ ┌──────────┬──────────┬──────────┐ │
│ │号码跟随 │跨度跟随 │合尾跟随 │ │
│ └──────────┴──────────┴──────────┘ │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 数据访问层 (Data Access) │
│ ┌──────────┬──────────┬──────────┐ │
│ │网络请求 │数据缓存 │Excel 导出 │ │
│ └──────────┴──────────┴──────────┘ │
└─────────────────────────────────────┘
🔧 技术栈
开发环境
- 语言: Python 3.13.1
- GUI 框架: Tkinter(Python 内置)
- 数据处理: Pandas >= 2.0.0
- 数值计算: NumPy >= 1.26.0
- Excel 导出: openpyxl >= 3.1.0
- HTTP 请求: requests >= 2.31.0
打包工具
- 工具: PyInstaller >= 6.0.0
- 模式: onedir(目录结构)
- 配置文件: build_exe.spec
📁 核心模块
main.py - 主程序
文件路径: main.py
代码行数: 约 3558 行
核心类: LotteryAnalyzerApp
主要方法:
class LotteryAnalyzerApp:
def __init__(self, root):
"""初始化应用"""
def fetch_and_parse_data(self, data_type, use_cache=True, force_refresh=False):
"""获取并解析数据"""
def analyze_follow_periods(self):
"""分析跟随期数"""
def _analyze_number_follow_patterns(self, df, follow_periods):
"""分析号码跟随模式"""
def _analyze_span_follow_patterns(self, df, follow_periods):
"""分析跨度跟随模式"""
def _analyze_tail_follow_patterns(self, df, follow_periods):
"""分析合尾跟随模式"""
def export_to_excel(self):
"""导出到 Excel"""
def display_analysis_result(self, results):
"""显示分析结果"""
registration/ - 授权模块
功能: 用户授权管理
核心组件:
ClientRegistrationManager- 客户端注册管理器RSAKeyManager- RSA 密钥管理器LicenseGenerator- 授权文件生成器
工作机制:
- 生成设备 ID(基于硬件信息)
- 管理员使用私钥签名授权文件
- 客户端使用公钥验证授权
- 7 天试用期机制
🗂️ 数据结构
原始数据格式
来源: [数据源地址已隐藏]
字段说明:
期号,开奖日期,百位,十位,个位,...
示例:
2026001,2026-01-01,8,5,3,...
DataFrame 结构
Pandas DataFrame 列:
期号(str):期号开奖日期(str):开奖日期开奖号百位(int):百位号码开奖号十位(int):十位号码开奖号个位(int):个位号码
🔍 核心算法
1. 号码跟随统计算法
原理:
统计当某个位置连续 N 期出现相同号码时,下一期的开奖情况。
伪代码:
def analyze_number_follow(df, follow_periods):
# 1. 找出所有连续 follow_periods 期相同号码的模式
patterns = []
for i in range(len(df) - follow_periods):
pattern = df.iloc[i:i+follow_periods]['百位'].tolist()
if len(set(pattern)) == 1: # 所有期都相同
next_number = df.iloc[i+follow_periods]['百位']
patterns.append((pattern[0], next_number))
# 2. 统计每个号码作为跟随结果的次数
result_counts = Counter(next_numbers)
# 3. 计算概率
total = sum(result_counts.values())
probabilities = {num: count/total for num, count in result_counts.items()}
return result_counts, probabilities
2. 跨度统计算法
跨度定义:
span = max(bai, shi, ge) - min(bai, shi, ge)
统计方法: 与号码跟随类似,但对象是跨度值
3. 合尾统计算法
合尾定义:
tail = (bai + shi + ge) % 10
统计方法: 与号码跟随类似,但对象是合尾值
4. 合理性评估算法
评估维度:
- 模式数量评分
if patterns < 5: score -= 20 # 过少
elif patterns > total * 0.3: score -= 15 # 过多
else: score += 10 # 适中
- 平均匹配次数评分
if avg_matches < 1.2: score -= 15
elif avg_matches > 8: score -= 10
elif 1.5 <= avg_matches <= 5: score += 15
- 多次匹配模式数评分
if with_matches < 3: score -= 15
elif with_matches > 60: score -= 10
elif 5 <= with_matches <= 40: score += 15
- 最大匹配次数评分
if max_matches < 2: score -= 10
elif max_matches > 25: score -= 5
elif 3 <= max_matches <= 15: score += 10
综合判断:
- 总分 >= 15:合理
- 总分 < 15:不合理
📊 性能指标
数据处理性能
| 操作 | 数据量 | 耗时 |
|---|---|---|
| 数据下载 | 5000 期 | ~2 秒 |
| 数据解析 | 5000 期 | <0.5 秒 |
| 号码跟随分析 | 3000 期×2 期跟随 | ~1 秒 |
| Excel 导出 | 完整结果 | ~2 秒 |
内存占用
- 空闲状态: ~50 MB
- 加载数据后: ~80 MB
- 分析过程中: ~120 MB
- 峰值: ~150 MB
🛡️ 安全机制
授权验证流程
1. 启动软件 → 检查授权文件
↓
2. 无授权 → 显示试用窗口(7 天倒计时)
↓
3. 有授权 → 读取设备 ID
↓
4. 验证签名 → 使用公钥验证
↓
5. 验证通过 → 正常使用
验证失败 → 提示错误
密钥管理
公钥: registration/keys/public_key.pem
- 包含在分发包中
- 用于验证授权文件
私钥: private_key.pem
- 由管理员保管
- 不放入分发包
- 用于生成授权文件
设备绑定
设备 ID 生成算法:
import hashlib
import platform
import uuid
def generate_device_id():
mac_address = ':'.join(['{:02x}'.format((uuid.getnode() >> i) & 0xff)
for i in range(0, 48, 8)])
processor = platform.processor()
machine = platform.machine()
info = f"{mac_address}{processor}{machine}"
device_id = hashlib.md5(info.encode()).hexdigest()
return device_id
📦 打包配置
build_exe.spec 关键配置
# 数据文件 - 只包含公钥,不包含私钥
datas = [
('registration', 'registration'),
('registration/keys/public_key.pem', 'registration/keys')
]
# 隐藏导入
hiddenimports = [
'pandas',
'numpy',
'openpyxl',
'requests'
]
# 排除的模块
excludes = [
'tkinter.test',
'test'
]
打包流程
# 1. 清理旧文件
rmdir /s /q build
rmdir /s /q dist_new
# 2. 打包
pyinstaller --clean build_exe.spec
# 3. 复制 registration 目录
xcopy /E /I registration dist_new\registration
# 4. 删除私钥(安全)
del dist_new\registration\keys\private_key.pem
# 5. 压缩
Compress-Archive dist_new 号码跟随选号器_发布包.zip
🔧 配置文件
config.json
路径: config.json
内容:
{
"version": "1.0",
"default_data_type": "3D",
"cache_expire_hours": 24,
"auto_update": true
}
📝 日志管理
日志文件
路径: app.log
格式:
2026-04-03 10:30:15 - INFO - 应用程序基础目录:F:\3D\SOFT\号码跟随选号器
2026-04-03 10:30:20 - INFO - 开始更新数据:3D
2026-04-03 10:30:22 - INFO - 数据更新完成:5000 期
日志级别:
- INFO:一般信息
- WARNING:警告信息
- ERROR:错误信息
🐛 错误处理
常见错误及处理
1. 网络连接失败
try:
response = requests.get(url, timeout=10)
except requests.exceptions.RequestException as e:
logger.error(f"网络请求失败:{e}")
messagebox.showerror("错误", "网络连接失败,请检查网络设置")
2. 数据解析错误
try:
df = pd.read_csv(StringIO(text), sep='\t')
except Exception as e:
logger.error(f"数据解析失败:{e}")
messagebox.showerror("错误", "数据格式错误")
3. 授权验证失败
if not license_valid:
logger.warning("授权验证失败")
show_registration_window()
🚀 优化建议
性能优化
- 数据缓存
- 使用本地缓存减少网络请求
- 缓存有效期 24 小时
- 多线程
- 数据下载使用后台线程
- 分析计算使用后台线程
- 避免阻塞 GUI
- 增量更新
- 只下载新数据
- 减少数据传输量
内存优化
- 及时释放
- 分析完成后释放临时 DataFrame
- 使用
del显式删除大对象
- 分批处理
- 大数据集分批处理
- 避免一次性加载全部数据
📞 技术支持
开发者: 摸球校尉陈八七
QQ 群: 253799100
微信: moqiuxiaowei
邮箱: moqiuxiaowei@qq.com
最后更新: 2026-04-03
软件版本: v3.1