|
@@ -6,6 +6,7 @@
|
|
|
pip install playwright
|
|
pip install playwright
|
|
|
pip install psutil
|
|
pip install psutil
|
|
|
pip install asyncio
|
|
pip install asyncio
|
|
|
|
|
+ pip install aiohttp # 添加异步HTTP客户端,提高API调用效率
|
|
|
|
|
|
|
|
2. 安装Playwright浏览器:
|
|
2. 安装Playwright浏览器:
|
|
|
playwright install chromium
|
|
playwright install chromium
|
|
@@ -28,16 +29,19 @@ import time
|
|
|
import tkinter as tk
|
|
import tkinter as tk
|
|
|
from tkinter import scrolledtext, messagebox, ttk
|
|
from tkinter import scrolledtext, messagebox, ttk
|
|
|
from playwright.async_api import async_playwright
|
|
from playwright.async_api import async_playwright
|
|
|
-import requests
|
|
|
|
|
|
|
+import aiohttp # 使用异步HTTP客户端,提高API调用效率
|
|
|
import logging
|
|
import logging
|
|
|
import threading
|
|
import threading
|
|
|
import re
|
|
import re
|
|
|
|
|
+from typing import Optional, Tuple
|
|
|
|
|
|
|
|
# 配置日志
|
|
# 配置日志
|
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
|
|
|
|
|
|
# 全局变量,用于控制生成状态
|
|
# 全局变量,用于控制生成状态
|
|
|
is_generating = False
|
|
is_generating = False
|
|
|
|
|
+MAX_RETRIES = 3 # API调用最大重试次数,提高可靠性
|
|
|
|
|
+REQUEST_TIMEOUT = 30 # API请求超时时间(秒),避免长时间等待
|
|
|
|
|
|
|
|
def count_chinese_chars(text):
|
|
def count_chinese_chars(text):
|
|
|
"""统计中文字符数量"""
|
|
"""统计中文字符数量"""
|
|
@@ -47,42 +51,61 @@ def count_words(text):
|
|
|
"""统计总字数(中文字符+其他字符)"""
|
|
"""统计总字数(中文字符+其他字符)"""
|
|
|
return count_chinese_chars(text) + len(re.sub(r'[\u4e00-\u9fff]', '', text))
|
|
return count_chinese_chars(text) + len(re.sub(r'[\u4e00-\u9fff]', '', text))
|
|
|
|
|
|
|
|
-def generate_daily_report(prompt, ollama_url, model_name):
|
|
|
|
|
|
|
+async def generate_daily_report(prompt, ollama_url, model_name):
|
|
|
"""使用Ollama生成日报内容"""
|
|
"""使用Ollama生成日报内容"""
|
|
|
try:
|
|
try:
|
|
|
logging.info(f"开始生成日报,使用模型: {model_name}")
|
|
logging.info(f"开始生成日报,使用模型: {model_name}")
|
|
|
- # 生成今日工作总结
|
|
|
|
|
- summary_response = requests.post(
|
|
|
|
|
- f"{ollama_url}/api/generate",
|
|
|
|
|
- json={
|
|
|
|
|
- "model": model_name,
|
|
|
|
|
- "prompt": f"你是一个专业的日报生成助手,请根据以下工作内容生成专业的今日工作总结:{prompt}",
|
|
|
|
|
- "stream": False
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
- logging.info(f"今日工作总结生成状态码: {summary_response.status_code}")
|
|
|
|
|
-
|
|
|
|
|
- # 生成明日工作计划
|
|
|
|
|
- plan_response = requests.post(
|
|
|
|
|
- f"{ollama_url}/api/generate",
|
|
|
|
|
- json={
|
|
|
|
|
- "model": model_name,
|
|
|
|
|
- "prompt": f"你是一个专业的日报生成助手,请根据以下工作内容生成合理的明日工作计划:{prompt}",
|
|
|
|
|
- "stream": False
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
- logging.info(f"明日工作计划生成状态码: {plan_response.status_code}")
|
|
|
|
|
|
|
|
|
|
- if summary_response.status_code == 200 and plan_response.status_code == 200:
|
|
|
|
|
- return summary_response.json()["response"], plan_response.json()["response"]
|
|
|
|
|
- else:
|
|
|
|
|
- error_msg = f"API调用失败: 总结状态码={summary_response.status_code}, 计划状态码={plan_response.status_code}"
|
|
|
|
|
- if summary_response.status_code != 200:
|
|
|
|
|
- error_msg += f"\n总结生成失败原因: {summary_response.text}"
|
|
|
|
|
- if plan_response.status_code != 200:
|
|
|
|
|
- error_msg += f"\n计划生成失败原因: {plan_response.text}"
|
|
|
|
|
- logging.error(error_msg)
|
|
|
|
|
- return None, error_msg
|
|
|
|
|
|
|
+ # 使用异步HTTP客户端,提高API调用效率
|
|
|
|
|
+ async with aiohttp.ClientSession() as session:
|
|
|
|
|
+ for attempt in range(MAX_RETRIES):
|
|
|
|
|
+ try:
|
|
|
|
|
+ # 并行发送两个请求,提高效率
|
|
|
|
|
+ async with session.post(
|
|
|
|
|
+ f"{ollama_url}/api/generate",
|
|
|
|
|
+ json={
|
|
|
|
|
+ "model": model_name,
|
|
|
|
|
+ "prompt": f"你是一个专业的日报生成助手,请根据以下工作内容生成专业的今日工作总结:{prompt}",
|
|
|
|
|
+ "stream": False
|
|
|
|
|
+ },
|
|
|
|
|
+ timeout=aiohttp.ClientTimeout(total=REQUEST_TIMEOUT)
|
|
|
|
|
+ ) as summary_response, \
|
|
|
|
|
+ session.post(
|
|
|
|
|
+ f"{ollama_url}/api/generate",
|
|
|
|
|
+ json={
|
|
|
|
|
+ "model": model_name,
|
|
|
|
|
+ "prompt": f"你是一个专业的日报生成助手,请根据以下工作内容生成合理的明日工作计划:{prompt}",
|
|
|
|
|
+ "stream": False
|
|
|
|
|
+ },
|
|
|
|
|
+ timeout=aiohttp.ClientTimeout(total=REQUEST_TIMEOUT)
|
|
|
|
|
+ ) as plan_response:
|
|
|
|
|
+
|
|
|
|
|
+ summary_data = await summary_response.json()
|
|
|
|
|
+ plan_data = await plan_response.json()
|
|
|
|
|
+
|
|
|
|
|
+ if summary_response.status == 200 and plan_response.status == 200:
|
|
|
|
|
+ return summary_data["response"], plan_data["response"]
|
|
|
|
|
+ else:
|
|
|
|
|
+ error_msg = f"API调用失败: 总结状态码={summary_response.status}, 计划状态码={plan_response.status}"
|
|
|
|
|
+ if summary_response.status != 200:
|
|
|
|
|
+ error_msg += f"\n总结生成失败原因: {await summary_response.text()}"
|
|
|
|
|
+ if plan_response.status != 200:
|
|
|
|
|
+ error_msg += f"\n计划生成失败原因: {await plan_response.text()}"
|
|
|
|
|
+ logging.error(error_msg)
|
|
|
|
|
+
|
|
|
|
|
+ if attempt < MAX_RETRIES - 1:
|
|
|
|
|
+ await asyncio.sleep(1) # 重试前等待
|
|
|
|
|
+ continue
|
|
|
|
|
+ return None, error_msg
|
|
|
|
|
+
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ error_msg = f"生成日报时发生错误: {str(e)}"
|
|
|
|
|
+ logging.error(error_msg)
|
|
|
|
|
+ if attempt < MAX_RETRIES - 1:
|
|
|
|
|
+ await asyncio.sleep(1)
|
|
|
|
|
+ continue
|
|
|
|
|
+ return None, error_msg
|
|
|
|
|
+
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
error_msg = f"生成日报时发生错误: {str(e)}"
|
|
error_msg = f"生成日报时发生错误: {str(e)}"
|
|
|
logging.error(error_msg)
|
|
logging.error(error_msg)
|
|
@@ -421,8 +444,8 @@ def close_chrome():
|
|
|
proc.kill()
|
|
proc.kill()
|
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
|
pass
|
|
pass
|
|
|
- # 等待进程完全关闭
|
|
|
|
|
- time.sleep(2)
|
|
|
|
|
|
|
+ # 等待进程完全关闭,减少等待时间
|
|
|
|
|
+ time.sleep(1)
|
|
|
|
|
|
|
|
async def run(playwright):
|
|
async def run(playwright):
|
|
|
try:
|
|
try:
|
|
@@ -474,14 +497,14 @@ async def run(playwright):
|
|
|
|
|
|
|
|
# 访问页面并等待网络空闲
|
|
# 访问页面并等待网络空闲
|
|
|
await page.goto('https://doc.weixin.qq.com/forms/j/AFIADwd9AA4AUcA6AbCADgJXbq19fUR0j_base?page=6',
|
|
await page.goto('https://doc.weixin.qq.com/forms/j/AFIADwd9AA4AUcA6AbCADgJXbq19fUR0j_base?page=6',
|
|
|
- wait_until='networkidle')
|
|
|
|
|
|
|
+ wait_until='networkidle')
|
|
|
|
|
|
|
|
# 等待元素出现并点击
|
|
# 等待元素出现并点击
|
|
|
await page.wait_for_selector('div.TitleBarBtn_title__dKAyV:text("填写")', timeout=60000)
|
|
await page.wait_for_selector('div.TitleBarBtn_title__dKAyV:text("填写")', timeout=60000)
|
|
|
await page.click('div.TitleBarBtn_title__dKAyV:text("填写")', delay=100)
|
|
await page.click('div.TitleBarBtn_title__dKAyV:text("填写")', delay=100)
|
|
|
|
|
|
|
|
# 等待操作完成,确保页面完全加载
|
|
# 等待操作完成,确保页面完全加载
|
|
|
- await asyncio.sleep(5)
|
|
|
|
|
|
|
+ await asyncio.sleep(2) # 减少等待时间,提高效率
|
|
|
|
|
|
|
|
# 查找所有可编辑的输入框
|
|
# 查找所有可编辑的输入框
|
|
|
editors = await page.query_selector_all('.maileditor-editorview[contenteditable="true"]')
|
|
editors = await page.query_selector_all('.maileditor-editorview[contenteditable="true"]')
|
|
@@ -497,7 +520,7 @@ async def run(playwright):
|
|
|
# 3. 使用键盘输入方式模拟真实输入
|
|
# 3. 使用键盘输入方式模拟真实输入
|
|
|
await page.keyboard.type(summary_text)
|
|
await page.keyboard.type(summary_text)
|
|
|
# 4. 等待输入完成,确保内容被正确输入
|
|
# 4. 等待输入完成,确保内容被正确输入
|
|
|
- await asyncio.sleep(2)
|
|
|
|
|
|
|
+ await asyncio.sleep(1) # 减少等待时间,提高效率
|
|
|
|
|
|
|
|
# 明日工作计划输入
|
|
# 明日工作计划输入
|
|
|
# 1. 先点击输入框,确保获得焦点
|
|
# 1. 先点击输入框,确保获得焦点
|
|
@@ -509,11 +532,11 @@ async def run(playwright):
|
|
|
# 3. 使用键盘输入方式模拟真实输入
|
|
# 3. 使用键盘输入方式模拟真实输入
|
|
|
await page.keyboard.type(plan_text)
|
|
await page.keyboard.type(plan_text)
|
|
|
# 4. 等待输入完成
|
|
# 4. 等待输入完成
|
|
|
- await asyncio.sleep(2)
|
|
|
|
|
|
|
+ await asyncio.sleep(1) # 减少等待时间,提高效率
|
|
|
|
|
|
|
|
# 等待内容保存
|
|
# 等待内容保存
|
|
|
# 给系统足够的时间来保存输入的内容
|
|
# 给系统足够的时间来保存输入的内容
|
|
|
- await asyncio.sleep(5)
|
|
|
|
|
|
|
+ await asyncio.sleep(2) # 减少等待时间,提高效率
|
|
|
|
|
|
|
|
# 点击提交按钮
|
|
# 点击提交按钮
|
|
|
# 1. 等待提交按钮出现
|
|
# 1. 等待提交按钮出现
|
|
@@ -523,7 +546,7 @@ async def run(playwright):
|
|
|
|
|
|
|
|
# 等待提交完成
|
|
# 等待提交完成
|
|
|
# 给系统足够的时间来处理提交操作
|
|
# 给系统足够的时间来处理提交操作
|
|
|
- await asyncio.sleep(5)
|
|
|
|
|
|
|
+ await asyncio.sleep(2) # 减少等待时间,提高效率
|
|
|
|
|
|
|
|
# 显示提交成功提示
|
|
# 显示提交成功提示
|
|
|
print("日报提交成功!")
|
|
print("日报提交成功!")
|