From 12c33502c4c037fbf2388e9a24be3930efd4f80e Mon Sep 17 00:00:00 2001 From: Xingzhimeng <3408335915@qq.com> Date: Sat, 30 May 2026 17:33:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20'project/src/main/java/com/example'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/example/Command.java | 11 ++ .../main/java/com/example/CommandInvoker.java | 44 ++++++++ .../src/main/java/com/example/Crawler.java | 106 ++++++++++++++++++ .../main/java/com/example/CrawlerCommand.java | 47 ++++++++ .../java/com/example/CrawlerException.java | 40 +++++++ 5 files changed, 248 insertions(+) create mode 100644 project/src/main/java/com/example/Command.java create mode 100644 project/src/main/java/com/example/CommandInvoker.java create mode 100644 project/src/main/java/com/example/Crawler.java create mode 100644 project/src/main/java/com/example/CrawlerCommand.java create mode 100644 project/src/main/java/com/example/CrawlerException.java diff --git a/project/src/main/java/com/example/Command.java b/project/src/main/java/com/example/Command.java new file mode 100644 index 0000000..883dc45 --- /dev/null +++ b/project/src/main/java/com/example/Command.java @@ -0,0 +1,11 @@ +package com.example; + +/** + * 命令接口 - 命令模式 + * 课堂知识点:命令模式、接口 + */ +public interface Command { + void execute() throws CrawlerException; + void undo(); + String getDescription(); +} \ No newline at end of file diff --git a/project/src/main/java/com/example/CommandInvoker.java b/project/src/main/java/com/example/CommandInvoker.java new file mode 100644 index 0000000..fa9cc75 --- /dev/null +++ b/project/src/main/java/com/example/CommandInvoker.java @@ -0,0 +1,44 @@ +package com.example; + +import java.util.ArrayList; +import java.util.List; + +/** + * 命令调用器 - 命令模式 + * 课堂知识点:命令模式、集合框架 + */ +public class CommandInvoker { + private final List history = new ArrayList<>(); + private int currentIndex = -1; + + public void execute(Command cmd) throws CrawlerException { + cmd.execute(); + if (currentIndex < history.size() - 1) { + history.subList(currentIndex + 1, history.size()).clear(); + } + history.add(cmd); + currentIndex++; + } + + public void undo() { + if (currentIndex < 0) { + System.out.println("没有可撤销的命令"); + return; + } + history.get(currentIndex).undo(); + currentIndex--; + } + + public void showHistory() { + System.out.println("\n========== 命令历史 =========="); + if (history.isEmpty()) { + System.out.println("暂无命令历史"); + } else { + for (int i = 0; i < history.size(); i++) { + String marker = (i == currentIndex) ? "→" : " "; + System.out.printf("%s %2d. %s\n", marker, i + 1, history.get(i).getDescription()); + } + } + System.out.println("=============================="); + } +} \ No newline at end of file diff --git a/project/src/main/java/com/example/Crawler.java b/project/src/main/java/com/example/Crawler.java new file mode 100644 index 0000000..3928cb6 --- /dev/null +++ b/project/src/main/java/com/example/Crawler.java @@ -0,0 +1,106 @@ +package com.example; + +import java.io.IOException; + +/** + * 爬虫基类 - 定义爬虫的通用行为和属性 + * 课堂知识点:继承、抽象类、封装 + */ +public abstract class Crawler { + + /** + * 请求间隔时间(毫秒)- 避免被网站封禁 + */ + protected static final int DELAY_MS = 1000; + + /** + * 爬取状态:是否成功 + */ + private boolean success; + + /** + * 爬取的数据数量 + */ + private int dataCount; + + /** + * 爬取数据 - 抽象方法,子类必须实现 + * 课堂知识点:抽象方法 + */ + public abstract void crawl(); + + /** + * 打印结果 - 抽象方法,子类必须实现 + */ + public abstract void printResults(); + + /** + * 保存数据到文件 - 抽象方法,子类必须实现 + */ + public abstract void saveToFile(String filename) throws IOException; + + /** + * 保存数据到数据库 - 抽象方法,子类必须实现 + * 课堂知识点:JDBC、数据库持久化 + */ + public abstract void saveToDatabase(); + + /** + * 检查网络状态 + * @return 网络是否可用 + */ + protected boolean isNetworkAvailable() { + return HttpCrawler.isNetworkAvailable(); + } + + /** + * 添加请求延迟,避免被封禁 + */ + protected void delay() { + try { + Thread.sleep(DELAY_MS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + /** + * 获取爬取状态 + * @return 是否成功 + */ + public boolean isSuccess() { + return success; + } + + /** + * 设置爬取状态 + * @param success 是否成功 + */ + protected void setSuccess(boolean success) { + this.success = success; + } + + /** + * 获取数据数量 + * @return 数据数量 + */ + public int getDataCount() { + return dataCount; + } + + /** + * 设置数据数量 + * @param dataCount 数据数量 + */ + protected void setDataCount(int dataCount) { + this.dataCount = dataCount; + } + + /** + * 获取爬虫名称(默认实现,子类可重写) + * @return 爬虫名称 + */ + public String getCrawlerName() { + return this.getClass().getSimpleName(); + } +} \ No newline at end of file diff --git a/project/src/main/java/com/example/CrawlerCommand.java b/project/src/main/java/com/example/CrawlerCommand.java new file mode 100644 index 0000000..38745b1 --- /dev/null +++ b/project/src/main/java/com/example/CrawlerCommand.java @@ -0,0 +1,47 @@ +package com.example; + +/** + * 爬虫命令 - 命令模式实现 + */ +public class CrawlerCommand implements Command { + private final Crawler crawler; + private final String filename; + private boolean executed; + + public CrawlerCommand(Crawler crawler, String filename) { + this.crawler = crawler; + this.filename = filename; + this.executed = false; + } + + @Override + public void execute() throws CrawlerException { + if (executed) { + throw new CrawlerException("命令已经执行过"); + } + try { + System.out.println("执行: " + getDescription()); + crawler.crawl(); + crawler.printResults(); + crawler.saveToFile(filename); + executed = true; + } catch (Exception e) { + throw new CrawlerException("执行失败: " + e.getMessage(), e); + } + } + + @Override + public void undo() { + if (!executed) { + System.out.println("命令未执行,无法撤销"); + return; + } + System.out.println("撤销: " + getDescription()); + executed = false; + } + + @Override + public String getDescription() { + return crawler.getCrawlerName() + " -> " + filename; + } +} \ No newline at end of file diff --git a/project/src/main/java/com/example/CrawlerException.java b/project/src/main/java/com/example/CrawlerException.java new file mode 100644 index 0000000..ebace69 --- /dev/null +++ b/project/src/main/java/com/example/CrawlerException.java @@ -0,0 +1,40 @@ +package com.example; + +import java.io.IOException; + +/** + * 爬虫异常基类 - 异常体系 + * 课堂知识点:自定义异常、异常继承体系 + */ +public class CrawlerException extends Exception { + public CrawlerException(String message) { + super(message); + } + public CrawlerException(String message, Throwable cause) { + super(message, cause); + } +} + +/** + * 网络异常 - 网络连接失败 + */ +class NetworkException extends CrawlerException { + public NetworkException(String message) { super(message); } + public NetworkException(String message, Throwable cause) { super(message, cause); } +} + +/** + * 数据解析异常 - HTML/JSON解析失败 + */ +class DataParseException extends CrawlerException { + public DataParseException(String message) { super(message); } + public DataParseException(String message, Throwable cause) { super(message, cause); } +} + +/** + * 文件保存异常 - 文件写入失败 + */ +class FileSaveException extends CrawlerException { + public FileSaveException(String message) { super(message); } + public FileSaveException(String message, IOException cause) { super(message, cause); } +} \ No newline at end of file