当前位置:首页>Excel>Word和Excel批量替换不好使?那咱手搓一个!

Word和Excel批量替换不好使?那咱手搓一个!

  • 2026-06-01 01:26:13
Word和Excel批量替换不好使?那咱手搓一个!

不想再为“全网搜软件”掀桌子?我用一个小时让大模型手搓了一把匕首。

“众里寻他千百度,蓦然回首,那人却在,灯火阑珊处。”

在传统的办公世界里,为了找一个特定功能的软件,我们常常要在GitHub、搜索引擎、甚至各种破解论坛里反复下载试用,最后得到的可能仍是一堆捆绑或冗余功能的全家桶。但在这个大模型滚滚而来的 Vibe Coding(灵感流编程)时代,这种“全网搜软件”的传统范式,可能真的要被降维打击了。

遇到极其客制化的琐碎痛点怎么办?顶级玩家的选择通常是:不搜了,我自己造。人类出脑子定架构,剩下的体力活,全权交给大模型。

一、 填坑:从“屠龙宝刀”到“精巧匕首”

前段时间,我为了彻底绝杀 Markdown 的编目排版玄学,刚刚花了巨大心血,拉着两大顶级 AI 搞出了一把准商业级交付的“屠龙刀”——Markdown to PDF Converter(MD2PDF 编书工具)

那款工具确实让我享受到了极致的效能交付。但就在最近,进入项目运营体系文件的模块化微调阶段时,ENTP的知觉毫无征兆地来了。

在封版前的合规性审阅中,大量特定文字需要全局化的规范替换。比如,需要将数十个混合类型文档里的“项目物业服务中心”全部严谨地更正为“物业管理服务中心”。而最扎心的是,这些文字不仅散落在 Markdown 源码里,还夹杂在大量做台账的 Excel 表格和写汇报的 Word 文档中。

体系文件的编制,特定文字的修改往往是全局性的。如果仅因为一个表述变更,就要把这N类文件分别拖进N个不同的小工具里去过N遍流水线,这简直是对【平台化精益运营】理念的公然羞辱。

二、 凡尔赛的代价:拒绝被GitHub的破轮子妥协

GitHub 上不是没有现成的批量替换器,但全网搜了一圈,那些野生脚本要么臃肿得像个全家桶,要么就是粗暴替换时直接把我原本精美的 OOXML 排版冲刷得稀烂。

对于一个在《白皮书》里立过规矩、对代码和视觉有着重度工程洁癖的人来说,去削足适履地去适应别人的烂逻辑,比我自己写一个还要痛苦。

所以还是那句话:既然市面上找不到称手的兵器,那我就亲手打一把。

不需要参考任何现成的项目,我直接坐在架构师的交椅上定下了“大一统”的底层控制流拓扑。个把小时、喝杯咖啡的功夫,在 AI 强劲算力的疯狂倾泻下,这把专为微调而生的精巧匕首——Multi_Replacer_GUI(多格式文档极速批量替换工具)就这么在从 0 到 1 的心流中平地起高楼,完美封板。

三、 极简的锋利:这很 Vibe Coding

虽然只是个手搓出来的边角小作,但本着极客精神,该立的规矩一字不能少:

  • 跨格式大一统:一键拖拽,直接横穿 .md.docx.xlsx(强力支持 Excel 单个工作簿下的多工作表 Sheet 矩阵级穿透遍历),一次点击,全局搞定。
  • 高傲的物理拦截:从代码物理层面上,坚决拒收远古时代的 .doc 与 .xls 格式,如果拖入,日志窗会直接予以温和但坚定的拦截。这不是妥协,这是为了守护底层代码的纯洁性,拒绝和微软老旧的 COM 自动化幽灵进程捉迷藏。
  • 多级防丢备份隔离:沿用了我一贯的原子化 IO 传统(写临时文件 → fsync 落盘 → 原子覆盖)。勾选备份后,单文件直接衍生 .bak,多文件自动同频封包为带有毫秒级时间戳的 ZIP 归档。
  • 一星秒杀快捷宏:在加减号旁,我刻意微调了一个“*”号按键(星号宏)。鼠标悬停提示“加载物业规则”,一键点击,自动把物业领域的体系高频词条塞进框内,实现行业级生产力的硬核微雕。

