当前位置:首页>python>Python Tkinter 从零到一:实现高性能屏幕录制器完全指南

Python Tkinter 从零到一:实现高性能屏幕录制器完全指南

  • 2026-06-30 15:43:39
Python Tkinter 从零到一:实现高性能屏幕录制器完全指南

🎬 你真的需要一个自己写的录屏工具吗?

先说结论:需要,而且非常值得。

市面上的录屏软件要么臃肿、要么收费、要么在某些企业内网环境下根本装不上。作为 Python 开发者,我们手里有 Tkinter、有 OpenCV、有 threading——完全可以在一个下午的时间里,从零撸出一个轻量、可控、可二次开发的屏幕录制工具。

我在给内部团队做技术分享录制时,就踩过这个坑:OBS 太重,ShareX 在某台老机器上崩溃,最后索性自己写。写完之后发现,不过 300 行代码,性能却出乎意料地稳。帧率稳在 25fps,CPU 占用不超过 15%。这篇文章,就把这套思路完整拆给你看。


🧱 技术选型:为什么是这套组合?

核心依赖只有三个:

  • • Tkinter:Python 内置 GUI 库,零安装成本,跨平台
  • • Pillow(PIL):截图能力,ImageGrab.grab() 在 Windows 下性能相当可观
  • • OpenCV(cv2):视频编码写入,VideoWriter 支持多种编解码器

有人会问,为什么不用 pyautogui 截图?原因很简单——pyautogui.screenshot() 底层也是调 PIL,但多了一层封装,速度反而更慢。直接用 ImageGrab 是最短路径。

另外,帧率控制这块,咱们用 threading.Event 配合时间戳对齐,而不是简单粗暴地 time.sleep()。这个细节差别很大,后面会详细讲。


🔧 环境准备

1pip install pillow opencv-python numpy

Tkinter 是 Python 标准库的一部分,Windows 下安装 Python 时默认勾选,一般不需要额外安装。如果你用的是精简版 Python 环境,执行 import tkinter 报错的话,重装一遍 Python 并勾选 tcl/tk 组件即可。


🏗️ 整体架构设计

在动手写代码之前,先把架构想清楚。这个录制器分三层:

1┌─────────────────────────────────┐
2│         Tkinter GUI 层           │  ← 用户交互、状态展示
3├─────────────────────────────────┤
4│         录制控制层               │  ← 线程调度、帧率控制
5├─────────────────────────────────┤
6│         底层采集 & 编码层         │  ← 截图、帧写入
7└─────────────────────────────────┘

GUI 层和录制逻辑必须跑在不同线程上。这不是可选项,是必须的——录制是 CPU 密集型操作,如果塞在主线程里,界面会直接卡死,按钮点不动,体验极差。


💻 完整代码实现

📁 项目结构

1screen_recorder/
2├── main.py          # 入口文件
3├── recorder.py      # 录制核心逻辑
4└── ui.py            # Tkinter 界面

🎯 第一步:录制核心模块 recorder.py

这是整个项目最关键的部分。帧率控制的精髓在这里。

