From 5046a6455ded79b0627426cc5a98744363bcbeb9 Mon Sep 17 00:00:00 2001 From: pizza0105 Date: Tue, 12 May 2026 10:52:13 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC9=E5=91=A8=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/datacollect/Main.java | 21 ++++++ .../example/datacollect/command/Command.java | 9 +++ .../datacollect/command/CrawlCommand.java | 49 +++++++++++++ .../datacollect/command/ExitCommand.java | 24 ++++++ .../datacollect/command/HelpCommand.java | 29 ++++++++ .../datacollect/command/HistoryCommand.java | 36 +++++++++ .../datacollect/command/ListCommand.java | 23 ++++++ .../controller/CrawlerController.java | 71 ++++++++++++++++++ .../example/datacollect/model/Article.java | 73 +++++++++++++++++++ .../example/datacollect/view/ConsoleView.java | 44 +++++++++++ w9/java-cli/strategy/BlogStrategy.java | 0 w9/java-cli/strategy/NewsStrategy.java | 0 12 files changed, 379 insertions(+) create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/Main.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/command/Command.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/command/CrawlCommand.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/command/ExitCommand.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/command/HelpCommand.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/command/HistoryCommand.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/command/ListCommand.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/controller/CrawlerController.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/model/Article.java create mode 100644 w9/java-cli/src/main/java/com/example/datacollect/view/ConsoleView.java create mode 100644 w9/java-cli/strategy/BlogStrategy.java create mode 100644 w9/java-cli/strategy/NewsStrategy.java diff --git a/w9/java-cli/src/main/java/com/example/datacollect/Main.java b/w9/java-cli/src/main/java/com/example/datacollect/Main.java new file mode 100644 index 0000000..44d00aa --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/Main.java @@ -0,0 +1,21 @@ +package com.example.datacollect; + +import com.example.datacollect.controller.CrawlerController; +import com.example.datacollect.model.Article; +import com.example.datacollect.view.ConsoleView; +import java.util.ArrayList; +import java.util.List; + +public class Main { + + public static void main(String[] args) { + ConsoleView view = new ConsoleView(); + List
articles = new ArrayList<>(); + CrawlerController controller = new CrawlerController(view, articles); + + view.printSuccess("Welcome to CLI Crawler (w9_1)! Type help for commands."); + while (true) { + controller.handle(view.readLine()); + } + } +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/command/Command.java b/w9/java-cli/src/main/java/com/example/datacollect/command/Command.java new file mode 100644 index 0000000..24e59a6 --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/command/Command.java @@ -0,0 +1,9 @@ +package com.example.datacollect.command; + +import com.example.datacollect.model.Article; +import java.util.List; + +public interface Command { + String getName(); + void execute(String[] args, List
articles); +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/command/CrawlCommand.java b/w9/java-cli/src/main/java/com/example/datacollect/command/CrawlCommand.java new file mode 100644 index 0000000..36e7add --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/command/CrawlCommand.java @@ -0,0 +1,49 @@ +package com.example.datacollect.command; + +import com.example.datacollect.model.Article; +import com.example.datacollect.view.ConsoleView; +import java.util.List; +import java.util.regex.Pattern; + +public class CrawlCommand implements Command { + private final ConsoleView view; + private static final Pattern URL_PATTERN = Pattern.compile( + "^(https?://)?([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?$" + ); + + public CrawlCommand(ConsoleView view) { + this.view = view; + } + + @Override + public String getName() { + return "crawl"; + } + + @Override + public void execute(String[] args, List
articles) { + if (args.length < 2) { + view.printError("Usage: crawl "); + return; + } + + String url = args[1]; + if (!isValidUrl(url)) { + view.printError("Invalid URL format: " + url); + view.printInfo("URL should start with http:// or https://"); + return; + } + + view.printInfo("Stub: would crawl " + url); + } + + private boolean isValidUrl(String url) { + if (url == null || url.isEmpty()) { + return false; + } + if (!url.startsWith("http://") && !url.startsWith("https://")) { + return false; + } + return URL_PATTERN.matcher(url).matches(); + } +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/command/ExitCommand.java b/w9/java-cli/src/main/java/com/example/datacollect/command/ExitCommand.java new file mode 100644 index 0000000..6946d85 --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/command/ExitCommand.java @@ -0,0 +1,24 @@ +package com.example.datacollect.command; + +import com.example.datacollect.model.Article; +import com.example.datacollect.view.ConsoleView; +import java.util.List; + +public class ExitCommand implements Command { + private final ConsoleView view; + + public ExitCommand(ConsoleView view) { + this.view = view; + } + + @Override + public String getName() { + return "exit"; + } + + @Override + public void execute(String[] args, List
articles) { + view.printSuccess("Bye!"); + System.exit(0); + } +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/command/HelpCommand.java b/w9/java-cli/src/main/java/com/example/datacollect/command/HelpCommand.java new file mode 100644 index 0000000..dccbac2 --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/command/HelpCommand.java @@ -0,0 +1,29 @@ +package com.example.datacollect.command; + +import com.example.datacollect.model.Article; +import com.example.datacollect.view.ConsoleView; +import java.util.List; + +public class HelpCommand implements Command { + private final ConsoleView view; + + public HelpCommand(ConsoleView view) { + this.view = view; + } + + @Override + public String getName() { + return "help"; + } + + @Override + public void execute(String[] args, List
articles) { + view.printInfo("Available commands:"); + view.printInfo(" crawl - 爬取指定URL的文章 (别名: c)"); + view.printInfo(" list - 列出所有已爬取的文章 (别名: l)"); + view.printInfo(" history - 显示命令历史记录 (别名: hi)"); + view.printInfo(" help - 显示帮助信息 (别名: h)"); + view.printInfo(" exit - 退出程序"); + view.printInfo("\nURL格式要求: 必须以 http:// 或 https:// 开头"); + } +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/command/HistoryCommand.java b/w9/java-cli/src/main/java/com/example/datacollect/command/HistoryCommand.java new file mode 100644 index 0000000..cf07a30 --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/command/HistoryCommand.java @@ -0,0 +1,36 @@ +package com.example.datacollect.command; + +import com.example.datacollect.model.Article; +import com.example.datacollect.view.ConsoleView; +import java.util.List; + +public class HistoryCommand implements Command { + private final ConsoleView view; + private final List history; + + public HistoryCommand(ConsoleView view, List history) { + this.view = view; + this.history = history; + } + + @Override + public String getName() { + return "history"; + } + + @Override + public void execute(String[] args, List
articles) { + if (history.isEmpty()) { + view.printInfo("暂无命令历史记录。"); + return; + } + view.printInfo("命令历史记录:"); + for (int i = 0; i < history.size(); i++) { + System.out.println((i + 1) + ". " + history.get(i)); + } + } + + public void addToHistory(String command) { + history.add(command); + } +} \ No newline at end of file diff --git a/w9/java-cli/src/main/java/com/example/datacollect/command/ListCommand.java b/w9/java-cli/src/main/java/com/example/datacollect/command/ListCommand.java new file mode 100644 index 0000000..8eba2cd --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/command/ListCommand.java @@ -0,0 +1,23 @@ +package com.example.datacollect.command; + +import com.example.datacollect.model.Article; +import com.example.datacollect.view.ConsoleView; +import java.util.List; + +public class ListCommand implements Command { + private final ConsoleView view; + + public ListCommand(ConsoleView view) { + this.view = view; + } + + @Override + public String getName() { + return "list"; + } + + @Override + public void execute(String[] args, List
articles) { + view.display(articles); + } +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/controller/CrawlerController.java b/w9/java-cli/src/main/java/com/example/datacollect/controller/CrawlerController.java new file mode 100644 index 0000000..91dc353 --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/controller/CrawlerController.java @@ -0,0 +1,71 @@ +package com.example.datacollect.controller; + +import com.example.datacollect.command.Command; +import com.example.datacollect.command.CrawlCommand; +import com.example.datacollect.command.ExitCommand; +import com.example.datacollect.command.HelpCommand; +import com.example.datacollect.command.HistoryCommand; +import com.example.datacollect.command.ListCommand; +import com.example.datacollect.model.Article; +import com.example.datacollect.view.ConsoleView; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CrawlerController { + private final Map commands = new HashMap<>(); + private final Map aliases = new HashMap<>(); + private final ConsoleView view; + private final List
articles; + private final List commandHistory = new ArrayList<>(); + private HistoryCommand historyCommand; + + public CrawlerController(ConsoleView view, List
articles) { + this.view = view; + this.articles = articles; + register(new HelpCommand(view)); + register(new ListCommand(view)); + register(new CrawlCommand(view)); + register(new ExitCommand(view)); + + historyCommand = new HistoryCommand(view, commandHistory); + register(historyCommand); + + registerAlias("c", "crawl"); + registerAlias("h", "help"); + registerAlias("l", "list"); + registerAlias("hi", "history"); + } + + private void register(Command command) { + commands.put(command.getName(), command); + } + + private void registerAlias(String alias, String commandName) { + aliases.put(alias, commandName); + } + + public void handle(String input) { + String text = input == null ? "" : input.trim(); + if (text.isEmpty()) { + return; + } + + commandHistory.add(text); + + String[] args = text.split("\\s+"); + String cmdName = args[0].toLowerCase(); + + if (aliases.containsKey(cmdName)) { + cmdName = aliases.get(cmdName); + } + + Command command = commands.get(cmdName); + if (command == null) { + view.printError("Unknown command: " + cmdName); + return; + } + command.execute(args, articles); + } +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/model/Article.java b/w9/java-cli/src/main/java/com/example/datacollect/model/Article.java new file mode 100644 index 0000000..978c641 --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/model/Article.java @@ -0,0 +1,73 @@ +package com.example.datacollect.model; + +public class Article { + private String title; + private String url; + private String content; + private String author; + private String publishDate; + + public Article(String title, String url, String content) { + this.title = title; + this.url = url; + this.content = content; + } + + public Article(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 void setTitle(String title) { + this.title = title; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getPublishDate() { + return publishDate; + } + + public void setPublishDate(String publishDate) { + this.publishDate = publishDate; + } + + @Override + public String toString() { + return "Article{" + + "title='" + title + '\'' + + ", url='" + url + '\'' + + ", author='" + author + '\'' + + ", publishDate='" + publishDate + '\'' + + '}'; + } +} diff --git a/w9/java-cli/src/main/java/com/example/datacollect/view/ConsoleView.java b/w9/java-cli/src/main/java/com/example/datacollect/view/ConsoleView.java new file mode 100644 index 0000000..1a7c023 --- /dev/null +++ b/w9/java-cli/src/main/java/com/example/datacollect/view/ConsoleView.java @@ -0,0 +1,44 @@ +package com.example.datacollect.view; + +import com.example.datacollect.model.Article; +import java.util.List; +import java.util.Scanner; + +public class ConsoleView { + private static final String ANSI_RESET = "\u001B[0m"; + private static final String ANSI_GREEN = "\u001B[38;5;48m"; + private static final String ANSI_RED = "\u001B[38;5;196m"; + private static final String ANSI_BLUE = "\u001B[38;5;39m"; + private static final String ANSI_DARK_BG = "\u001B[48;5;234m"; + private static final String ANSI_WHITE = "\u001B[38;5;255m"; + + private final Scanner scanner = new Scanner(System.in); + + public String readLine() { + System.out.print("> "); + return scanner.nextLine(); + } + + public void printSuccess(String msg) { + System.out.println(ANSI_GREEN + msg + ANSI_RESET); + } + + public void printError(String msg) { + System.out.println(ANSI_RED + msg + ANSI_RESET); + } + + public void printInfo(String msg) { + System.out.println(ANSI_BLUE + msg + ANSI_RESET); + } + + public void display(List
articles) { + if (articles.isEmpty()) { + printInfo("暂无文章,请先执行 crawl。"); + return; + } + for (int i = 0; i < articles.size(); i++) { + Article a = articles.get(i); + System.out.println((i + 1) + ". " + a.getTitle() + " | " + a.getUrl()); + } + } +} diff --git a/w9/java-cli/strategy/BlogStrategy.java b/w9/java-cli/strategy/BlogStrategy.java new file mode 100644 index 0000000..e69de29 diff --git a/w9/java-cli/strategy/NewsStrategy.java b/w9/java-cli/strategy/NewsStrategy.java new file mode 100644 index 0000000..e69de29