From aa4a2f90e80b3f081d3f55e4fc9bc3a8d50400c4 Mon Sep 17 00:00:00 2001 From: ZhangYuhan <2179360179@qq.com> Date: Sun, 31 May 2026 01:28:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=81=A5=E5=A3=AE=E6=80=A7=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- w11/AnalyzeCommand11.java | 39 +++++++++++++++++ w11/Article11.java | 27 ++++++++++++ w11/ArticleRepository11.java | 48 +++++++++++++++++++++ w11/Command11.java | 6 +++ w11/CommandRegistry11.java | 14 +++++++ w11/CrawlStrategy11.java | 4 ++ w11/CrawlerException11.java | 6 +++ w11/ExitCommand11.java | 18 ++++++++ w11/HelpCommand11.java | 21 ++++++++++ w11/HistoryCommand11.java | 31 ++++++++++++++ w11/Main11.java | 81 ++++++++++++++++++++++++++++++++++++ w11/NetworkException11.java | 6 +++ w11/ParseException11.java | 6 +++ w11/StrategyFactory11.java | 19 +++++++++ 14 files changed, 326 insertions(+) create mode 100644 w11/AnalyzeCommand11.java create mode 100644 w11/Article11.java create mode 100644 w11/ArticleRepository11.java create mode 100644 w11/Command11.java create mode 100644 w11/CommandRegistry11.java create mode 100644 w11/CrawlStrategy11.java create mode 100644 w11/CrawlerException11.java create mode 100644 w11/ExitCommand11.java create mode 100644 w11/HelpCommand11.java create mode 100644 w11/HistoryCommand11.java create mode 100644 w11/Main11.java create mode 100644 w11/NetworkException11.java create mode 100644 w11/ParseException11.java create mode 100644 w11/StrategyFactory11.java diff --git a/w11/AnalyzeCommand11.java b/w11/AnalyzeCommand11.java new file mode 100644 index 0000000..3fd3cac --- /dev/null +++ b/w11/AnalyzeCommand11.java @@ -0,0 +1,39 @@ +import java.util.List; +import java.util.logging.Logger; + +public class AnalyzeCommand11 implements Command11 { + private static final Logger logger = Logger.getLogger(AnalyzeCommand11.class.getName()); + private final StrategyFactory11 factory; + + public AnalyzeCommand11(StrategyFactory11 factory) { + this.factory = factory; + } + + @Override + public String getName() { + return "analyze"; + } + + @Override + public void execute(String[] args, List articles) { + if (args == null || args.length == 0) { + logger.warning("analyze 命令未传入URL参数"); + System.out.println("用法:analyze 网址"); + return; + } + String url = args[0]; + logger.info("开始分析链接:" + url); + CrawlStrategy11 strategy = factory.getMatchStrategy(url); + + System.out.println("===== 链接分析结果 ====="); + if (strategy != null) { + logger.info("链接 " + url + " 匹配到对应爬取策略"); + System.out.println("链接:" + url); + System.out.println("状态:支持解析 ✅"); + } else { + logger.warning("链接 " + url + " 未匹配到任何策略"); + System.out.println("链接:" + url); + System.out.println("状态:不支持解析 ❌"); + } + } +} \ No newline at end of file diff --git a/w11/Article11.java b/w11/Article11.java new file mode 100644 index 0000000..dd1689f --- /dev/null +++ b/w11/Article11.java @@ -0,0 +1,27 @@ +public class Article11 { + private String title; + private String url; + private String content; + private String author; + private String publishDate; + + public Article11(String title, String url, String content) { + this.title = title; + this.url = url; + this.content = content; + } + + public Article11(String title, String url, String content, String author, String publishDate) { + this.title = title; + this.url = url; + this.content = content; + this.author = author; + this.publishDate = publishDate; + } + + public String getTitle() { return title; } + public String getUrl() { return url; } + public String getContent() { return content; } + public String getAuthor() { return author; } + public String getPublishDate() { return publishDate; } +} \ No newline at end of file diff --git a/w11/ArticleRepository11.java b/w11/ArticleRepository11.java new file mode 100644 index 0000000..bfed78c --- /dev/null +++ b/w11/ArticleRepository11.java @@ -0,0 +1,48 @@ +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; + +public class ArticleRepository11 { + private static final Logger logger = Logger.getLogger(ArticleRepository11.class.getName()); + private final List articles = new ArrayList<>(); + + public void add(Article11 article) { + if (article == null) { + logger.severe("添加失败:文章对象为 null"); + throw new IllegalArgumentException("文章对象不能为空"); + } + articles.add(article); + logger.info("成功添加文章:" + article.getTitle()); + } + + public void addAll(List newArticles) { + if (newArticles == null) { + logger.severe("批量添加失败:传入列表为 null"); + throw new IllegalArgumentException("文章列表不能为空"); + } + int successCount = 0; + for (Article11 article : newArticles) { + if (article == null) { + logger.warning("列表中存在空对象,已跳过"); + continue; + } + articles.add(article); + successCount++; + } + logger.info("批量添加完成,共成功添加 " + successCount + " 篇文章"); + } + + public List getAll() { + return Collections.unmodifiableList(articles); + } + + public int size() { + return articles.size(); + } + + public void clear() { + logger.info("清空文章集合,原有数量:" + articles.size()); + articles.clear(); + } +} \ No newline at end of file diff --git a/w11/Command11.java b/w11/Command11.java new file mode 100644 index 0000000..f913db8 --- /dev/null +++ b/w11/Command11.java @@ -0,0 +1,6 @@ +import java.util.List; + +public interface Command11 { + String getName(); + void execute(String[] args, List articles); +} \ No newline at end of file diff --git a/w11/CommandRegistry11.java b/w11/CommandRegistry11.java new file mode 100644 index 0000000..2e0e648 --- /dev/null +++ b/w11/CommandRegistry11.java @@ -0,0 +1,14 @@ +import java.util.HashMap; +import java.util.Map; + +public class CommandRegistry11 { + private final Map commandMap = new HashMap<>(); + + public void registerCommand(Command11 command) { + commandMap.put(command.getName(), command); + } + + public Command11 getCommand(String name) { + return commandMap.get(name); + } +} \ No newline at end of file diff --git a/w11/CrawlStrategy11.java b/w11/CrawlStrategy11.java new file mode 100644 index 0000000..e84a8f8 --- /dev/null +++ b/w11/CrawlStrategy11.java @@ -0,0 +1,4 @@ +public interface CrawlStrategy11 { + boolean supports(String url); + Article11 crawl(String url) throws ParseException11, NetworkException11; +} \ No newline at end of file diff --git a/w11/CrawlerException11.java b/w11/CrawlerException11.java new file mode 100644 index 0000000..730fde6 --- /dev/null +++ b/w11/CrawlerException11.java @@ -0,0 +1,6 @@ +public class CrawlerException11 extends Exception { + public CrawlerException11() { super(); } + public CrawlerException11(String message) { super(message); } + public CrawlerException11(String message, Throwable cause) { super(message, cause); } + public CrawlerException11(Throwable cause) { super(cause); } +} \ No newline at end of file diff --git a/w11/ExitCommand11.java b/w11/ExitCommand11.java new file mode 100644 index 0000000..48c34ea --- /dev/null +++ b/w11/ExitCommand11.java @@ -0,0 +1,18 @@ +import java.util.List; +import java.util.logging.Logger; + +public class ExitCommand11 implements Command11 { + private static final Logger logger = Logger.getLogger(ExitCommand11.class.getName()); + + @Override + public String getName() { + return "exit"; + } + + @Override + public void execute(String[] args, List articles) { + logger.info("用户执行 exit 命令,程序即将退出"); + System.out.println("程序已安全退出!"); + System.exit(0); + } +} \ No newline at end of file diff --git a/w11/HelpCommand11.java b/w11/HelpCommand11.java new file mode 100644 index 0000000..43ae2cc --- /dev/null +++ b/w11/HelpCommand11.java @@ -0,0 +1,21 @@ +import java.util.List; +import java.util.logging.Logger; + +public class HelpCommand11 implements Command11 { + private static final Logger logger = Logger.getLogger(HelpCommand11.class.getName()); + + @Override + public String getName() { + return "help"; + } + + @Override + public void execute(String[] args, List articles) { + logger.info("用户执行 help 命令"); + System.out.println("===== W11 帮助菜单 ====="); + System.out.println("help 查看帮助"); + System.out.println("history 查看命令历史"); + System.out.println("analyze 分析URL链接"); + System.out.println("exit 退出程序"); + } +} \ No newline at end of file diff --git a/w11/HistoryCommand11.java b/w11/HistoryCommand11.java new file mode 100644 index 0000000..4e6aa46 --- /dev/null +++ b/w11/HistoryCommand11.java @@ -0,0 +1,31 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +public class HistoryCommand11 implements Command11 { + private static final Logger logger = Logger.getLogger(HistoryCommand11.class.getName()); + private final List commandHistory = new ArrayList<>(); + + @Override + public String getName() { + return "history"; + } + + @Override + public void execute(String[] args, List articles) { + if (commandHistory.isEmpty()) { + logger.info("暂无命令历史记录"); + System.out.println("暂无命令历史记录"); + return; + } + logger.info("用户查看命令历史"); + System.out.println("===== 命令历史 ====="); + for (int i = 0; i < commandHistory.size(); i++) { + System.out.println((i + 1) + ". " + commandHistory.get(i)); + } + } + + public void addCommand(String cmd) { + commandHistory.add(cmd); + } +} \ No newline at end of file diff --git a/w11/Main11.java b/w11/Main11.java new file mode 100644 index 0000000..ace9980 --- /dev/null +++ b/w11/Main11.java @@ -0,0 +1,81 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.logging.Logger; + +public class Main11 { + private static final Logger logger = Logger.getLogger(Main11.class.getName()); + private static final int MAX_RETRY_TIMES = 3; + + public static void main(String[] args) { + StrategyFactory11 strategyFactory = new StrategyFactory11(); + CommandRegistry11 cmdRegistry = new CommandRegistry11(); + HistoryCommand11 historyCmd = new HistoryCommand11(); + ArticleRepository11 repository = new ArticleRepository11(); + + // 模拟爬取策略 + 失败重试逻辑 + CrawlStrategy11 blogStrategy = new CrawlStrategy11() { + @Override + public boolean supports(String url) { + return url != null && url.contains("blog"); + } + + @Override + public Article11 crawl(String url) throws ParseException11, NetworkException11 { + for (int i = 1; i <= MAX_RETRY_TIMES; i++) { + try { + double random = Math.random(); + if (random < 0.3) { + throw new NetworkException11("网络连接超时"); + } + if (random < 0.2) { + throw new ParseException11("页面内容解析失败"); + } + return new Article11("博客文章", url, "正文内容", "博主", "2026-05-30"); + } catch (NetworkException11 e) { + logger.warning("第 " + i + " 次爬取异常:" + e.getMessage()); + if (i == MAX_RETRY_TIMES) { + throw new NetworkException11("已重试" + MAX_RETRY_TIMES + "次,任务终止", e); + } + } + } + return null; + } + }; + strategyFactory.registerStrategy(blogStrategy); + + cmdRegistry.registerCommand(new HelpCommand11()); + cmdRegistry.registerCommand(historyCmd); + cmdRegistry.registerCommand(new AnalyzeCommand11(strategyFactory)); + cmdRegistry.registerCommand(new ExitCommand11()); + + List articleData = new ArrayList<>(); + Scanner scanner = new Scanner(System.in); + logger.info("W11 爬虫程序启动成功"); + System.out.println("===== W11 爬虫程序启动 ====="); + + while (true) { + System.out.print("请输入命令:"); + String input = scanner.nextLine().trim(); + historyCmd.addCommand(input); + logger.info("用户输入命令:" + input); + + String[] splitArr = input.split(" ", 2); + String cmdName = splitArr[0]; + Command11 command = cmdRegistry.getCommand(cmdName); + + if (command != null) { + String[] params = splitArr.length > 1 ? new String[]{splitArr[1]} : new String[0]; + try { + command.execute(params, articleData); + } catch (Exception e) { + logger.severe("命令执行发生异常:" + e.getMessage()); + System.out.println("命令执行出错,请查看日志!"); + } + } else { + logger.warning("未知命令:" + cmdName); + System.out.println("未知命令,请输入 help 查看帮助"); + } + } + } +} \ No newline at end of file diff --git a/w11/NetworkException11.java b/w11/NetworkException11.java new file mode 100644 index 0000000..7271328 --- /dev/null +++ b/w11/NetworkException11.java @@ -0,0 +1,6 @@ +public class NetworkException11 extends CrawlerException11 { + public NetworkException11() { super(); } + public NetworkException11(String message) { super(message); } + public NetworkException11(String message, Throwable cause) { super(message, cause); } + public NetworkException11(Throwable cause) { super(cause); } +} \ No newline at end of file diff --git a/w11/ParseException11.java b/w11/ParseException11.java new file mode 100644 index 0000000..f7ec468 --- /dev/null +++ b/w11/ParseException11.java @@ -0,0 +1,6 @@ +public class ParseException11 extends CrawlerException11 { + public ParseException11() { super(); } + public ParseException11(String message) { super(message); } + public ParseException11(String message, Throwable cause) { super(message, cause); } + public ParseException11(Throwable cause) { super(cause); } +} \ No newline at end of file diff --git a/w11/StrategyFactory11.java b/w11/StrategyFactory11.java new file mode 100644 index 0000000..05edca2 --- /dev/null +++ b/w11/StrategyFactory11.java @@ -0,0 +1,19 @@ +import java.util.ArrayList; +import java.util.List; + +public class StrategyFactory11 { + private final List strategyList = new ArrayList<>(); + + public void registerStrategy(CrawlStrategy11 strategy) { + strategyList.add(strategy); + } + + public CrawlStrategy11 getMatchStrategy(String url) { + for (CrawlStrategy11 s : strategyList) { + if (s.supports(url)) { + return s; + } + } + return null; + } +} \ No newline at end of file