1import cv2
2import numpy as np
3import threading
4import time
5from PIL import ImageGrab
6
7class ScreenRecorder:
8def __init__(self, output_path, fps=25, region=None):
9"""
10        output_path: 输出文件路径,如 'output.mp4'
11        fps: 目标帧率
12        region: 录制区域 (x1, y1, x2, y2),None 表示全屏
13        """
14        self.output_path = output_path
15        self.fps = fps
16        self.region = region
17        self.is_recording = False
18        self._stop_event = threading.Event()
19        self._thread = None
20        self.frame_count = 0
21        self.actual_fps = 0.0
22
23def _get_screen_size(self):
24"""获取录制区域尺寸"""
25if self.region:
26            x1, y1, x2, y2 = self.region
27return (x2 - x1, y2 - y1)
28# 全屏尺寸
29import tkinter as tk
30        root = tk.Tk()
31        w = root.winfo_screenwidth()
32        h = root.winfo_screenheight()
33        root.destroy()
34return (w, h)
35
36def _capture_frame(self):
37"""截取一帧,转换为 OpenCV 格式"""
38        img = ImageGrab.grab(bbox=self.region)
39# PIL Image (RGB) → numpy array → BGR (OpenCV 格式)
40        frame = np.array(img)
41        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
42return frame
43
44def _record_loop(self):
45"""核心录制循环,精确帧率控制"""
46        width, height = self._get_screen_size()
47
48# 使用 mp4v 编解码器,兼容性最好
49        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
50        writer = cv2.VideoWriter(
51            self.output_path, fourcc, self.fps, (width, height)
52        )
53
54if not writer.isOpened():
55raise RuntimeError(f"无法创建视频文件: {self.output_path}")
56
57        frame_interval = 1.0 / self.fps
58        start_time = time.perf_counter()
59        self.frame_count = 0
60
61try:
62while not self._stop_event.is_set():
63                frame_start = time.perf_counter()
64
65# 截图 & 写帧
66                frame = self._capture_frame()
67                writer.write(frame)
68                self.frame_count += 1
69
70# 精确帧间隔控制(关键!)
71                elapsed = time.perf_counter() - frame_start
72                sleep_time = frame_interval - elapsed
73if sleep_time > 0:
74                    time.sleep(sleep_time)
75
76# 实时计算实际帧率
77                total_elapsed = time.perf_counter() - start_time
78if total_elapsed > 0:
79                    self.actual_fps = self.frame_count / total_elapsed
80
81finally:
82            writer.release()
83
84def start(self):
85"""启动录制(非阻塞)"""
86if self.is_recording:
87return
88        self._stop_event.clear()
89        self.is_recording = True
90        self._thread = threading.Thread(
91            target=self._record_loop, daemon=True
92        )
93        self._thread.start()
94
95def stop(self):
96"""停止录制,等待线程结束"""
97if not self.is_recording:
98return
99        self._stop_event.set()
100        self._thread.join(timeout=5)
101        self.is_recording = False
102
103def get_stats(self):
104"""返回当前录制统计信息"""
105return {
106"frame_count": self.frame_count,
107"actual_fps"round(self.actual_fps, 1)
108        }

这里有个细节值得展开说——time.perf_counter() 而不是 time.time()。前者是高精度计时器,在 Windows 下精度能到微秒级;后者在某些系统上精度只有 10-15ms,对帧率控制来说误差太大了。

🎨 第二步:界面模块 ui.py

界面不求华丽,但信息要到位:录制状态、实际帧率、已录帧数,一眼就能看清楚。

