当前位置:首页>网站源码>【玉箫制作】网页代码压缩工具

【玉箫制作】网页代码压缩工具

  • 2026-04-05 22:45:37
【玉箫制作】网页代码压缩工具

WebCodeCompressor

网页代码压缩工具

1

背景介绍

WebCodeCompressor

网页代码压缩

WebCodeCompressor

作者最初是使用Axure进行原型设计时,发现导出的HTML文件包结构较为复杂,研究了一段时间想看看能不能直接把这个文件包变成前端,最终当然也是以失败告终,不过看到其中有的代码文件存在压缩加密,就想到能不能把自己的代码也做相似的压缩加密,就算做不到加密,只是去注释去缩进来将其变成一长行还是可行的。

这个想法拖了好久才开始去实现,而开发过程中突然发现Minify这个插件,做的正是我想做的事情,而且做的更加成熟,于是开发到一半就停工了,开始用现成的Minify插件,同时发现VUE框架下的前端打包时也是用Minify来压缩代码的(虽然两个可能只是同名并非一个东西)。

但后来我尝试用Minify压缩一个内联CSS和JS的HTML文件时,发现其压缩后运行出错,主要问题就在其中JS部分的注释,经常导致各种一团乱,但是内联CSS和JS的HTML文件对于一个简洁的网页小工具来说是很好的选择,作者也喜欢开发小工具时把所有的代码放在一个文件里面,完整又统一。所以我再次开始了网页代码压缩工具的开发。

遗憾的是,代码从开始的400多行一直升到900多行,不断地查漏补缺,最终也没能完美地解决内联CSS和JS的HTML文件的压缩问题,情况太多总是会出错,作者思量再三之后觉得不如用户遇到错误直接手动删除该处注释,调整一下再重新压缩。

最后,这个网页代码压缩小工具基本能达到和Minify插件一样的压缩效果(可能Minify插件还有更多功能是我的小工具所未实现的)。

附:刚发现微信公众号推送里粘贴进来的代码缩进也有各种问题,一个一个改太费劲了,作者在此就不改了(我记得本身从推送里复制代码就有缩进错误,既然出入都有错误就不如不改),读者可复制代码后让AI修复缩进错误,或直接私信联系作者要代码源文件。

2

软件图示

WebCodeCompressor

WebCodeCompressor

3

软件源代码

WebCodeCompressor