其 UI 风格,更是完美继承了我上一个工具的“极客美学”与 1B+2B 级的手术级 CSS 覆写,滚动条箭头清零,零视觉噪音。

四、 开源与 43.8MB 的强迫症

为了让这把匕首具备真正的“商业级交付”品质,摆脱一切恶心的本地 Python 依赖,在工程层的自动化打包流水线里,我把一整套现代 Office 极其沉重的 XML 解析引擎全部无痕吞噬、暴力内化了。

其代价就是,最终编译出来的独立沙盒单体 EXE,体积达到了 43.8MB

对于一个追求极致轻量化的极客来说,这个刀鞘多少显得有些“重”了。虑及不少同行本机并没有 Python 环境,为了照顾所有人,我做了一个很Easy的决定:

业务层PY开源发布+EXE同步推送

如果你是嫌折腾、只想双击即焚、开箱即用的办公效率派,那就直接去网盘下载那尊 43.8MB 的脱机单体版 EXE。而若你追求极简、本机有Python环境的硬核玩家,直接拿走仅几百行的 Python 源码跑脚本,轻盈如风。

在 AI 时代,我们没有必要转行去当程序员,但是必须学会做架构师。但面对滚滚而来的浪潮,谁能率先更新自己内在的“工作方法论操作系统”,谁就能一个人活成一支军队。

📥 [Multi_Replacer_GUI v0.3] 交付通道

【以下无正文,END】


