mirror of
https://github.com/Nezumi-2711/astrbot_plugin_qq_group_daily_analysis.git
synced 2026-09-22 20:01:04 +00:00
[fix] 更改错误的方法,增加浏览器开启选项
This commit is contained in:
@@ -177,6 +177,40 @@ class TopicAnalyzer(BaseAnalyzer):
|
||||
logger.error(f"创建话题对象失败: {e}")
|
||||
return []
|
||||
|
||||
def extract_text_messages(self, messages: List[Dict]) -> List[Dict]:
|
||||
"""
|
||||
从群聊消息中提取文本消息
|
||||
|
||||
Args:
|
||||
messages: 群聊消息列表
|
||||
|
||||
Returns:
|
||||
提取的文本消息列表
|
||||
"""
|
||||
text_messages = []
|
||||
for msg in messages:
|
||||
sender = msg.get("sender", {})
|
||||
nickname = sender.get("nickname", "") or sender.get("card", "")
|
||||
msg_time = datetime.fromtimestamp(msg.get("time", 0)).strftime("%H:%M")
|
||||
|
||||
for content in msg.get("message", []):
|
||||
if content.get("type") == "text":
|
||||
text = content.get("data", {}).get("text", "").strip()
|
||||
if text and len(text) > 2 and not text.startswith("/"):
|
||||
# 清理消息内容
|
||||
text = text.replace('""', '"').replace('""', '"')
|
||||
text = text.replace(''', "'").replace(''', "'")
|
||||
text = text.replace('\n', ' ').replace('\r', ' ')
|
||||
text = text.replace('\t', ' ')
|
||||
text = re.sub(r'[\x00-\x1f\x7f-\x9f]', '', text)
|
||||
text_messages.append({
|
||||
"sender": nickname,
|
||||
"time": msg_time,
|
||||
"content": text.strip()
|
||||
})
|
||||
|
||||
return text_messages
|
||||
|
||||
async def analyze_topics(self, messages: List[Dict], umo: str = None) -> Tuple[List[SummaryTopic], TokenUsage]:
|
||||
"""
|
||||
分析群聊话题
|
||||
|
||||
@@ -82,18 +82,6 @@ async def call_provider_with_retry(context, config_manager, prompt: str, max_tok
|
||||
return CustomResponse()
|
||||
else:
|
||||
# 确保使用当前指定的模型
|
||||
if provider is None:
|
||||
provider = context.get_using_provider(umo=umo)
|
||||
provider_id = 'unknown'
|
||||
if provider:
|
||||
try:
|
||||
meta = provider.meta()
|
||||
provider_id = meta.id
|
||||
except Exception as e:
|
||||
logger.debug(f"获取提供商ID失败: {e}")
|
||||
logger.info(f"获取到的 provider ID: {provider_id}")
|
||||
if not provider or provider_id == 'unknown':
|
||||
logger.warning(f"获取的提供商不正确 (Provider ID: {provider_id})")
|
||||
provider = context.get_using_provider(umo=umo)
|
||||
provider_id = 'unknown'
|
||||
if provider:
|
||||
|
||||
+100
-24
@@ -324,7 +324,11 @@ class ReportGenerator:
|
||||
'--enable-automation',
|
||||
'--password-store=basic',
|
||||
'--use-mock-keychain',
|
||||
'--export-tagged-pdf'
|
||||
'--export-tagged-pdf',
|
||||
'--disable-web-security',
|
||||
'--disable-features=VizDisplayCompositor',
|
||||
'--single-process', # 单进程模式,提高稳定性
|
||||
'--disable-blink-features=AutomationControlled' # 隐藏自动化特征
|
||||
]
|
||||
}
|
||||
|
||||
@@ -333,10 +337,12 @@ class ReportGenerator:
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
# Windows 系统 Chrome 安装路径
|
||||
username = os.environ.get('USERNAME', '')
|
||||
chrome_paths = [
|
||||
r"C:\Program Files\Google\Chrome\Application\chrome.exe",
|
||||
r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
|
||||
r"C:\Users\{}\AppData\Local\Google\Chrome\Application\chrome.exe".format(os.environ.get('USERNAME', '')),
|
||||
rf"C:\Users\{username}\AppData\Local\Google\Chrome\Application\chrome.exe",
|
||||
r"C:\Program Files\Chromium\Application\chrome.exe",
|
||||
]
|
||||
elif sys.platform.startswith('linux'):
|
||||
# Linux 系统 Chrome/Chromium 路径
|
||||
@@ -346,6 +352,7 @@ class ReportGenerator:
|
||||
'/usr/bin/chromium',
|
||||
'/usr/bin/chromium-browser',
|
||||
'/snap/bin/chromium',
|
||||
'/usr/bin/chromium-freeworld',
|
||||
]
|
||||
elif sys.platform.startswith('darwin'):
|
||||
# macOS 系统 Chrome 路径
|
||||
@@ -363,37 +370,80 @@ class ReportGenerator:
|
||||
|
||||
# 尝试启动浏览器,最多重试3次
|
||||
max_retries = 3
|
||||
browser = None
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
logger.info(f"尝试启动浏览器 (第 {attempt + 1} 次)")
|
||||
# 添加更多内存友好的启动选项
|
||||
launch_options.update({
|
||||
'dumpio': True, # 输出浏览器日志以便调试
|
||||
'autoClose': False, # 防止自动关闭
|
||||
'handleSIGINT': False,
|
||||
'handleSIGTERM': False,
|
||||
'handleSIGHUP': False
|
||||
})
|
||||
browser = await launch(**launch_options)
|
||||
logger.info("浏览器启动成功")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.warning(f"第 {attempt + 1} 次启动浏览器失败: {e}")
|
||||
if attempt < max_retries - 1:
|
||||
await asyncio.sleep(2) # 等待2秒后重试
|
||||
await asyncio.sleep(3) # 增加等待时间到3秒
|
||||
# 尝试减少内存占用的启动选项
|
||||
launch_options['args'].extend([
|
||||
'--disable-images',
|
||||
'--disable-javascript',
|
||||
'--disable-plugins',
|
||||
'--disable-webgl',
|
||||
'--disable-threaded-animation',
|
||||
'--disable-threaded-scrolling',
|
||||
'--disable-sync',
|
||||
'--disable-notifications',
|
||||
'--disable-default-apps',
|
||||
'--mute-audio',
|
||||
'--no-zygote',
|
||||
'--disable-gpu-sandbox',
|
||||
'--disable-software-rasterizer'
|
||||
])
|
||||
else:
|
||||
raise e
|
||||
logger.error(f"多次尝试后浏览器启动失败,无法生成 PDF, {e}")
|
||||
return False
|
||||
|
||||
if not browser:
|
||||
logger.error("浏览器启动失败,无法继续")
|
||||
return False
|
||||
|
||||
try:
|
||||
# 创建新页面,设置更合理的超时时间
|
||||
page = await browser.newPage()
|
||||
|
||||
# 设置页面内容 (pyppeteer 1.0.2 版本的 API)
|
||||
await page.setContent(html_content)
|
||||
|
||||
# 等待页面加载完成
|
||||
# 设置页面视口,减少内存占用
|
||||
await page.setViewport({
|
||||
'width': 1024,
|
||||
'height': 768,
|
||||
'deviceScaleFactor': 1,
|
||||
'isMobile': False,
|
||||
'hasTouch': False,
|
||||
'isLandscape': False
|
||||
})
|
||||
|
||||
# 设置页面内容,使用更安全的加载方式
|
||||
logger.info("开始设置页面内容...")
|
||||
await page.setContent(html_content, {'waitUntil': 'domcontentloaded', 'timeout': 30000})
|
||||
|
||||
# 等待页面基本加载完成,但不要太长时间
|
||||
try:
|
||||
await page.waitForSelector('body', {'timeout': 15000})
|
||||
await page.waitForSelector('body', {'timeout': 5000})
|
||||
logger.info("页面基本加载完成")
|
||||
except Exception:
|
||||
# 如果等待失败,继续执行(可能页面已经加载完成)
|
||||
logger.warning("等待页面加载超时,继续执行")
|
||||
pass
|
||||
|
||||
# 减少等待时间,避免内存累积
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# 等待额外时间确保页面完全渲染
|
||||
await asyncio.sleep(2)
|
||||
|
||||
# 导出 PDF
|
||||
await page.pdf({
|
||||
# 导出 PDF,使用更保守的设置
|
||||
logger.info("开始生成PDF...")
|
||||
pdf_options = {
|
||||
'path': output_path,
|
||||
'format': 'A4',
|
||||
'printBackground': True,
|
||||
@@ -405,18 +455,44 @@ class ReportGenerator:
|
||||
},
|
||||
'scale': 0.8,
|
||||
'displayHeaderFooter': False,
|
||||
'preferCSSPageSize': True
|
||||
})
|
||||
|
||||
'preferCSSPageSize': True,
|
||||
'timeout': 60000 # 增加PDF生成超时时间到60秒
|
||||
}
|
||||
|
||||
await page.pdf(pdf_options)
|
||||
logger.info(f"PDF 生成成功: {output_path}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"PDF生成过程中出错: {e}")
|
||||
return False
|
||||
|
||||
finally:
|
||||
# 确保浏览器被关闭
|
||||
try:
|
||||
await browser.close()
|
||||
except Exception as e:
|
||||
logger.warning(f"关闭浏览器时出错: {e}")
|
||||
# 确保浏览器被正确关闭
|
||||
if browser:
|
||||
try:
|
||||
logger.info("正在关闭浏览器...")
|
||||
# 先关闭所有页面
|
||||
pages = await browser.pages()
|
||||
for page in pages:
|
||||
try:
|
||||
await page.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
# 等待一小段时间让资源释放
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
# 关闭浏览器
|
||||
await browser.close()
|
||||
logger.info("浏览器已关闭")
|
||||
except Exception as e:
|
||||
logger.warning(f"关闭浏览器时出错: {e}")
|
||||
# 强制清理
|
||||
try:
|
||||
await browser.disconnect()
|
||||
except:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
|
||||
Reference in New Issue
Block a user