package com.example.datacollect.command; import com.example.datacollect.model.Article; import com.example.datacollect.repository.ArticleRepository; import com.example.datacollect.strategy.CrawlStrategy; import com.example.datacollect.strategy.StrategyFactory; import com.example.datacollect.view.ConsoleView; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.stream.Collectors; public class AnalyzeCommand implements Command { // 1. 添加 Logger 成员 private static final Logger logger = LoggerFactory.getLogger(AnalyzeCommand.class); private final ConsoleView view; private final StrategyFactory strategyFactory; public AnalyzeCommand(ConsoleView view, StrategyFactory strategyFactory) { this.view = view; this.strategyFactory = strategyFactory; } @Override public String getName() { return "analyze"; } @Override public void execute(String[] args, ArticleRepository repository) { if (args.length < 2) { logger.error("指令参数错误,正确用法: analyze "); view.printError("Usage: analyze "); // 保留控制台提示,方便用户直接看到 return; } String url = args[1]; CrawlStrategy strategy = strategyFactory.getStrategy(url); if (strategy == null) { logger.error("未找到适用于 URL [{}] 的抓取策略", url); view.printError("No strategy found for: " + url); return; } try { logger.info("开始分析目标网站: {}", url); Document doc = Jsoup.connect(url).get(); // 调用策略解析,但不存入 Repository List
articles = strategy.parse(url, doc); // 统计信息 int total = articles.size(); double avgTitleLen = articles.stream() .mapToInt(a -> a.getTitle().length()) .average() .orElse(0.0); // Top 5 按标题长度排序 List
top5 = articles.stream() .sorted((a, b) -> Integer.compare(b.getTitle().length(), a.getTitle().length())) .limit(5) .collect(Collectors.toList()); // 输出结果到日志 logger.info("=== 分析结果 ==="); logger.info("提取文章总数: {}", total); logger.info("平均标题长度: {:.2f} 字符", avgTitleLen); logger.info("Top 5 文章 (按标题长度排序):"); int rank = 1; for (Article a : top5) { logger.info("{}. {} ({} 字符)", rank, a.getTitle(), a.getTitle().length()); rank++; } logger.info("=================="); // 保留原有的控制台输出,确保用户交互体验不受影响 view.printInfo("=== Analysis Result ==="); view.printInfo("Total Articles: " + total); view.printInfo("Avg Title Length: " + String.format("%.2f", avgTitleLen)); view.printInfo("Top 5 Articles (by Title Length):"); rank = 1; for (Article a : top5) { view.printInfo(rank + ". " + a.getTitle() + " (" + a.getTitle().length() + " chars)"); rank++; } view.printInfo("========================"); } catch (Exception e) { logger.error("分析 URL [{}] 时发生异常: ", url, e); // 传入异常对象 e,以便记录完整堆栈 view.printError("Failed to analyze: " + e.getMessage()); } } }