import sysimport osimport reimport jsonfrom PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,                             QHBoxLayout, QPushButton, QLabel, QTextEdit,                             QFileDialog, QMessageBox, QFrame, QListWidget,                             QListWidgetItem, QProgressBar, QSplitter)from PyQt5.QtCore import Qtfrom PyQt5.QtGui import QFontclassWebCodeCompressorApp(QMainWindow):def__init__(self):super().__init__()        self.files = []        self.output_directory = None        self.initUI()definitUI(self):"""初始化用户界面"""        self.setWindowTitle('网页代码压缩工具')        self.setGeometry(1001001000700)        self.setup_style()        self.create_widgets()        self.setup_connections()defsetup_style(self):"""设置界面样式"""        self.setStyleSheet("""            QMainWindow {                background-color: #1a1d23;            }            QWidget {                color: #e0e0e0;                font-family: 'Segoe UI', Arial, sans-serif;            }            QPushButton {                background-color: #2d3748;                border: 2px solid #4a5568;                color: #e0e0e0;                padding: 10px 20px;                border-radius: 4px;                font-weight: bold;                font-size: 12px;            }            QPushButton:hover {                background-color: #4a5568;                border-color: #718096;            }            QPushButton:pressed {                background-color: #1a202c;                border-color: #2d3748;            }            QPushButton:disabled {                background-color: #2d3748;                color: #718096;            }            QListWidget {                background-color: #2d3748;                border: 2px solid #4a5568;                border-radius: 4px;                padding: 5px;                font-size: 12px;            }            QListWidget::item {                padding: 8px;                border-bottom: 1px solid #4a5568;            }            QListWidget::item:selected {                background-color: #4a5568;                color: #ffffff;            }            QTextEdit {                background-color: #2d3748;                border: 2px solid #4a5568;                border-radius: 4px;                padding: 12px;                font-family: 'Consolas', 'Monaco', monospace;                font-size: 12px;            }            QLabel {                padding: 5px;                color: #cbd5e0;            }            QProgressBar {                border: 2px solid #4a5568;                border-radius: 4px;                text-align: center;                background-color: #2d3748;                color: #e0e0e0;                height: 20px;            }            QProgressBar::chunk {                background-color: #4299e1;                border-radius: 2px;            }            QFrame {                background-color: #2d3748;                border-radius: 4px;                border: 2px solid #4a5568;            }            QSplitter::handle {                background-color: #4a5568;                width: 4px;            }        """)defcreate_widgets(self):"""创建界面控件"""        central_widget = QWidget()        self.setCentralWidget(central_widget)        layout = QVBoxLayout(central_widget)# 标题        title = QLabel("网页代码压缩工具")        title.setAlignment(Qt.AlignCenter)        title_font = QFont('Segoe UI'24, QFont.Bold)        title.setFont(title_font)        title.setStyleSheet("color: #4299e1; padding: 20px; border-bottom: 2px solid #4a5568;")        layout.addWidget(title)# 创建分割器        splitter = QSplitter(Qt.Horizontal)# 左侧面板        left_frame = QFrame()        left_frame.setMaximumWidth(350)        left_layout = QVBoxLayout(left_frame)# 文件列表区域        file_label = QLabel("已选文件:")        file_label.setFont(QFont('Segoe UI'12, QFont.Bold))        left_layout.addWidget(file_label)        self.file_list = QListWidget()        self.file_list.setMinimumHeight(200)        self.file_list.setStyleSheet("font-size: 20px; padding: 5px;")        left_layout.addWidget(self.file_list)# 按钮区域        button_layout = QHBoxLayout()        self.add_button = QPushButton("📁 添加文件")        self.add_button.clicked.connect(self.add_files)        self.add_button.setStyleSheet("""            QPushButton {                background-color: #4299e1;                border-color: #3182ce;                font-size: 20px;                padding: 12px;            }            QPushButton:hover {                background-color: #3182ce;                border-color: #2c5282;            }        """)        button_layout.addWidget(self.add_button)        self.remove_button = QPushButton("🗑️ 移除文件")        self.remove_button.clicked.connect(self.remove_file)        self.remove_button.setStyleSheet("""            QPushButton {                background-color: #4299e1;                border-color: #3182ce;                font-size: 20px;                padding: 12px;            }            QPushButton:hover {                background-color: #3182ce;                border-color: #2c5282;            }        """)        button_layout.addWidget(self.remove_button)        left_layout.addLayout(button_layout)# 输出路径选择        output_layout = QVBoxLayout()        output_label = QLabel("输出路径:")        output_label.setFont(QFont('Segoe UI'12, QFont.Bold))        output_layout.addWidget(output_label)        self.output_path_button = QPushButton("📂 选择输出目录")        self.output_path_button.clicked.connect(self.select_output_directory)        self.output_path_button.setStyleSheet("""            QPushButton {                background-color: #4299e1;                border-color: #3182ce;                font-size: 24px;                padding: 12px;            }            QPushButton:hover {                background-color: #3182ce;                border-color: #2c5282;            }        """)        output_layout.addWidget(self.output_path_button)        self.output_path_label = QLabel("未选择目录")        self.output_path_label.setStyleSheet("""            color: #a0aec0            font-size: 20px;             padding: 5px;             background-color: #1a202c            border-radius: 3px;        """)        self.output_path_label.setWordWrap(True)        output_layout.addWidget(self.output_path_label)        left_layout.addLayout(output_layout)# 压缩按钮        self.process_button = QPushButton("⚡ 压缩文件")        self.process_button.clicked.connect(self.process_files)        self.process_button.setStyleSheet("""            QPushButton {                background-color: #4299e1;                border-color: #3182ce;                font-size: 24px;                padding: 12px;            }            QPushButton:hover {                background-color: #3182ce;                border-color: #2c5282;            }        """)        left_layout.addWidget(self.process_button)# 进度条        self.progress_bar = QProgressBar()        self.progress_bar.setVisible(False)        left_layout.addWidget(self.progress_bar)        left_layout.addStretch()# 右侧面板 - 预览        right_frame = QFrame()        right_layout = QVBoxLayout(right_frame)        preview_label = QLabel("文件预览:")        preview_label.setFont(QFont('Segoe UI'12, QFont.Bold))        right_layout.addWidget(preview_label)        self.preview_edit = QTextEdit()        self.preview_edit.setPlaceholderText("选择文件以预览...")        self.preview_edit.setStyleSheet("font-size: 20px; padding: 5px;")        self.preview_edit.setMinimumHeight(400)        right_layout.addWidget(self.preview_edit)# 状态标签        self.preview_status = QLabel("")        self.preview_status.setStyleSheet("color: #a0aec0; font-size: 20px; padding: 5px;")        right_layout.addWidget(self.preview_status)# 添加到分割器        splitter.addWidget(left_frame)        splitter.addWidget(right_frame)        splitter.setSizes([350650])        layout.addWidget(splitter)# 状态栏        self.statusBar().setStyleSheet("background-color: #1a202c; color: #a0aec0;")        self.statusBar().showMessage("就绪")defsetup_connections(self):"""设置信号连接"""        self.file_list.currentItemChanged.connect(self.preview_file)defadd_files(self):"""添加文件到列表"""        file_dialog = QFileDialog()        file_paths, _ = file_dialog.getOpenFileNames(            self"选择文件""","网页文件 (*.html *.htm *.css *.js *.json);;所有文件 (*.*)"        )        new_files_count = 0for file_path in file_paths:if file_path notin self.files:                self.files.append(file_path)                item = QListWidgetItem(f"📄 {os.path.basename(file_path)}")                item.setData(Qt.UserRole, file_path)                item.setToolTip(file_path)                self.file_list.addItem(item)                new_files_count += 1if new_files_count > 0:            self.statusBar().showMessage(f"已添加 {new_files_count} 个文件")else:            self.statusBar().showMessage("没有添加新文件")defremove_file(self):"""从列表中移除文件"""        current_row = self.file_list.currentRow()if current_row >= 0:            item = self.file_list.takeItem(current_row)            file_path = item.data(Qt.UserRole)if file_path in self.files:                self.files.remove(file_path)            self.statusBar().showMessage("已移除文件")            self.preview_edit.clear()            self.preview_status.setText("")else:            QMessageBox.warning(self"警告""请先选择一个文件")defselect_output_directory(self):"""选择输出目录"""        directory = QFileDialog.getExistingDirectory(self"选择输出目录")if directory:            self.output_directory = directory            display_path = directoryiflen(directory) > 50:                display_path = "..." + directory[-47:]            self.output_path_label.setText(display_path)            self.output_path_label.setToolTip(directory)            self.statusBar().showMessage(f"输出目录: {directory}")defpreview_file(self, current, previous):"""预览选中的文件"""if current:            file_path = current.data(Qt.UserRole)try:withopen(file_path, 'r', encoding='utf-8'as file:                    content = file.read()                    self.preview_edit.setPlainText(content)                file_size = os.path.getsize(file_path)                file_ext = os.path.splitext(file_path)[1].lower()                self.preview_status.setText(f"文件: {os.path.basename(file_path)} | 大小: {self.format_file_size(file_size)} | 类型: {file_ext}")except Exception as e:                self.preview_edit.setPlainText(f"无法读取文件: {str(e)}")                self.preview_status.setText(f"错误: {str(e)}")defformat_file_size(self, size):"""格式化文件大小显示"""for unit in ['B''KB''MB''GB']:if size < 1024.0:returnf"{size:.1f}{unit}"            size /= 1024.0returnf"{size:.1f} TB"defprocess_files(self):"""处理所有选中的文件"""if self.output_directory isNone:            QMessageBox.warning(self"警告""请先选择输出目录")returnifnot self.files:            QMessageBox.warning(self"警告""请先添加文件")return        self.progress_bar.setVisible(True)        self.progress_bar.setMaximum(len(self.files))        self.progress_bar.setValue(0)        success_count = 0        error_files = []for i, file_path inenumerate(self.files):try:withopen(file_path, 'r', encoding='utf-8'as file:                    content = file.read()                file_ext = os.path.splitext(file_path)[1].lower()                processed_content = self.compress_content(content, file_ext)                file_name = os.path.basename(file_path)                output_path = os.path.join(self.output_directory, file_name)withopen(output_path, 'w', encoding='utf-8'as file:                    file.write(processed_content)                success_count += 1except Exception as e:                error_files.append(os.path.basename(file_path))            self.progress_bar.setValue(i + 1)        self.progress_bar.setVisible(False)        message = f"成功处理 {success_count}/{len(self.files)} 个文件"if error_files:            message += f"\n失败文件: {', '.join(error_files[:5])}"iflen(error_files) > 5:                message += f" 等{len(error_files)}个文件"        QMessageBox.information(self"处理完成", message)        self.statusBar().showMessage(f"完成: {success_count}/{len(self.files)} 个文件")defcompress_content(self, content, file_ext):"""压缩文件内容"""# 移除注释        content = self.remove_comments(content, file_ext)# 移除缩进和空白        content = self.remove_indentation(content, file_ext)# 根据文件类型进行特定压缩if file_ext == '.js':return self.compress_js(content)elif file_ext == '.css':return self.compress_css(content)elif file_ext in ['.html''.htm']:# 检测是否包含内联CSS或JSif self.has_inline_css_js(content):return self.compress_htmlcssjs(content)else:return self.compress_html(content)elif file_ext == '.json':return self.compress_json(content)else:return self.basic_compress(content)defhas_inline_css_js(self, html_content):"""检测HTML是否包含内联CSS或JS"""# 检测<style>标签        style_pattern = re.compile(r'<style[^>]*>[\s\S]*?</style>', re.IGNORECASE)        has_style = Falsefor match in style_pattern.finditer(html_content):            style_content = match.group(0)# 提取<style>标签内容            tag_match = re.match(r'<style[^>]*>([\s\S]*?)</style>', style_content, re.IGNORECASE)if tag_match and tag_match.group(1).strip():                has_style = Truebreak# 检测<script>标签        script_pattern = re.compile(r'<script[^>]*>[\s\S]*?</script>', re.IGNORECASE)        has_script_content = Falsefor match in script_pattern.finditer(html_content):            script_tag = match.group(0)# 检查是否有src属性if re.search(r'src\s*=', script_tag, re.IGNORECASE):# 如果有src属性,检查标签内是否还有内容                tag_match = re.match(r'<script[^>]*>([\s\S]*?)</script>', script_tag, re.IGNORECASE)if tag_match and tag_match.group(1).strip():# 既有src属性又有内容                    has_script_content = Truebreakelse:# 若没有src属性,检查标签内是否有内容                tag_match = re.match(r'<script[^>]*>([\s\S]*?)</script>', script_tag, re.IGNORECASE)if tag_match and tag_match.group(1).strip():                    has_script_content = Truebreak# 检测内联事件处理        has_inline_events = re.search(r'on\w+\s*=\s*["\'][^"\']*["\']', html_content, re.IGNORECASE) isnotNone# 检测内联样式        has_inline_style = re.search(r'style\s*=\s*["\'][^"\']*["\']', html_content, re.IGNORECASE) isnotNone# 调试信息:在控制台输出检测结果        print(f"HTML内联代码检测结果:")        print(f"包含内联CSS(<style>标签): {has_style}")        print(f"包含内联JS(<script>标签内容): {has_script_content}")        print(f"包含内联事件(如onclick): {has_inline_events}")        print(f"包含内联样式(style属性): {has_inline_style}")        print(f"使用特殊压缩(有内联CSS或内联JS): {has_style or has_script_content}")        print(f"使用普通HTML压缩: {not (has_style or has_script_content)}")return has_style or has_script_contentdefremove_comments(self, content, file_ext):"""根据文件类型移除注释"""if file_ext == '.js':# 移除多行注释 /* ... */            content = re.sub(r'/\*[\s\S]*?\*/''', content)# 移除单行注释 //            content = re.sub(r'//.*''', content)elif file_ext == '.css':# 移除CSS注释 /* ... */            content = re.sub(r'/\*[\s\S]*?\*/''', content)elif file_ext in ['.html''.htm']:# 移除HTML注释 <!-- ... -->            content = re.sub(r'<!--[\s\S]*?-->''', content)elif file_ext == '.json':# JSON不支持注释,直接返回passreturn contentdefremove_indentation(self, content, file_ext):"""去除缩进和多余空白"""        lines = content.split('\n')        processed_lines = []for line in lines:            line = line.strip()            line = re.sub(r'\s+'' ', line)if line:                processed_lines.append(line)if file_ext == '.json':# JSON保持单行格式return' '.join(processed_lines)elif file_ext in ['.html''.htm']:# HTML标签紧贴            joined = ' '.join(processed_lines)return re.sub(r'>\s+<''><', joined)else:# 其他文件用空格连接return' '.join(processed_lines)defbasic_compress(self, content):"""基本压缩"""        content = re.sub(r'\s+'' ', content)return content.strip()defcompress_js(self, content):"""压缩JavaScript代码"""        content = re.sub(r'\s*([=+\-*/%&|^<>!?:;,{}()])\s*'r'\1', content)        content = re.sub(r';(\w)'r'; \1', content)        content = re.sub(r'(\w+)\s*\('r'\1(', content)        content = re.sub(r'\.\s+''.', content)return content.strip()defcompress_css(self, content):"""压缩CSS代码"""        content = re.sub(r'\s*([{}:;,])\s*'r'\1', content)        content = re.sub(r';}''}', content)        content = re.sub(r':(\w)'r': \1', content)return content.strip()defcompress_html(self, content):"""压缩HTML代码"""        content = re.sub(r'>\s+<''><', content)        content = re.sub(r'<(\w+)([^>]*?)\s*>'r'<\1\2>', content)        content = re.sub(r'\s+=\s+''=', content)return content.strip()defcompress_json(self, content):"""压缩JSON代码"""try:            data = json.loads(content)return json.dumps(data, separators=(','':'))except:return self.basic_compress(content)defcompress_htmlcssjs(self, content):"""压缩内联CSS和JS的HTML文件"""        original_len = len(content)# 除HTML注释        content = re.sub(r'<!--[\s\S]*?-->''', content)# 按行处理,保持基本结构        lines = content.split('\n')        processed_lines = []for line in lines:            line = line.strip()ifnot line:continue            line = re.sub(r'\s+'' ', line)            processed_lines.append(line)        content = ' '.join(processed_lines)# 处理<style>标签中的CSS        style_pattern = re.compile(r'(<style[^>]*>)(.*?)(</style>)', re.IGNORECASE | re.DOTALL)defprocess_style(match):            tag_start, css_content, tag_end = match.groups()# 移除CSS注释            css_content = re.sub(r'/\*[\s\S]*?\*/''', css_content)# 安全压缩CSS            lines = []for css_line in css_content.split(';'):                css_line = css_line.strip()if css_line:                    css_line = re.sub(r'\s*{\s*''{', css_line)                    css_line = re.sub(r'\s*}\s*''}', css_line)                    css_line = re.sub(r'\s*:\s*'':', css_line)                    css_line = re.sub(r'\s*,\s*'',', css_line)                    css_line = re.sub(r'\s+'' ', css_line)                    lines.append(css_line)            compressed_css = ';'.join(lines)# 确保每个规则正确结束            compressed_css = re.sub(r'([^;}])$'r'\1;', compressed_css)returnf'{tag_start}{compressed_css}{tag_end}'        content = style_pattern.sub(process_style, content)# 找到所有<script>标签的位置        script_tags = []        script_positions = []# 查找所有的<script>开始标签        pattern = re.compile(r'<script[^>]*>', re.IGNORECASE)for match in pattern.finditer(content):            script_tags.append(match.group())            script_positions.append(match.start())# 迭代方式处理脚本标签if script_positions:for i inrange(len(script_positions) - 1, -1, -1):                start_pos = script_positions[i]                tag_end_pos = content.find('>', start_pos)if tag_end_pos == -1:continue                content_start = tag_end_pos + 1                end_script_pos = content.find('</script>', content_start)if end_script_pos == -1:continue# 提取<script>开始标签和内容                script_start_tag = content[start_pos:tag_end_pos + 1]                script_content = content[content_start:end_script_pos]# 处理JS内容(区分外部脚本和内联脚本)if'src='in script_start_tag.lower():# 外部脚本,保持内容不变                    processed_content = script_contentelse:# 内联脚本,进行压缩                    processed_content = self.compress_javascript_content(script_content)# 重新构建整个<script>标签                new_script_tag = f"{script_start_tag}{processed_content}</script>"# 替换原内容中的<script>标签部分                content = content[:start_pos] + new_script_tag + content[end_script_pos + 9:]  # 9是len('</script>')# 处理HTML标签结构defprocess_html_structure(html):"""处理HTML结构,确保标签正确"""# 处理自闭合标签            self_closing_tags = ['meta''link''img''br''hr''input']for tag in self_closing_tags:                pattern = re.compile(f'<{tag}([^>]*?)\\s*>', re.IGNORECASE)                html = pattern.sub(f'<{tag}\\1>', html)# 处理普通标签            html = re.sub(r'<(\w+)\s*>'r'<\1>', html)# 确保标签名和属性间有空格deffix_tag_spacing(match):                full_match = match.group(0)if re.search(r'<\w+[a-zA-Z0-9]', full_match):                    tag_end_match = re.search(r'<\w+', full_match)if tag_end_match:                        tag_name_end = tag_end_match.end()                        fixed = full_match[:tag_name_end] + ' ' + full_match[tag_name_end:]return fixedreturn full_match            tag_pattern = re.compile(r'<\w+[^>]*>')            html = tag_pattern.sub(fix_tag_spacing, html)# 压缩标签内的空白defcompress_tag_internals(match):                tag_content = match.group(0)                tag_content = re.sub(r'\s+=\s+''=', tag_content)                tag_content = re.sub(r'\s+'' ', tag_content)return tag_content            html = tag_pattern.sub(compress_tag_internals, html)# 移除标签间的空白            html = re.sub(r'>\s+<''><', html)return html        content = process_html_structure(content)# 修复CSS错误        content = re.sub(r'};}'r'}}', content)        content = re.sub(r'};'r'}', content)        content = re.sub(r'(\w+):(\w+)'r'\1:\2', content)# 处理内联事件处理器defprocess_inline_events(match):            attr_name = match.group(1)            quote_char = match.group(2)            js_code = match.group(3)            js_code = re.sub(r'\s+'' ', js_code.strip())returnf'{attr_name}={quote_char}{js_code}{quote_char}'        inline_event_pattern = re.compile(r'(on\w+)=(["\'])(.*?)\2', re.IGNORECASE | re.DOTALL)        content = inline_event_pattern.sub(process_inline_events, content)# 处理内联样式defprocess_inline_styles(match):            attr_name = match.group(1)            quote_char = match.group(2)            css_code = match.group(3)            css_code = re.sub(r'\s*:\s*'':', css_code)            css_code = re.sub(r'\s*;\s*'';', css_code)            css_code = re.sub(r'\s+'' ', css_code.strip())returnf'{attr_name}={quote_char}{css_code}{quote_char}'        inline_style_pattern = re.compile(r'(style)=(["\'])(.*?)\2', re.IGNORECASE | re.DOTALL)        content = inline_style_pattern.sub(process_inline_styles, content)# 确保DOCTYPE正确if'<!DOCTYPE'in content and'html>'in content:            doctype_end = content.find('html>') + 5            doctype_part = content[:doctype_end]            rest = content[doctype_end:]# 确保DOCTYPE后没有紧贴其他标签if rest and rest[0] != ' ':                content = doctype_part + ' ' + rest# 修复可能的多余空格        content = re.sub(r'\s+'' ', content).strip()# 检查是否有空的<script></script>标签        empty_scripts = re.findall(r'<script[^>]*>\s*</script>', content, re.IGNORECASE)if empty_scripts:            print(f"警告:发现 {len(empty_scripts)} 个空的<script>标签")        print(f"压缩完成:")        print(f"  原始长度: {original_len} 字符")        print(f"  压缩后长度: {len(content)} 字符")if original_len > 0:            compression_rate = (1 - len(content) / original_len) * 100            print(f"  压缩率: {compression_rate:.1f}%")return contentdefcompress_javascript_content(self, js_content):"""压缩HTML文件内联JavaScript内容"""# 如果内容为空或只有空白,返回原样ifnot js_content or js_content.strip() == '':return js_content        original_js = js_content# 移除多行注释 /* ... */        js_content = re.sub(r'/\*[\s\S]*?\*/''', js_content)# 移除单行注释 //        lines = js_content.split('\n')        processed_lines = []for line in lines:# 处理单行注释            in_string = False            string_char = None            escaped = False            result_chars = []            i = 0while i < len(line):                char = line[i]# 处理转义字符if escaped:                    result_chars.append(char)                    escaped = False                    i += 1continue# 处理字符串if in_string:if char == '\\':                        escaped = Trueelif char == string_char:                        in_string = False                    result_chars.append(char)                    i += 1continue# 检查字符串开始if char in ['"'"'"]:                    in_string = True                    string_char = char                    result_chars.append(char)                    i += 1continue# 检查单行注释if char == '/'and i + 1 < len(line) and line[i + 1] == '/':# 找到注释开始,跳过行剩余部分break# 正常字符                result_chars.append(char)                i += 1            processed_line = ''.join(result_chars).strip()if processed_line:                processed_lines.append(processed_line)        js_content = '\n'.join(processed_lines)# 如果处理后内容为空,返回原始内容ifnot js_content.strip():            print("警告:JS内容处理后为空,返回原始内容")return original_js# 将多行压缩为一行,但保留基本结构        js_content = ' '.join(line.strip() for line in js_content.split('\n'if line.strip())# 压缩运算符周围的空格        js_content = re.sub(r'\s*([=!<>+\-*/%&|^])\s*=\s*'r'\1=', js_content)        js_content = re.sub(r'=\s*=\s*='r'===', js_content)        js_content = re.sub(r'!\s*=\s*='r'!==', js_content)# 压缩函数调用        js_content = re.sub(r'(\w)\s*\(\s*'r'\1(', js_content)        js_content = re.sub(r'\s*\)\s*'r')', js_content)# 压缩大括号和分号        js_content = re.sub(r'\s*{\s*'r'{', js_content)        js_content = re.sub(r'\s*}\s*'r'}', js_content)        js_content = re.sub(r'\s*;\s*'r';', js_content)        js_content = re.sub(r'\s*,\s*'r',', js_content)        js_content = re.sub(r'\s*:\s*'r':', js_content)# 压缩点号周围的空格        js_content = re.sub(r'\s*\.\s*'r'.', js_content)# 压缩多余空格,但保留基本的空格        js_content = re.sub(r'\s+'' ', js_content).strip()# 确保不以分号结尾        js_content = re.sub(r';\s*$'';', js_content)return js_contentif __name__ == '__main__':    app = QApplication(sys.argv)    app.setStyle('Fusion')    window = WebCodeCompressorApp()    window.show()    sys.exit(app.exec_())

源代码:基于PyQt5开发、利用pyinstaller打包

排版|秀米、玉箫制作

代码|玉箫制作

文字|玉箫制作

图片|玉箫制作

代码均为原创,仅供参考

部分图像素材源于网络

如有侵权请联系删除!

最新文章

随机文章

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