import\u0020javafx.application.Application;import\u0020javafx.application.Platform;import\u0020javafx.concurrent.Task;import\u0020javafx.geometry.Insets;import\u0020javafx.scene.Scene;import\u0020javafx.scene.control.;import\u0020javafx.scene.layout.;import\u0020javafx.scene.text.Font;import\u0020javafx.stage.Stage;import\u0020org.jsoup.Jsoup;import\u0020org.jsoup.nodes.Document;import\u0020org.jsoup.select.Elements;import\u0020org.openqa.selenium.By;import\u0020org.openqa.selenium.Keys;import\u0020org.openqa.selenium.WebDriver;import\u0020org.openqa.selenium.WebElement;import\u0020org.openqa.selenium.chrome.ChromeDriver;import\u0020org.openqa.selenium.chrome.ChromeOptions;import\u0020org.openqa.selenium.support.ui.ExpectedConditions;import\u0020org.openqa.selenium.support.ui.WebDriverWait;import\u0020java.io.BufferedWriter;import\u0020java.io.File;import\u0020java.io.FileWriter;import\u0020java.io.IOException;import\u0020java.util.HashMap;import\u0020java.util.List;import\u0020java.util.Map;import\u0020java.util.stream.Collectors;public\u0020class\u0020NovelDownloader\u0020extends\u0020Application\u0020{private\u0020Map<String, String> chapters\u0020=\u0020new\u0020HashMap<>();private\u0020TextField novelNameInput;private\u0020CheckBox saveCheckBox;private\u0020ListView chapterList;private\u0020TextArea chapterText;private\u0020WebDriver driver;public\u0020static\u0020void\u0020main(String[] args) {launch(args);}@Overridepublic\u0020void\u0020start(Stage primaryStage) {primaryStage.setTitle('小说下载器');novelNameInput\u0020=\u0020new\u0020TextField();saveCheckBox\u0020=\u0020new\u0020CheckBox('是否下载小说内容到当前目录下');Button searchButton\u0020=\u0020new\u0020Button('获取');chapterList\u0020=\u0020new\u0020ListView<>();chapterText\u0020=\u0020new\u0020TextArea();VBox root\u0020=\u0020new\u0020VBox(10);root.setPadding(new\u0020Insets(10));HBox inputBox\u0020=\u0020new\u0020HBox(10);HBox.setHgrow(novelNameInput, Priority.ALWAYS);inputBox.getChildren().addAll(novelNameInput, saveCheckBox, searchButton);root.getChildren().addAll(new\u0020Label('请输入小说名称:'), inputBox, createChapterPane());searchButton.setOnAction(event\u0020-> {String novelName\u0020=\u0020novelNameInput.getText();if (!novelName.isEmpty()) {searchNovelAndScrape(novelName);} else {showAlert('警告', '请输入小说名称', Alert.AlertType.WARNING);}});chapterList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue)\u0020-> {if (newValue != null) {showChapterContent(newValue);}});primaryStage.setScene(new\u0020Scene(root, 800, 600));primaryStage.show();}public\u0020VBox createChapterPane() {VBox chapterPane\u0020=\u0020new\u0020VBox(10);chapterPane.setPadding(new\u0020Insets(10));chapterPane.setStyle('-fx-background-color:\u0020#f1f1f1');HBox headerBox\u0020=\u0020new\u0020HBox(10);headerBox.setPadding(new\u0020Insets(5));headerBox.setStyle('-fx-background-color:\u0020#e1e1e1');Label chapterLabel\u0020=\u0020new\u0020Label('章节列表');chapterLabel.setFont(Font.font(14));Region spacer\u0020=\u0020new\u0020Region();HBox.setHgrow(spacer, Priority.ALWAYS);headerBox.getChildren().addAll(chapterLabel, spacer);chapterText.setEditable(false);chapterText.setWrapText(true);chapterPane.getChildren().addAll(headerBox, chapterList, chapterText);VBox.setVgrow(chapterList, Priority.ALWAYS);VBox.setVgrow(chapterText, Priority.ALWAYS);return chapterPane;}public\u0020void\u0020searchNovelAndScrape(String novelName) {Task task\u0020=\u0020new\u0020Task() {@Overrideprotected\u0020Void call() throws\u0020Exception {try {setupChromeDriver();driver.get('https://www.bige3.cc/');WebElement searchInput\u0020=\u0020driver.findElement(By.xpath('/html/body/div[4]/div[1]/div[2]/form/input[1]'));searchInput.sendKeys(novelName);searchInput.sendKeys(Keys.ENTER);WebDriverWait wait\u0020=\u0020new\u0020WebDriverWait(driver, 10);wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath('/html/body/div[5]/div/div/div/div/div[2]/h4/a')));List elements\u0020=\u0020driver.findElements(By.xpath('/html/body/div[5]/div/div/div/div/div[2]/h4/a'));if (elements.isEmpty()) {showAlert('提示', '没有找到相关小说', Alert.AlertType.INFORMATION);return null;}for (WebElement element : elements) {element.click();driver.switchTo().window(driver.getWindowHandles().stream().reduce((first, second) -> second).orElse(null));wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath('//[@class='listmain']/dl/dd/a')));List chapterElements\u0020=\u0020driver.findElements(By.xpath('//[@class='listmain']/dl/dd/a'));for (WebElement chapter : chapterElements) {chapter.click();while (true) {wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath('//[@id='read']/div[5]/div[3]/h1')));WebElement chapterTitleElement\u0020=\u0020driver.findElement(By.xpath('//[@id='read']/div[5]/div[3]/h1'));WebElement chapterContentElement\u0020=\u0020driver.findElement(By.xpath('//*[@id='chaptercontent']'));String chapterTitle\u0020=\u0020chapterTitleElement.getText().replace('、', '');String chapterContent\u0020=\u0020chapterContentElement.getAttribute('innerHTML').replaceAll('无弹窗,更新快,免费阅读!', '').replaceAll('请收藏本站:https://www.bige3.cc。笔趣阁手机版:https://m.bige3.cc', '').replaceAll('『点此报错』『加入书签』', '');if (saveCheckBox.isSelected()) {saveChapterToFile(novelName, chapterTitle, chapterContent);}String cleanContent\u0020=\u0020cleanChapterContent(chapterContent);chapters.put(chapterTitle, cleanContent);updateChapterList();try {wait.until(ExpectedConditions.elementToBeClickable(By.xpath('//div[@class='Readpage pagedown']/a[@id='pb_next']')));WebElement nextButton\u0020=\u0020driver.findElement(By.xpath('//div[@class='Readpage pagedown']/a[@id='pb_next']'));nextButton.click();} catch (Exception e) {break;}}driver.navigate().back();}}catch (Exception e) {e.printStackTrace();showAlert('提示', '运行出错', Alert.AlertType.ERROR);} finally {cleanupChromeDriver();}}return null;}}Thread thread\u0020=\u0020new\u0020Thread(task);thread.setDaemon(true);thread.start();}private\u0020void\u0020setupChromeDriver() {ChromeOptions options\u0020=\u0020new\u0020ChromeOptions();options.addArguments('--no-sandbox');options.addArguments('--disable-dev-shm-usage');options.addArguments('--window-size=1920,1080');options.addArguments('user-agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'');driver\u0020=\u0020new\u0020ChromeDriver(options);}private\u0020void\u0020cleanupChromeDriver() {if (driver != null) {driver.close();driver.quit();}}private\u0020void\u0020saveChapterToFile(String novelName, String chapterTitle, String chapterContent) {String bookDir\u0020=\u0020System.getProperty('user.dir') + '/' + novelName;File bookDirectory\u0020=\u0020new\u0020File(bookDir);if (!bookDirectory.exists()) {bookDirectory.mkdirs();}String chapterPath\u0020=\u0020bookDir + '/' + chapterTitle + '.txt';try (BufferedWriter writer\u0020=\u0020new\u0020BufferedWriter(new\u0020FileWriter(chapterPath))) {writer.write(chapterContent);} catch (IOException e) {e.printStackTrace();}}private\u0020String cleanChapterContent(String chapterContent) {Document doc\u0020=\u0020Jsoup.parse(chapterContent);Elements chapterBrElements\u0020=\u0020doc.select('br');return chapterBrElements.stream().map(brElement\u0020->\u0020brElement.nextSibling().toString().trim()).filter(text\u0020->\u0020!text.isEmpty()).collect(Collectors.joining('\n'));}public\u0020void\u0020updateChapterList() {Platform.runLater(() -> {chapterList.getItems().clear();chapterList.getItems().addAll(chapters.keySet());});}public\u0020void\u0020showChapterContent(String chapterTitle) {Platform.runLater(() -> {String content\u0020=\u0020chapters.get(chapterTitle);if (content != null) {content\u0020=\u0020content.replaceAll('
', '\n '); // Replace
with spaceschapterText.setText(content);}});}public\u0020static\u0020void\u0020showAlert(String title, String message, Alert.AlertType alertType) {Platform.runLater(() -> {Alert alert\u0020=\u0020new\u0020Alert(alertType);alert.setTitle(title);alert.setHeaderText(null);alert.setContentText(message);alert.showAndWait();});}@Overridepublic\u0020void\u0020stop() {cleanupChromeDriver();