1import tkinter as tk
2from tkinter import ttk, filedialog, messagebox
3import threading
4from recorder import ScreenRecorder
5
6class RecorderUI:
7def __init__(self):
8        self.root = tk.Tk()
9        self.root.title("屏幕录制器")
10        self.root.geometry("420x320")
11        self.root.resizable(FalseFalse)
12
13        self.recorder = None
14        self._stats_job = None  # 用于取消定时任务
15
16        self._build_ui()
17
18def _build_ui(self):
19"""构建界面布局"""
20        pad = {"padx"12"pady"6}
21
22# ── 输出文件选择 ──
23        file_frame = ttk.LabelFrame(self.root, text="输出文件", padding=8)
24        file_frame.pack(fill="x", **pad)
25
26        self.path_var = tk.StringVar(value="output.mp4")
27        ttk.Entry(file_frame, textvariable=self.path_var, width=30).pack(
28            side="left", padx=(06)
29        )
30        ttk.Button(
31            file_frame, text="浏览", command=self._choose_file
32        ).pack(side="left")
33
34# ── 录制参数 ──
35        param_frame = ttk.LabelFrame(self.root, text="录制参数", padding=8)
36        param_frame.pack(fill="x", **pad)
37
38        ttk.Label(param_frame, text="目标帧率 (FPS):").grid(
39            row=0, column=0, sticky="w"
40        )
41        self.fps_var = tk.IntVar(value=25)
42        ttk.Spinbox(
43            param_frame, from_=5, to=60, textvariable=self.fps_var, width=8
44        ).grid(row=0, column=1, padx=8)
45
46        ttk.Label(param_frame, text="录制区域:").grid(
47            row=1, column=0, sticky="w", pady=(60)
48        )
49        self.region_var = tk.StringVar(value="全屏")
50        region_combo = ttk.Combobox(
51            param_frame,
52            textvariable=self.region_var,
53            values=["全屏""自定义区域"],
54            state="readonly",
55            width=12
56        )
57        region_combo.grid(row=1, column=1, padx=8, pady=(60))
58
59# ── 状态信息 ──
60        status_frame = ttk.LabelFrame(self.root, text="录制状态", padding=8)
61        status_frame.pack(fill="x", **pad)
62
63        self.status_label = ttk.Label(
64            status_frame, text="就绪", foreground="gray"
65        )
66        self.status_label.pack(anchor="w")
67
68        self.stats_label = ttk.Label(
69            status_frame, text="帧率: -- | 已录帧数: --"
70        )
71        self.stats_label.pack(anchor="w")
72
73# ── 控制按钮 ──
74        btn_frame = ttk.Frame(self.root)
75        btn_frame.pack(pady=10)
76
77        self.start_btn = ttk.Button(
78            btn_frame, text="▶ 开始录制", command=self._start_recording, width=14
79        )
80        self.start_btn.pack(side="left", padx=6)
81
82        self.stop_btn = ttk.Button(
83            btn_frame, text="■ 停止录制", command=self._stop_recording,
84            width=14, state="disabled"
85        )
86        self.stop_btn.pack(side="left", padx=6)
87
88def _choose_file(self):
89        path = filedialog.asksaveasfilename(
90            defaultextension=".mp4",
91            filetypes=[("MP4 视频""*.mp4"), ("所有文件""*.*")]
92        )
93if path:
94            self.path_var.set(path)
95
96def _start_recording(self):
97        output = self.path_var.get().strip()
98if not output:
99            messagebox.showwarning("提示""请先选择输出文件路径")
100return
101
102        fps = self.fps_var.get()
103        region = None  # 暂时只支持全屏,自定义区域可扩展
104
105        self.recorder = ScreenRecorder(output, fps=fps, region=region)
106
107try:
108            self.recorder.start()
109except Exception as e:
110            messagebox.showerror("错误"f"录制启动失败:{e}")
111return
112
113        self.start_btn.config(state="disabled")
114        self.stop_btn.config(state="normal")
115        self.status_label.config(text="录制中...", foreground="red")
116
117# 每秒刷新一次状态
118        self._update_stats()
119
120def _stop_recording(self):
121if self.recorder:
122# 停止定时刷新
123if self._stats_job:
124                self.root.after_cancel(self._stats_job)
125                self._stats_job = None
126
127# 停止录制(可能耗时,放子线程避免界面卡顿)
128def _do_stop():
129                self.recorder.stop()
130                stats = self.recorder.get_stats()
131                self.root.after(0lambda: self._on_stopped(stats))
132
133            threading.Thread(target=_do_stop, daemon=True).start()
134
135def _on_stopped(self, stats):
136"""录制停止后的 UI 更新(必须在主线程执行)"""
137        self.start_btn.config(state="normal")
138        self.stop_btn.config(state="disabled")
139        self.status_label.config(text="录制完成", foreground="green")
140        self.stats_label.config(
141            text=f"帧率: {stats['actual_fps']} | 总帧数: {stats['frame_count']}"
142        )
143        messagebox.showinfo(
144"完成"f"录制完成!\n共 {stats['frame_count']} 帧\n"
145f"实际帧率: {stats['actual_fps']} fps\n"
146f"文件: {self.path_var.get()}"
147        )
148
149def _update_stats(self):
150"""定时刷新录制状态(在主线程调用)"""
151if self.recorder and self.recorder.is_recording:
152            stats = self.recorder.get_stats()
153            self.stats_label.config(
154                text=f"帧率: {stats['actual_fps']} fps | 已录帧数: {stats['frame_count']}"
155            )
156# 1000ms 后再次调用自身
157            self._stats_job = self.root.after(1000, self._update_stats)
158
159def run(self):
160        self.root.mainloop()

🚀 第三步:入口文件 main.py

1from ui import RecorderUI
2
3if __name__ == "__main__":
4    app = RecorderUI()
5    app.run()

就这三行。干净。


⚡ 性能优化:从"能用"到"好用"

帧率为什么对不上?

这是最常见的问题。你设置了 25fps,实际跑出来可能只有 18fps。原因通常有两个:

截图本身耗时。ImageGrab.grab() 在全屏 1080p 下,单次调用耗时大约 20~40ms,本身就快接近一帧的时间预算了(25fps = 40ms/帧)。解决方案是降低录制分辨率,或者缩小录制区域——很多时候你根本不需要录整个屏幕。

编码写入耗时。cv2.VideoWriter.write() 是同步操作,压缩编码会占用一定时间。进阶做法是引入双缓冲队列:截图线程只负责把帧放进队列,另一个编码线程从队列里取帧写入文件,两者互不阻塞。

