Files
ai_wht_wechat/backend/error_screenshot.py
2026-01-06 19:36:42 +08:00

147 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
错误截图保存工具
当发生错误时自动截图并保存,便于问题排查
"""
import os
import sys
from datetime import datetime
from pathlib import Path
from typing import Optional
from playwright.async_api import Page
# 截图保存目录
SCREENSHOT_DIR = Path("error_screenshots")
SCREENSHOT_DIR.mkdir(exist_ok=True)
async def save_error_screenshot(
page: Optional[Page],
error_type: str,
error_message: str = "",
prefix: str = ""
) -> Optional[str]:
"""
保存错误截图
Args:
page: Playwright 页面对象
error_type: 错误类型login_failed, send_code_failed, publish_failed等
error_message: 错误信息(可选,会添加到日志)
prefix: 文件名前缀(可选)
Returns:
截图文件路径失败返回None
"""
if not page:
print("[错误截图] 页面对象为空,无法截图", file=sys.stderr)
return None
try:
# 生成文件名年月日时分秒_错误类型.png
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# 清理错误类型字符串(移除特殊字符)
safe_error_type = "".join(c for c in error_type if c.isalnum() or c in ('_', '-'))
# 组合文件名
if prefix:
filename = f"{prefix}_{timestamp}_{safe_error_type}.png"
else:
filename = f"{timestamp}_{safe_error_type}.png"
filepath = SCREENSHOT_DIR / filename
# 截图
await page.screenshot(path=str(filepath), full_page=True)
# 打印日志
print(f"[错误截图] 已保存: {filepath}", file=sys.stderr)
if error_message:
print(f"[错误截图] 错误信息: {error_message}", file=sys.stderr)
# 返回文件路径
return str(filepath)
except Exception as e:
print(f"[错误截图] 截图失败: {str(e)}", file=sys.stderr)
return None
def cleanup_old_screenshots(days: int = 7):
"""
清理旧的错误截图
Args:
days: 保留最近几天的截图默认7天
"""
try:
import time
current_time = time.time()
cutoff_time = current_time - (days * 24 * 60 * 60)
deleted_count = 0
for file in SCREENSHOT_DIR.glob("*.png"):
if file.stat().st_mtime < cutoff_time:
file.unlink()
deleted_count += 1
if deleted_count > 0:
print(f"[错误截图] 已清理 {deleted_count} 个超过 {days} 天的旧截图", file=sys.stderr)
except Exception as e:
print(f"[错误截图] 清理旧截图失败: {str(e)}", file=sys.stderr)
async def save_screenshot_with_html(
page: Optional[Page],
error_type: str,
error_message: str = "",
prefix: str = ""
) -> tuple[Optional[str], Optional[str]]:
"""
保存错误截图和HTML源码用于深度调试
Args:
page: Playwright 页面对象
error_type: 错误类型
error_message: 错误信息(可选)
prefix: 文件名前缀(可选)
Returns:
(截图路径, HTML路径),失败返回(None, None)
"""
if not page:
return None, None
try:
# 生成文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
safe_error_type = "".join(c for c in error_type if c.isalnum() or c in ('_', '-'))
if prefix:
base_filename = f"{prefix}_{timestamp}_{safe_error_type}"
else:
base_filename = f"{timestamp}_{safe_error_type}"
# 保存截图
screenshot_path = SCREENSHOT_DIR / f"{base_filename}.png"
await page.screenshot(path=str(screenshot_path), full_page=True)
# 保存HTML
html_path = SCREENSHOT_DIR / f"{base_filename}.html"
html_content = await page.content()
with open(html_path, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"[错误截图] 已保存截图: {screenshot_path}", file=sys.stderr)
print(f"[错误截图] 已保存HTML: {html_path}", file=sys.stderr)
if error_message:
print(f"[错误截图] 错误信息: {error_message}", file=sys.stderr)
return str(screenshot_path), str(html_path)
except Exception as e:
print(f"[错误截图] 保存截图和HTML失败: {str(e)}", file=sys.stderr)
return None, None