# ==============================================================================# 全局元数据区 (Business Layer Metadata)# ==============================================================================APP_VERSION = "v0.3"OPERATION_CODE = "[Operation Clarity]"DISPLAY_VERSION = f"{APP_VERSION} {OPERATION_CODE}"BUILD_DATE = "20260525"FUNC_DESC = "多格式文档极速批量替换工具"AUTHOR_INFO = "主创:哲哥说 | 协同:Gemini"COMPANY_NAME = "哲哥说@VibeFox"import osimport sysimport timeimport tracebackimport shutilimport zipfileimport datetimefrom pathlib import Path# ==============================================================================# 终端样式系统与优雅降级 (Style Dependencies)# ==============================================================================try:    from colorama import init as _ca_init, Fore, Style    _ca_init(autoreset=True)    C_RED = Fore.LIGHTRED_EX + Style.BRIGHT    C_CYAN = Fore.LIGHTCYAN_EX + Style.BRIGHT    C_YELLOW = Fore.LIGHTYELLOW_EX + Style.BRIGHTexcept ImportError:    os.system("")  # 激活 Windows 原生 ANSI    C_RED = "\033[91;1m"    C_CYAN = "\033[96;1m"    C_YELLOW = "\033[93;1m"def red(text): return f"{C_RED}{text}\033[0m"def cyan(text): return f"{C_CYAN}{text}\033[0m"def yellow(text): return f"{C_YELLOW}{text}\033[0m"def safe_input(prompt=""):"""安全输入钩子:防冻结态阻塞,防幽灵挂死"""if prompt:        sys.stdout.write(prompt)        sys.stdout.flush()    try:return input()    except Exception:return ""# ==============================================================================# 核心依赖探针与分级熔断 (Core Dependencies)# ==============================================================================# [P8_DESIGN_CHOICE]: 核心依赖 PyQt5 及 Office 解析引擎熔断块,包含内联暂停等待机制try:    from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,                                 QPushButton, QLineEdit, QTextEdit, QLabel,                                 QFileDialog, QScrollArea, QFrame, QMessageBox,                                 QCheckBox, QSizePolicy)    from PyQt5.QtCore import Qt    from PyQt5.QtGui import QIconexcept ImportError:print(red("\n[!] 缺失界面核心依赖 PyQt5,请执行: pip install PyQt5\n"))    sys.stdout.write("    按回车键退出...")    sys.stdout.flush()    try: input()    except Exception: pass    sys.exit(1)try:    import docx    import openpyxlexcept ImportError:print(red("\n[!] 缺失 Office 文档解析引擎,请执行: pip install python-docx openpyxl\n"))    sys.stdout.write("    按回车键退出...")    sys.stdout.flush()    try: input()    except Exception: pass    sys.exit(1)# ==============================================================================# 图标系统双态环境自适应句柄注入引擎# ==============================================================================def try_inject_icon():"""    [P8_DESIGN_CHOICE]: 双态图标嗅探与跨平台句柄注入    支持打包态(sys._MEIPASS)与源码态(同级目录)下的图标自动检索。    """    icon_name = "zhegesay.ico"    icon_path = Noneif getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):        bundled_path = Path(sys._MEIPASS) / icon_nameif bundled_path.exists():            icon_path = bundled_pathif not icon_path:        local_path = Path(__file__).parent / icon_nameif local_path.exists():            icon_path = local_pathif not icon_path:return None    icon_path_str = str(icon_path.resolve())    try:        import ctypes        hwnd = ctypes.windll.kernel32.GetConsoleWindow()if hwnd:            hicon = ctypes.windll.user32.LoadImageW(0, icon_path_str, 1, 0, 0, 0x00000010)if hicon:                WM_SETICON = 0x0080                ctypes.windll.user32.SendMessageW(hwnd, WM_SETICON, 0, hicon)                ctypes.windll.user32.SendMessageW(hwnd, WM_SETICON, 1, hicon)    except Exception:        passreturn icon_path_str# ==============================================================================# 核心业务逻辑与 GUI 控件区 (Core Engine)# ==============================================================================class FileDropArea(QTextEdit):"""支持系统级拖拽的自定义文本框,附带智能格式拦截系统"""    def __init__(self, parent_logger=None, parent=None):        super().__init__(parent)        self.parent_logger = parent_logger        self.setAcceptDrops(True)        self.setReadOnly(True)# [UI微调]: 插入精准的换行符以优化视觉排版        self.setPlaceholderText("将 .md / .docx / .xlsx 文件直接拖入此框中...\n\n(注意:为保障数据绝对安全,本工具拒收远古时代的 .doc 与 .xls 格式,\n请将其另存为新版格式后使用)")        self.setStyleSheet("background-color: #f8f9fa; border: 1px dashed #ced4da; padding: 5px;")    def dragEnterEvent(self, event):if event.mimeData().hasUrls():            event.acceptProposedAction()else:            event.ignore()    def dragMoveEvent(self, event):if event.mimeData().hasUrls():            event.acceptProposedAction()else:            event.ignore()    def dropEvent(self, event):        urls = event.mimeData().urls()for url in urls:            file_path = url.toLocalFile()            self.process_incoming_file(file_path)        event.acceptProposedAction()    def process_incoming_file(self, file_path):        ext = Path(file_path).suffix.lower()if ext in ['.md''.docx''.xlsx']:if file_path not in self.toPlainText():                self.append(file_path)elif ext in ['.doc''.xls']:if self.parent_logger:                self.parent_logger(f"   [拦截] 拒绝摄入 {Path(file_path).name}。请打开它并另存为 .docx 或 .xlsx 以脱离旧版组件束缚。")else:            passclass ReplacementRow(QFrame):"""动态替换行组件,包含原文本、新文本与增减按钮"""    def __init__(self, parent_layout, parent_widget):        super().__init__()        self.parent_layout = parent_layout        self.parent_widget = parent_widget        self.init_ui()    def init_ui(self):        self.setFrameShape(QFrame.StyledPanel)        layout = QHBoxLayout(self)        layout.setContentsMargins(5, 5, 5, 5)        self.old_text_input = QLineEdit()# [UI微调]: 修正文案为“查找什么”        self.old_text_input.setPlaceholderText("查找什么 (原始文本)")        layout.addWidget(self.old_text_input)        self.new_text_input = QLineEdit()        self.new_text_input.setPlaceholderText("换成什么 (目标文本)")        layout.addWidget(self.new_text_input)# 挂载业务侧高频规则快捷键 (星号宏)        self.star_btn = QPushButton("*")        self.star_btn.setFixedWidth(30)        self.star_btn.setToolTip("加载物业规则")        self.star_btn.clicked.connect(self.load_property_rule)        layout.addWidget(self.star_btn)        self.add_btn = QPushButton("+")        self.add_btn.setFixedWidth(30)        self.add_btn.setToolTip("新增替换规则")        self.add_btn.clicked.connect(self.parent_widget.add_replacement_row)        layout.addWidget(self.add_btn)        self.remove_btn = QPushButton("-")        self.remove_btn.setFixedWidth(30)        self.remove_btn.setToolTip("删除替换规则")        self.remove_btn.clicked.connect(self.remove_self)        layout.addWidget(self.remove_btn)    def load_property_rule(self):"""一键填充物业系统专有名词规范化"""        self.old_text_input.setText("项目物业服务中心")        self.new_text_input.setText("物业管理服务中心")    def remove_self(self):if self.parent_layout.count() > 2:            self.parent_layout.removeWidget(self)            self.deleteLater()else:            self.old_text_input.clear()            self.new_text_input.clear()    def get_rule(self):return self.old_text_input.text(), self.new_text_input.text()class MainApp(QWidget):"""主控界面类"""    def __init__(self, icon_file_path=None):        super().__init__()        self.icon_file_path = icon_file_path        self.init_ui()    def init_ui(self):        self.setWindowTitle(f"{FUNC_DESC} {DISPLAY_VERSION} | {COMPANY_NAME}")        self.resize(700, 650)        main_layout = QVBoxLayout(self)if self.icon_file_path:            self.setWindowIcon(QIcon(self.icon_file_path))# 1. 文件选择区        file_header_layout = QHBoxLayout()        file_header_layout.addWidget(QLabel("1. 添加待处理的文档 (支持 MD / DOCX / XLSX):"))        btn_add_files = QPushButton("浏览文件...")        btn_add_files.clicked.connect(self.browse_files)        file_header_layout.addWidget(btn_add_files)        main_layout.addLayout(file_header_layout)        self.file_drop_area = FileDropArea(parent_logger=self.log)        self.file_drop_area.setFixedHeight(120)        main_layout.addWidget(self.file_drop_area)# 2. 替换规则区        main_layout.addWidget(QLabel("\n2. 设定全局替换规则 (由上至下依序执行):"))        self.rules_scroll = QScrollArea()        self.rules_scroll.setWidgetResizable(True)        self.rules_widget = QWidget()        self.rules_layout = QVBoxLayout(self.rules_widget)        self.add_replacement_row()        self.rules_layout.addStretch()        self.rules_scroll.setWidget(self.rules_widget)        main_layout.addWidget(self.rules_scroll)# 3. 大一统全局执行按钮 (移除约束,随窗体自适应最大化延展)        self.btn_execute = QPushButton("开 始 全 局 替 换")        self.btn_execute.setFixedHeight(40)        self.btn_execute.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)        self.btn_execute.setStyleSheet("font-weight: bold; background-color: #4CAF50; color: white;")        self.btn_execute.clicked.connect(self.execute_replacement)        main_layout.addWidget(self.btn_execute)# 4. 日志窗头与备份复选框平齐对齐区        log_header_layout = QHBoxLayout()        log_header_layout.addWidget(QLabel("3. 运行日志与执行报告:"))        log_header_layout.addStretch()  # 利用弹簧将复选框顶至最右侧        self.chk_backup = QCheckBox("执行前备份源文件 (推荐)")        self.chk_backup.setChecked(True)        self.chk_backup.setStyleSheet("font-weight: bold; color: #495057;")        log_header_layout.addWidget(self.chk_backup)        main_layout.addLayout(log_header_layout)# 日志窗本体        self.log_area = QTextEdit()        self.log_area.setReadOnly(True)        self.log_area.setStyleSheet("background-color: #212529; color: #00ff00; font-family: Consolas;")        main_layout.addWidget(self.log_area)        self.log(f"[{COMPANY_NAME}] 大一统多引擎替换器加载完毕。代号: {OPERATION_CODE}")if self.icon_file_path:            self.log(f"   [状态] 成功挂载 {Path(self.icon_file_path).name} 专属图腾。")    def add_replacement_row(self):        new_row = ReplacementRow(self.rules_layout, self)        count = self.rules_layout.count()        self.rules_layout.insertWidget(count - 1, new_row)    def browse_files(self):        filters = "支持的文档格式 (*.md *.docx *.xlsx);;Markdown (*.md);;Word 文档 (*.docx);;Excel 表格 (*.xlsx);;All Files (*)"        files, _ = QFileDialog.getOpenFileNames(self, "选择待处理的文档""", filters)for f in files:            self.file_drop_area.process_incoming_file(f)    def log(self, message):        self.log_area.append(message)        self.log_area.verticalScrollBar().setValue(self.log_area.verticalScrollBar().maximum())        QApplication.processEvents()    def get_all_rules(self):        rules = []for i in range(self.rules_layout.count() - 1):            widget = self.rules_layout.itemAt(i).widget()if isinstance(widget, ReplacementRow):                old_t, new_t = widget.get_rule()if old_t:                    rules.append((old_t, new_t))return rules    def execute_replacement(self):        raw_files = self.file_drop_area.toPlainText().strip().split('\n')        files = [f.strip() for f in raw_files if f.strip() and Path(f.strip()).exists()]if not files:            QMessageBox.warning(self, "提示""请至少添加一个有效的文档文件!")return        rules = self.get_all_rules()if not rules:            QMessageBox.warning(self, "提示""请至少设定一条有效的替换规则!")return        self.btn_execute.setEnabled(False)        self.log("\n" + "=" * 60)        self.log(f"激活全局替换流,共 {len(files)} 个待处理文件...")# 前置多级智能防丢备份隔离屏障if self.chk_backup.isChecked():            self.log("[-] 侦测到备份指令,正在构建历史版本沙盒区...")            try:if len(files) == 1:                    file_path = Path(files[0])                    bak_path = file_path.with_suffix(file_path.suffix + '.bak')                    shutil.copy2(file_path, bak_path)                    self.log(f"   [备份成功] 单文件应急快照点已就绪: {bak_path.name}")else:                    first_file = Path(files[0])                    timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")                    zip_name = f"{first_file.stem}等文件备份+{timestamp}.zip"                    zip_path = first_file.parent / zip_name                    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:for f in files:                            fp = Path(f)                            zipf.write(fp, arcname=fp.name)                    self.log(f"   [备份成功] 多文件防损封包完成: {zip_name}")            except Exception as e:                self.log(f"   [警告] 备份屏障构建失败: {str(e)},基于容错原则降级执行核心逻辑...")        success_files = 0        total_replacements = 0# 多态分发处理器for file_path in files:            self.log(f"-> 正在拆解: {Path(file_path).name}")            ext = Path(file_path).suffix.lower()if ext == '.md':                rep_count = self.atomic_replace_md(file_path, rules)elif ext == '.docx':                rep_count = self.atomic_replace_docx(file_path, rules)elif ext == '.xlsx':                rep_count = self.atomic_replace_xlsx(file_path, rules)else:                self.log(f"   [跳过] 无法识别的后缀系统: {ext}")                rep_count = 0if rep_count > 0:                success_files += 1                total_replacements += rep_count        self.log("=" * 60)        self.log(f"体系重构完毕!成功更新 {success_files} 个文档,共注入替换 {total_replacements} 处。")        self.btn_execute.setEnabled(True)# --------------------------------------------------------------------------# 分布式格式引擎 (Atomic Operations)# --------------------------------------------------------------------------    def atomic_replace_md(self, file_path, replace_rules):"""纯文本体系解析引擎"""        try:            with open(file_path, 'r', encoding='utf-8') as f:                content = f.read()            new_content = content            file_replace_count = 0for old_text, new_text in replace_rules:if old_text in new_content:                    count = new_content.count(old_text)                    file_replace_count += count                    new_content = new_content.replace(old_text, new_text)if file_replace_count == 0:                self.log(f"   [跳过] 内容完全合规,无需修改")return 0            temp_path = f"{file_path}.tmp"            with open(temp_path, 'w', encoding='utf-8') as f:                f.write(new_content)                f.flush()                os.fsync(f.fileno())            os.replace(temp_path, file_path)            self.log(f"   [成功] 纯文本底层替换了 {file_replace_count} 处")return file_replace_count        except Exception as e:            self.log(f"   [失败] MD 解析异常: {str(e)}")return -1    def atomic_replace_docx(self, file_path, replace_rules):"""OOXML Word 体系解析引擎 (穿透段落与表格)"""        try:            doc = docx.Document(file_path)            file_replace_count = 0            def replace_in_paragraphs(paragraphs):                nonlocal file_replace_countfor p in paragraphs:for old_text, new_text in replace_rules:if old_text in p.text:for run in p.runs:if old_text in run.text:                                    count = run.text.count(old_text)                                    run.text = run.text.replace(old_text, new_text)                                    file_replace_count += countif old_text in p.text:                                count = p.text.count(old_text)                                p.text = p.text.replace(old_text, new_text)                                file_replace_count += countfor table in doc.tables:for row in table.rows:for cell in row.cells:                        replace_in_paragraphs(cell.paragraphs)            replace_in_paragraphs(doc.paragraphs)if file_replace_count == 0:                self.log(f"   [跳过] 内容完全合规,无需修改")return 0            temp_path = f"{file_path}.tmp.docx"            doc.save(temp_path)            os.replace(temp_path, file_path)            self.log(f"   [成功] DOCX 体系替换了 {file_replace_count} 处")return file_replace_count        except Exception as e:            self.log(f"   [失败] DOCX 解析异常 (若文件被打开请先关闭): {str(e)}")return -1    def atomic_replace_xlsx(self, file_path, replace_rules):"""OOXML Excel 体系解析引擎 (跨越全 Sheet 矩阵)"""        try:            wb = openpyxl.load_workbook(file_path)            file_replace_count = 0for sheet_name in wb.sheetnames:                sheet = wb[sheet_name]for row in sheet.iter_rows():for cell in row:if isinstance(cell.value, str):for old_text, new_text in replace_rules:if old_text in cell.value:                                    count = cell.value.count(old_text)                                    cell.value = cell.value.replace(old_text, new_text)                                    file_replace_count += countif file_replace_count == 0:                self.log(f"   [跳过] 内容完全合规,无需修改")return 0            temp_path = f"{file_path}.tmp.xlsx"            wb.save(temp_path)            os.replace(temp_path, file_path)            self.log(f"   [成功] XLSX 矩阵替换了 {file_replace_count} 处")return file_replace_count        except Exception as e:            self.log(f"   [失败] XLSX 解析异常 (若文件被打开请先关闭): {str(e)}")return -1# ==============================================================================# 全局崩溃熔断器与应用入口 (Global Entry & Crash Barrier)# ==============================================================================def main():# [P8_DESIGN_CHOICE]: 2B - 环境变量级静音屏蔽    os.environ["QT_LOGGING_RULES"] = "qt.qpa.fonts.warning=false"if getattr(sys, 'frozen', False):        sys.stderr = open(os.devnull, 'w')    app = QApplication(sys.argv)# [P8_DESIGN_CHOICE]: 1B - 手术级 CSS 覆写 (Global Stylesheet Override)    app.setStyleSheet("""        QScrollBar:vertical {            border: none;            background: #f1f3f5;            width: 12px;            margin: 0px 0px 0px 0px;        }        QScrollBar::handle:vertical {            background: #ced4da;            min-height: 30px;            border-radius: 6px;        }        QScrollBar::handle:vertical:hover {            background: #adb5bd;        }        QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {            height: 0px;             background: none;        }        QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {            background: none;        }        QScrollBar:horizontal {            border: none;            background: #f1f3f5;            height: 12px;            margin: 0px 0px 0px 0px;        }        QScrollBar::handle:horizontal {            background: #ced4da;            min-width: 30px;            border-radius: 6px;        }        QScrollBar::handle:horizontal:hover {            background: #adb5bd;        }        QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {            width: 0px;            background: none;        }        QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {            background: none;        }    """)    resolved_icon_path = try_inject_icon()    window = MainApp(icon_file_path=resolved_icon_path)    window.show()    sys.exit(app.exec_())if __name__ == "__main__":    try:        main()    except SystemExit:        pass    except KeyboardInterrupt:        sys.exit(0)    except Exception:print(red("\n======================================================="))print(red(f"  [!] {FUNC_DESC} - 发生致命业务崩溃"))print(red("=======================================================\n"))print(red(traceback.format_exc()))        safe_input("\n按回车键关闭 (请截图留存排障)...")

最新文章

随机文章

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