1# 双缓冲队列示意(进阶版)
2import queue
3
4frame_queue = queue.Queue(maxsize=30)  # 最多缓冲 30 帧
5
6def capture_thread():
7while not stop_event.is_set():
8        frame = _capture_frame()
9try:
10            frame_queue.put_nowait(frame)
11except queue.Full:
12pass  # 队列满了就丢帧,优先保证实时性
13
14def encode_thread():
15while not stop_event.is_set() or not frame_queue.empty():
16try:
17            frame = frame_queue.get(timeout=0.1)
18            writer.write(frame)
19except queue.Empty:
20continue

这个改动能让截图和编码并行运行,帧率稳定性明显提升。

内存别让它无限涨

队列的 maxsize=30 这个参数很重要。如果不限制,在编码速度跟不上截图速度时,队列会无限积压帧数据,内存蹭蹭往上涨。30 帧大约是 1 秒的缓冲量,超出就主动丢帧——对录屏来说,偶尔丢一两帧远比内存爆掉要好。


🕳️ 踩坑预警

坑一:视频文件打不开。 用 mp4v 编解码器生成的 .mp4 文件,在某些播放器下可能无法正常播放。换成 avc1(H.264)通常能解决,但需要系统安装了对应的编解码器。最稳妥的方案是生成后用 FFmpeg 转一遍:ffmpeg -i output.mp4 -vcodec libx264 final.mp4

坑二:多显示器截图区域错乱。ImageGrab.grab() 在多显示器环境下,坐标系是以主显示器左上角为原点的。如果你的副屏在主屏左边,坐标会出现负值,需要特殊处理。

坑三:after() 不能在子线程调用。 Tkinter 的 GUI 操作必须在主线程执行。子线程想更新界面,只能通过 root.after(0, callback) 把操作调度回主线程,或者用线程安全的队列传递消息。代码里 _on_stopped 的写法就是标准做法,别嫌麻烦。

坑四:程序退出时线程没清理干净。 录制线程设置了 daemon=True,这意味着主线程退出时它会被强制终止。但 VideoWriter 可能来不及 release(),导致视频文件损坏。建议在窗口关闭事件里显式调用 stop()

1self.root.protocol("WM_DELETE_WINDOW", self._on_close)
2
3def _on_close(self):
4if self.recorder and self.recorder.is_recording:
5        self._stop_recording()
6    self.root.destroy()

🧩 扩展方向

这套基础框架搭好之后,可以往很多方向延伸:

  • • 加入音频录制:用 pyaudio 同步采集麦克风或系统音频,再用 FFmpeg 合并音视频轨道
  • • 自定义录制区域:在界面上拖拽选框,把坐标传给 ImageGrab.grab(bbox=...)
  • • GIF 导出:把帧序列用 Pillow 的 save() 方法直接导出为 GIF,适合录制短片段用于文档说明
  • • 定时录制:加一个倒计时启动功能,方便录制需要提前准备的操作

📌 三句话总结

  1. 1. Tkinter + Pillow + OpenCV 这套组合,300 行代码就能实现一个生产可用的录屏工具。
  2. 2. 帧率稳定的关键在于精确的时间控制(perf_counter)和截图/编码的解耦(双缓冲队列)。
  3. 3. GUI 和录制逻辑必须分线程,Tkinter 的 UI 操作必须回到主线程执行——这两条是避坑的核心原则。

#Python#Tkinter#屏幕录制#OpenCV#多线程编程

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-04 07:16:20 HTTP/2.0 GET : https://f.mffb.com.cn/a/489829.html
  2. 运行时间 : 0.309713s [ 吞吐率:3.23req/s ] 内存消耗:4,784.99kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=43b9a30b08cb17f83a0b19b83498b1f4
  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.000919s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001639s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.008849s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.030169s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001645s ]
  6. SELECT * FROM `set` [ RunTime:0.000573s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001336s ]
  8. SELECT * FROM `article` WHERE `id` = 489829 LIMIT 1 [ RunTime:0.013647s ]
  9. UPDATE `article` SET `lasttime` = 1783120580 WHERE `id` = 489829 [ RunTime:0.022314s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000618s ]
  11. SELECT * FROM `article` WHERE `id` < 489829 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.013484s ]
  12. SELECT * FROM `article` WHERE `id` > 489829 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.034088s ]
  13. SELECT * FROM `article` WHERE `id` < 489829 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.011176s ]
  14. SELECT * FROM `article` WHERE `id` < 489829 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.008431s ]
  15. SELECT * FROM `article` WHERE `id` < 489829 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.002858s ]
0.312785s