更新了web方式查看products的效果

This commit is contained in:
2025-11-30 12:36:48 +08:00
parent 1c91dd45ed
commit ff7e114324
18 changed files with 21092 additions and 31986 deletions

View File

@@ -322,27 +322,59 @@ class IntegratedProductSystem:
logger.error(f"调用Ollama AI API时出错: {e}")
return None
def parse_ai_response(self, response: str) -> Tuple[str, str, str]:
"""解析AI响应内容"""
def parse_ai_response(self, response: str) -> Tuple[str, str, str, int]:
"""解析AI响应内容,提取产品名称、简介、难度描述和难度分数"""
try:
# 使用/分割响应内容
parts = response.split('/')
product_name = ""
product_intro = ""
difficulty = ""
difficulty_score = None
if len(parts) >= 3:
product_name = parts[0].strip()
product_intro = parts[1].strip()
difficulty = parts[2].strip()
logger.info(f"解析结果: 名称='{product_name}', 简介='{product_intro[:30]}...', 难度='{difficulty}'")
return product_name, product_intro, difficulty
# 从难度描述中提取分数
import re
# 尝试匹配数字分数
score_match = re.search(r'\b(\d+)\b分|\b难度(\d+)\b|\b(\d+)\b', difficulty)
if score_match:
# 获取第一个匹配的数字
for group in score_match.groups():
if group:
difficulty_score = int(group)
break
# 如果没有提取到分数,根据关键词设置默认分数
if difficulty_score is None:
difficulty_lower = difficulty.lower()
if any(keyword in difficulty_lower for keyword in ['', '很难', '非常难', '复杂']):
difficulty_score = 85
elif any(keyword in difficulty_lower for keyword in ['', '一般', '适中', '普通']):
difficulty_score = 60
elif any(keyword in difficulty_lower for keyword in ['', '简单', '容易']):
difficulty_score = 35
else:
difficulty_score = 50 # 默认中等难度
logger.info(f"提取到难度分数: {difficulty_score}")
else:
logger.warning(f"响应格式不符合预期: {response}")
# 如果格式不符合,返回原始内容
return "", response, ""
difficulty = response
difficulty_score = 50 # 默认中等难度
return product_name, product_intro, difficulty, difficulty_score
except Exception as e:
logger.error(f"解析AI响应失败: {e}")
return "", response, ""
return "", response, "", 50
def check_product_exists_in_analysis(self, conn: sqlite3.Connection, original_name: str) -> bool:
"""检查产品是否已存在于分析结果表中"""
@@ -367,19 +399,23 @@ class IntegratedProductSystem:
def save_analysis_result(self, conn: sqlite3.Connection,
original_id: int, original_name: str,
product_name: str, difficulty: str, ai_response: str):
"""保存分析结果到数据库"""
product_name: str, difficulty: str, ai_response: str, difficulty_score: int = None):
"""保存分析结果到数据库,包括难度分数"""
try:
cursor = conn.cursor()
# 如果没有提供难度分数设置默认值50
if difficulty_score is None:
difficulty_score = 50
cursor.execute("""
INSERT INTO product_analysis
(original_id, original_name, product_name, development_difficulty, ai_response)
VALUES (?, ?, ?, ?, ?)
""", (original_id, original_name, product_name, difficulty, ai_response))
(original_id, original_name, product_name, development_difficulty, difficulty_score, ai_response)
VALUES (?, ?, ?, ?, ?, ?)
""", (original_id, original_name, product_name, difficulty, difficulty_score, ai_response))
conn.commit()
logger.success(f"保存分析结果成功: {product_name}")
logger.success(f"保存分析结果成功: {product_name}, 难度分数: {difficulty_score}")
except Exception as e:
logger.error(f"保存分析结果失败: {e}")
@@ -435,11 +471,11 @@ class IntegratedProductSystem:
logger.info(f"API调用成功正在处理数据...")
# 解析响应
product_name, product_intro, difficulty = self.parse_ai_response(ai_response)
product_name, product_intro, difficulty, difficulty_score = self.parse_ai_response(ai_response)
# 保存结果不再保存product_intro避免与ai_response重复
self.save_analysis_result(conn, original_id, name,
product_name, difficulty, ai_response)
product_name, difficulty, ai_response, difficulty_score)
success_count += 1
# 显示完成状态
@@ -549,8 +585,86 @@ class IntegratedProductSystem:
except Exception as e:
logger.error(f"显示抓取结果失败: {e}")
def analyze_missing_scores(self):
"""分析并补充缺失难度分数的产品"""
logger.info("=== 开始分析缺失难度分数的产品 ===")
conn = None
try:
# 连接数据库
conn = self.connect_to_database()
cursor = conn.cursor()
# 查询缺失难度分数的产品
cursor.execute("""
SELECT pa.id, p.name, p.introduction, pa.ai_response
FROM product_analysis pa
JOIN products p ON pa.original_id = p.id
WHERE pa.difficulty_score IS NULL OR pa.difficulty_score = ''
""")
products_with_missing_scores = cursor.fetchall()
logger.info(f"找到 {len(products_with_missing_scores)} 个缺失难度分数的产品")
if not products_with_missing_scores:
logger.info("没有发现缺失难度分数的产品")
return
# 为每个缺失分数的产品分析并更新分数
updated_count = 0
for i, (analysis_id, name, introduction, ai_response) in enumerate(products_with_missing_scores, 1):
logger.info(f"处理缺失分数的产品 {i}/{len(products_with_missing_scores)}: {name}")
# 如果已有AI响应从响应中重新提取分数
difficulty_score = None
if ai_response:
try:
_, _, _, difficulty_score = self.parse_ai_response(ai_response)
logger.info(f"从现有AI响应中提取分数: {difficulty_score}")
except Exception as e:
logger.error(f"从现有响应提取分数失败: {e}")
# 如果无法从现有响应提取重新调用API
if difficulty_score is None:
logger.info(f"重新调用API分析产品: {name}")
ai_response = self.call_ollama_ai_api(name, introduction)
if ai_response:
_, _, _, difficulty_score = self.parse_ai_response(ai_response)
# 更新AI响应
cursor.execute("""
UPDATE product_analysis
SET ai_response = ?
WHERE id = ?
""", (ai_response, analysis_id))
# 更新难度分数
if difficulty_score is not None:
cursor.execute("""
UPDATE product_analysis
SET difficulty_score = ?
WHERE id = ?
""", (difficulty_score, analysis_id))
conn.commit()
updated_count += 1
logger.success(f"成功更新产品 '{name}' 的难度分数为 {difficulty_score}")
else:
logger.warning(f"无法为产品 '{name}' 确定难度分数")
# 避免API调用过于频繁
if i < len(products_with_missing_scores):
time.sleep(2)
logger.success(f"缺失分数分析完成! 成功更新 {updated_count} 个产品的难度分数")
except Exception as e:
logger.error(f"分析缺失分数过程中出错: {e}")
finally:
if conn:
conn.close()
logger.info("数据库连接已关闭")
async def run_full_workflow_async(self, max_products=None, analyze_only=False):
"""异步运行完整工作流程:抓取+分析"""
"""异步运行完整工作流程:抓取+分析+补充缺失分数"""
logger.info("=== 开始全功能产品系统工作流程 ===")
# 初始化数据库
@@ -567,6 +681,10 @@ class IntegratedProductSystem:
logger.info("步骤2: 开始AI分析产品数据...")
self.analyze_products(max_products)
# 步骤3: 分析并补充缺失的难度分数
logger.info("步骤3: 开始分析并补充缺失的难度分数...")
self.analyze_missing_scores()
logger.success("=== 全功能产品系统工作流程完成 ===")
def run_full_workflow(self, max_products=None, analyze_only=False):