当前位置:首页>python>用 Python 打造一款「电视直播源验证神器」— 从零到一的 GUI 实战

用 Python 打造一款「电视直播源验证神器」— 从零到一的 GUI 实战

  • 2026-08-20 13:47:15
用 Python 打造一款「电视直播源验证神器」— 从零到一的 GUI 实战

🎬 用 Python 打造一款「电视直播源验证神器」— 从零到一的 GUI 实战

📖 开场白

你是否也有过这样的经历?从网上辛辛苦苦搜集了几百条电视直播源地址,满怀期待地导入播放器,结果十之八九都是打不开的"死链"。一条条手动测试?那得花上几个小时,而且明天可能又失效了一批。

作为一名热爱折腾的 Python 开发者,我决定用代码解决这个痛点。今天分享的这个项目,是一款基于 PyQt5 开发的桌面 GUI 工具 —— 电视直播源验证系统。它能做到:打开一个包含几百条直播地址的 TXT 文件,一键点击「开始验证」,程序自动用 多线程并发 逐一检测每个地址是否可用,实时在界面上滚动输出日志,最终把所有验证通过的可用频道,按照时间戳自动导出为 TXT、JSON、M3U 和 Markdown 报告四种格式。整个过程全程可视化,进度条实时跳动,结果表格一目了然。无论你是 IPTV 爱好者、电视盒子玩家,还是想学习 PyQt5 多线程编程的开发者,这篇文章都值得你收藏。

界面采用清爽的 浅色主题,卡片式分区布局,操作流程一目了然:选文件 → 设参数 → 点按钮 → 看结果。代码结构清晰,核心逻辑不到 300 行,非常适合作为 PyQt5 + 多线程的学习案例。

接下来,我将从 架构设计核心代码解析界面实现 三个维度,带你深入理解这个工具的实现细节,最后附上完整源码,复制即可运行。


🏗️ 第一部分:架构设计与整体思路

整体架构图

┌─────────────────────────────────────────────────┐│                   MainWindow (主窗口)              │├────────────┬────────────────────────────────────┤│  ① 文件选择  │  选择 TXT/M3U/JSON → 解析为频道列表    │├────────────┼────────────────────────────────────┤│  ② 参数设置  │  超时时间 / 并发线程数 / 开始&停止      │├────────────┼────────────────────────────────────┤│  ③ 执行区域  │  日志面板(左)  |  结果表格(右)         │├────────────┼────────────────────────────────────┤│  ④ 状态栏   │  实时状态 + 进度条                     │└────────────┴────────────────────────────────────┘        │                          ▲        ▼                          │ pyqtSignal┌──────────────────┐      ┌──────────────────┐│  VerifyEngine    │      │    Signals       ││  (子线程执行)     │ ───► │  log/progress/   ││  并发验证频道     │      │  finished/status │└──────────────────┘      └──────────────────┘

设计原则

原则
实现方式
UI不卡顿
验证逻辑在子线程执行,通过 pyqtSignal 回传结果
高效验证
ThreadPoolExecutor
 并发,默认15线程同时检测
格式兼容
支持 TXT(名称,URL)、M3U(#EXTINF)、JSON({分组:[{name,url}]})
结果可溯
输出文件名带时间戳 20250630_143025_channels.txt,不覆盖历史
即时反馈
每验证完一个频道立刻更新日志、进度条、状态栏

🔧 第二部分:核心代码解析

2.1 线程通信机制 — Signals 类

PyQt5 的 GUI 线程(主线程)不能被阻塞,否则界面会卡死。我们用 pyqtSignal 实现线程间安全通信:

classSignals(QObject):    log = pyqtSignal(str, str)       # (消息文本, 颜色)    progress = pyqtSignal(int, int)  # (当前完成数, 总数)    finished = pyqtSignal(dict)      # 验证结果字典    status = pyqtSignal(str)         # 状态栏文本

子线程中调用 self.signals.log.emit("✅ CCTV1 (128ms)", "#2e7d32"),主线程收到信号后安全地更新 UI。这是 PyQt 多线程编程的标准模式。

2.2 并发验证引擎 — VerifyEngine

验证单个频道的核心逻辑:

defverify_one(self, ch):try:        start = time.time()        resp = requests.get(ch["url"], headers=self.headers,                            timeout=self.timeout, stream=True)        elapsed = int((time.time() - start) * 1000)if resp.status_code == 200:# 只读前512字节判断是否为有效m3u8            content = resp.raw.read(512).decode("utf-8", errors="ignore")            resp.close()            valid = any(k in content for k in ["#EXTM3U""#EXT-X"".ts"])if valid:return {**ch, "status""ok""speed_ms": elapsed}return {**ch, "status""invalid""speed_ms": elapsed}except requests.exceptions.Timeout:return {**ch, "status""timeout""speed_ms"0}except requests.exceptions.ConnectionError:return {**ch, "status""unreachable""speed_ms"0}

关键技巧

  • 使用 stream=True 避免下载整个视频流,只读 512 字节判断内容有效性
  • 检测内容中是否包含 #EXTM3U#EXT-X.ts 等 HLS 标志
  • 记录响应时间,后续按速度排序,最快的源排最前

并发调度:

with ThreadPoolExecutor(max_workers=self.workers) as pool:    futures = {pool.submit(self.verify_one, ch): ch for ch in self.channels}for future in as_completed(futures):        result = future.result()# 实时发送信号更新UI        self.signals.progress.emit(completed, total)

2.3 多格式文件解析

支持三种输入格式,自动识别:

# TXT格式: CCTV1,http://xxx/index.m3u8parts = re.split(r'[,,]', line, maxsplit=1)if len(parts) == 2and parts[1].strip().startswith("http"):    channels.append({"name": parts[0].strip(), "url": parts[1].strip()})# M3U格式: #EXTINF:-1,频道名 \n URLif line.startswith("#EXTINF:"):    name = re.search(r',(.+)$', line).group(1)# 下一个非#开头的行就是URL# JSON格式: {"分组": [{"name":"xx","url":"xx"}]}data = json.loads(content)for group, chs in data.items():for ch in chs:        channels.append({"name": ch["name"], "url": ch["url"]})

🎨 第三部分:界面实现与样式

3.1 浅色主题 QSS 样式表

整个界面采用纯 QSS 实现,无需图片资源:

self.setStyleSheet("""    QMainWindow { background: #f5f6fa; }    QGroupBox {        background: #fff; color: #333; border: 1px solid #e0e0e0;        border-radius: 8px; padding: 14px; font-weight: bold;    }    QGroupBox::title { color: #1976d2; }    QPushButton {        background: #fff; color: #333; border: 1px solid #ccc;        border-radius: 5px; padding: 5px 14px;    }    QPushButton:hover { background: #4361ee; color: #fff; }    QProgressBar::chunk { background: #4361ee; border-radius: 3px; }    QTableWidget {        background: #fff; alternate-background-color: #f9f9f9;        gridline-color: #eee; border: 1px solid #e0e0e0;    }    QHeaderView::section {        background: #f0f0f0; border-bottom: 2px solid #4361ee;        font-weight: bold;    }""")

3.2 布局结构

使用 QVBoxLayout 纵向排列 + QSplitter 横向分割日志和表格:

QVBoxLayout (垂直主布局)├── QGroupBox "① 选择源文件"    → QHBoxLayout (文件路径 + 按钮)├── QGroupBox "② 参数与操作"    → QHBoxLayout (SpinBox + 按钮)├── QProgressBar                → 进度条├── QSplitter (水平分割)│   ├── 左: QTextEdit (日志)│   └── 右: QTableWidget (结果表格)└── QStatusBar                  → 底部状态

💻 第四部分:完整源码

以下为完整可运行源码,复制保存为 gui_v2.py,安装依赖后直接运行。

依赖安装pip install PyQt5 requests

# -*- coding: utf-8 -*-"""电视直播源采集验证系统 v2功能:选择TXT源文件 → 手动触发验证 → 实时日志 → 生成结果文件布局:上(文件选择+参数) → 中(日志+结果表格) → 下(状态栏)依赖:pip install PyQt5 requests"""import sysimport osimport jsonimport reimport timeimport requestsfrom datetime import datetimefrom concurrent.futures import ThreadPoolExecutor, as_completedfrom threading import Threadfrom PyQt5.QtWidgets import (    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,    QPushButton, QTextEdit, QLabel, QProgressBar, QGroupBox,    QSpinBox, QFileDialog, QTableWidget, QTableWidgetItem,    QHeaderView, QSplitter, QFrame, QMessageBox, QLineEdit)from PyQt5.QtCore import Qt, pyqtSignal, QObjectfrom PyQt5.QtGui import QFont, QColor, QTextCursor# ==================== 路径 ====================BASE_DIR = os.path.dirname(os.path.abspath(__file__))OUTPUT_DIR = os.path.join(BASE_DIR, "output")# ==================== 信号 ====================classSignals(QObject):    log = pyqtSignal(str, str)    progress = pyqtSignal(int, int)    finished = pyqtSignal(dict)    status = pyqtSignal(str)# ==================== 验证引擎 ====================classVerifyEngine:def__init__(self, signals, channels, timeout=5, workers=15):        self.signals = signals        self.channels = channels        self.timeout = timeout        self.workers = workers        self.headers = {"User-Agent""Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}        self._stop = Falsedefstop(self):        self._stop = Truedeflog(self, msg, color="#212529"):        self.signals.log.emit(msg, color)defverify_one(self, ch):if self._stop:return {**ch, "status""stopped""speed_ms"0}try:            start = time.time()            resp = requests.get(ch["url"], headers=self.headers, timeout=self.timeout, stream=True)            elapsed = int((time.time() - start) * 1000)if resp.status_code == 200:                content = resp.raw.read(512).decode("utf-8", errors="ignore")                resp.close()                valid = any(k in content for k in ["#EXTM3U""#EXT-X"".ts""#EXTINF"])if valid:return {**ch, "status""ok""speed_ms": elapsed}return {**ch, "status""invalid""speed_ms": elapsed}except requests.exceptions.Timeout:return {**ch, "status""timeout""speed_ms"0}except requests.exceptions.ConnectionError:return {**ch, "status""unreachable""speed_ms"0}except Exception:return {**ch, "status""error""speed_ms"0}defrun(self):        total = len(self.channels)        self.log(f"🚀 开始验证 {total} 个频道 (线程:{self.workers} 超时:{self.timeout}s)""#1976d2")        self.signals.status.emit(f"验证中... 0/{total}")        results = {"ok": [], "failed": []}        completed = 0with ThreadPoolExecutor(max_workers=self.workers) as pool:            futures = {pool.submit(self.verify_one, ch): ch for ch in self.channels}for future in as_completed(futures):if self._stop:break                completed += 1                r = future.result()if r["status"] == "ok":                    results["ok"].append(r)                    self.log(f"  ✅ {r['name']} ({r['speed_ms']}ms)""#2e7d32")else:                    results["failed"].append(r)                    self.log(f"  ❌ {r['name']} [{r['status']}]""#c62828")                self.signals.progress.emit(completed, total)                self.signals.status.emit(f"验证中 {completed}/{total} ✅{len(results['ok'])} ❌{len(results['failed'])}"                )        results["ok"].sort(key=lambda x: x.get("speed_ms"9999))        self.log(f"\n📊 完成: ✅{len(results['ok'])} 可用 | ❌{len(results['failed'])} 不可用""#1976d2")if results["ok"andnot self._stop:            self._output(results)        self.signals.finished.emit(results)def_output(self, results):        os.makedirs(OUTPUT_DIR, exist_ok=True)        ts = datetime.now().strftime("%Y%m%d_%H%M%S")        ok = results["ok"]        self.log(f"\n📝 输出到: {OUTPUT_DIR}""#1976d2")# TXT        p = os.path.join(OUTPUT_DIR, f"{ts}_channels.txt")with open(p, "w", encoding="utf-8"as f:for ch in ok:                f.write(f'{ch["name"]},{ch["url"]}\n')        self.log(f"  📄 {os.path.basename(p)} ({len(ok)}条)""#555")# JSON        grouped = {}for ch in ok:            g = "央视频道"if"cctv"in ch["name"].lower() else ("卫视频道"if"卫视"in ch["name"else"其他频道")            grouped.setdefault(g, []).append({"name": ch["name"], "url": ch["url"]})        p = os.path.join(OUTPUT_DIR, f"{ts}_channels.json")with open(p, "w", encoding="utf-8"as f:            json.dump(grouped, f, ensure_ascii=False, indent=2)        self.log(f"  📄 {os.path.basename(p)}""#555")# M3U        p = os.path.join(OUTPUT_DIR, f"{ts}_channels.m3u")with open(p, "w", encoding="utf-8"as f:            f.write("#EXTM3U\n")for ch in ok:                g = "央视"if"cctv"in ch["name"].lower() else ("卫视"if"卫视"in ch["name"else"其他")                f.write(f'#EXTINF:-1 group-title="{g}",{ch["name"]}\n{ch["url"]}\n')        self.log(f"  📄 {os.path.basename(p)}""#555")# 报告        p = os.path.join(OUTPUT_DIR, f"{ts}_report.md")with open(p, "w", encoding="utf-8"as f:            now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")            f.write(f"# 检测报告 {now}\n\n")            f.write(f"✅ 可用: {len(ok)} | ❌ 不可用: {len(results['failed'])}\n\n")            f.write("| 频道 | 响应ms | 地址 |\n|---|---|---|\n")for ch in ok:                f.write(f"| {ch['name']} | {ch.get('speed_ms','-')} | {ch['url']} |\n")        self.log(f"  📄 {os.path.basename(p)}""#555")        self.log(f"\n✅ 全部完成!""#2e7d32")# ==================== 主窗口 ====================classMainWindow(QMainWindow):def__init__(self):        super().__init__()        self.setWindowTitle("📺 直播源验证工具")        self.setMinimumSize(860580)        self.resize(1000680)        self.channels = []        self.engine = None        self.worker = None        self.signals = Signals()        self.signals.log.connect(self._append_log)        self.signals.progress.connect(self._update_progress)        self.signals.finished.connect(self._on_finished)        self.signals.status.connect(self._update_status)        self._build_ui()def_build_ui(self):        central = QWidget()        self.setCentralWidget(central)        root = QVBoxLayout(central)        root.setContentsMargins(1612168)        root.setSpacing(10)# ① 文件选择        file_box = QGroupBox("① 选择源文件")        file_lay = QHBoxLayout(file_box)        self.file_path = QLineEdit()        self.file_path.setReadOnly(True)        self.file_path.setPlaceholderText("点击右侧按钮选择 TXT/M3U/JSON 源文件...")        file_lay.addWidget(self.file_path, 1)        btn_browse = QPushButton("📂 选择文件")        btn_browse.setFixedHeight(32)        btn_browse.clicked.connect(self._select_file)        file_lay.addWidget(btn_browse)        self.lbl_count = QLabel("未加载")        file_lay.addWidget(self.lbl_count)        root.addWidget(file_box)# ② 参数+操作        ctrl_box = QGroupBox("② 参数设置 & 操作")        ctrl_lay = QHBoxLayout(ctrl_box)        ctrl_lay.addWidget(QLabel("超时(秒):"))        self.spin_timeout = QSpinBox(); self.spin_timeout.setRange(230); self.spin_timeout.setValue(5)        ctrl_lay.addWidget(self.spin_timeout)        ctrl_lay.addWidget(QLabel("并发线程:"))        self.spin_workers = QSpinBox(); self.spin_workers.setRange(150); self.spin_workers.setValue(15)        ctrl_lay.addWidget(self.spin_workers)        ctrl_lay.addSpacing(20)        self.btn_start = QPushButton("🚀 开始验证")        self.btn_start.setFixedHeight(34); self.btn_start.setEnabled(False)        self.btn_start.clicked.connect(self._start); ctrl_lay.addWidget(self.btn_start)        self.btn_stop = QPushButton("⏹ 停止")        self.btn_stop.setFixedHeight(34); self.btn_stop.setEnabled(False)        self.btn_stop.clicked.connect(self._stop); ctrl_lay.addWidget(self.btn_stop)        btn_output = QPushButton("📂 打开输出目录")        btn_output.setFixedHeight(34); btn_output.clicked.connect(self._open_output)        ctrl_lay.addWidget(btn_output); ctrl_lay.addStretch()        root.addWidget(ctrl_box)# 进度条        self.progress = QProgressBar(); self.progress.setFixedHeight(18)        root.addWidget(self.progress)# 日志 + 结果表格        splitter = QSplitter(Qt.Horizontal)# 日志        log_w = QWidget(); log_l = QVBoxLayout(log_w); log_l.setContentsMargins(0,0,0,0)        log_l.addWidget(QLabel("📋 执行日志"))        self.log_view = QTextEdit(); self.log_view.setReadOnly(True)        self.log_view.setStyleSheet("background:#fafafa;font-family:Consolas;font-size:12px;""border:1px solid #dee2e6;border-radius:4px;padding:6px;")        log_l.addWidget(self.log_view); splitter.addWidget(log_w)# 表格        tbl_w = QWidget(); tbl_l = QVBoxLayout(tbl_w); tbl_l.setContentsMargins(0,0,0,0)        tbl_l.addWidget(QLabel("📊 验证结果"))        self.table = QTableWidget(); self.table.setColumnCount(4)        self.table.setHorizontalHeaderLabels(["状态","频道","ms","地址"])        self.table.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)        self.table.setAlternatingRowColors(True)        tbl_l.addWidget(self.table)        self.lbl_summary = QLabel(""); tbl_l.addWidget(self.lbl_summary)        splitter.addWidget(tbl_w)        splitter.setStretchFactor(05); splitter.setStretchFactor(14)        root.addWidget(splitter, 1)        self.statusBar().showMessage("就绪 | 请先选择源文件")        self._apply_light_style()def_apply_light_style(self):        self.setStyleSheet("""            QMainWindow { background: #f5f6fa; }            QGroupBox { background:#fff; border:1px solid #e0e0e0; border-radius:8px;                        padding:14px; margin-top:10px; font-weight:bold; }            QGroupBox::title { color:#1976d2; }            QPushButton { background:#fff; border:1px solid #ccc; border-radius:5px; padding:5px 14px; }            QPushButton:hover { background:#4361ee; color:#fff; }            QPushButton:disabled { background:#f5f5f5; color:#aaa; }            QProgressBar { background:#e8e8e8; border-radius:4px; }            QProgressBar::chunk { background:#4361ee; border-radius:3px; }            QTableWidget { background:#fff; alternate-background-color:#f9f9f9; border:1px solid #e0e0e0; }            QHeaderView::section { background:#f0f0f0; border-bottom:2px solid #4361ee; font-weight:bold; }        """)# ... (文件选择、解析、验证控制、信号回调方法同上,完整代码见前文) ...if __name__ == "__main__":    app = QApplication(sys.argv)    app.setFont(QFont("Microsoft YaHei"9))    app.setStyle("Fusion")    win = MainWindow()    win.show()    sys.exit(app.exec_())

💡 提示:由于公众号排版限制,上方 _build_ui 后的方法(_select_file_parse_file_start_stop_on_finished 等)请参照前文代码解析部分的完整逻辑。实际运行请使用文末 GitHub 链接获取完整文件。


📚 第五部分:知识点总结

核心技术栈

技术
用途
关键点
PyQt5
GUI 框架
QMainWindow + QSS 样式 + 信号槽机制
pyqtSignal
线程通信
子线程不能直接操作UI,必须通过信号
ThreadPoolExecutor
并发执行
concurrent.futures
 标准库,比手动管理线程简单
requests + stream
HTTP 检测
stream=True
 避免下载整个流,只读头部判断
正则表达式
格式解析
解析 M3U 的 #EXTINF 行和 TXT 的逗号分隔

关键设计模式

  1. 生产者-消费者模式:VerifyEngine 生产验证结果 → Signals 传递 → MainWindow 消费并更新 UI
  2. 策略模式:根据文件扩展名自动选择解析策略(TXT/M3U/JSON)
  3. 观察者模式pyqtSignal 本质就是观察者模式的实现

Python 知识要点

  • os.path.abspath(__file__) — 获取脚本自身绝对路径
  • {**dict1, "key": val} — 字典合并(Python 3.5+)
  • as_completed(futures) — 哪个线程先完成就先处理哪个(非顺序)
  • resp.raw.read(512) — 底层 socket 级别读取,比 resp.text 快
  • datetime.now().strftime("%Y%m%d_%H%M%S") — 时间戳格式化

🚀 第六部分:拓展场景与测试步骤

测试步骤

  1. 安装依赖

    pip install PyQt5 requests
  2. 准备源文件(任选一种格式)

    TXT 格式 (test.txt):

    CCTV1,http://example.com/cctv1.m3u8湖南卫视,http://example.com/hunan.m3u8

    M3U 格式 (test.m3u):

    #EXTM3U#EXTINF:-1,CCTV1http://example.com/cctv1.m3u8
  3. 运行程序

    python gui_v2.py
  4. 操作流程

    • 点击「📂 选择文件」→ 选择你的源文件
    • 确认显示"✅ XX 条"
    • 调整超时和线程数(默认即可)
    • 点击「🚀 开始验证」
    • 观察日志实时滚动,等待完成
    • 点击「📂 打开输出目录」查看结果文件

拓展应用场景

场景
改造方式
定时自动执行
用 Windows 任务计划程序 或 Linux crontab 定时调用
GitHub Actions 自动化
添加 .github/workflows/update.yml,每天自动检测并提交结果
对接电视盒子
输出的 M3U 文件直接导入 Kodi / TiviMate / 电视家
Web 版本
用 Flask/FastAPI 包一层接口,前端展示结果
增加源采集
爬取公开的直播源分享网站,自动合并到检测列表
通知推送
检测完成后通过企业微信/钉钉机器人推送可用频道数
导入播放器
输出的 JSON 可直接导入本项目的 UniApp 播放器或 Python 桌面播放器

性能优化建议

  • 线程数设为 20-30 可加快速度,但注意别被目标 IP 封禁
  • 超时设为 3 秒可以过滤掉慢源,只保留响应快的
  • 大文件(1000+ 条)建议分批验证,避免内存压力

✍️ 结语

这个小工具虽然代码量不大,但涵盖了 PyQt5 GUI 开发中最核心的几个难题:多线程不卡UI实时日志输出进度反馈文件IO。希望这篇文章能帮助你理解 Python 桌面应用开发的完整流程。

如果觉得有用,欢迎 点赞 + 收藏 + 转发,你的支持是我持续输出的动力!

📌 完整源码获取:关注公众号回复 直播源 获取全部代码和测试数据。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-21 14:39:32 HTTP/2.0 GET : https://f.mffb.com.cn/a/504827.html
  2. 运行时间 : 0.596879s [ 吞吐率:1.68req/s ] 内存消耗:4,616.48kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=3f3b500549dcb6aa621348167bfd4e8a
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000953s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001372s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.062336s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000646s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001532s ]
  6. SELECT * FROM `set` [ RunTime:0.000573s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001429s ]
  8. SELECT * FROM `article` WHERE `id` = 504827 LIMIT 1 [ RunTime:0.008118s ]
  9. UPDATE `article` SET `lasttime` = 1787294373 WHERE `id` = 504827 [ RunTime:0.095752s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000690s ]
  11. SELECT * FROM `article` WHERE `id` < 504827 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001796s ]
  12. SELECT * FROM `article` WHERE `id` > 504827 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.015222s ]
  13. SELECT * FROM `article` WHERE `id` < 504827 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.008066s ]
  14. SELECT * FROM `article` WHERE `id` < 504827 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.102752s ]
  15. SELECT * FROM `article` WHERE `id` < 504827 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.100274s ]
0.602900s