package sample;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Alert;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.application.Platform;
import java.io.File;
import java.net.HttpURLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import javax.swing.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class main extends Application {
private TextField shareUrlField = new TextField();
private CheckBox testOpenCheckbox = new CheckBox("调试");
private TextField testPathField = new TextField();
private TextField testTimeField = new TextField();
private Button downloadButton = new Button("下载视频");
private ProgressBar progressBar = new ProgressBar(0);
// 默认等待时间
private static final int DEFAULT_TEST_TIME = 5;
private static final int WINDOW_WIDTH = 400;
private static final int WINDOW_HEIGHT = 300;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("视频下载器");
primaryStage.setMinWidth(WINDOW_WIDTH);
primaryStage.setMinHeight(WINDOW_HEIGHT);
primaryStage.setMaxWidth(WINDOW_WIDTH);
primaryStage.setMaxHeight(WINDOW_HEIGHT);
progressBar.setPrefWidth(WINDOW_WIDTH);
testTimeField.setPromptText("5"); // 设置默认值提示
downloadButton.setOnAction(e -> {
downloadButton.setDisable(true);
downloadButton.setText("下载中...");
String shareUrl = shareUrlField.getText();
boolean testOpen = testOpenCheckbox.isSelected();
String testPath = testPathField.getText();
// 检查testTimeField是否为空,使用默认值
int testTime = testTimeField.getText().isEmpty() ? DEFAULT_TEST_TIME : Integer.parseInt(testTimeField.getText());
// 重置进度条
progressBar.setProgress(0);
// 创建一个后台任务
Task downloadTask = new Task() {
@Override
protected Void call() throws Exception {
// 在这里调用您的视频下载代码,将用户输入传递给下载方法
downloadVideo(shareUrl, testOpen, testPath, testTime);
return null;
}
};
downloadTask.setOnSucceeded(event -> {
// 下载完成时的处理,例如弹出消息或其他操作
downloadButton.setText("下载视频");
downloadButton.setDisable(false);
});
downloadTask.setOnFailed(event -> {
// 下载失败时的处理
downloadButton.setText("下载视频");
downloadButton.setDisable(false);
});
// 启动任务
Thread downloadThread = new Thread(downloadTask);
downloadThread.setDaemon(true); // 设置为守护线程,以便在主窗口关闭时终止下载
downloadThread.start();
});
VBox vbox = new VBox(10);
vbox.setPrefWidth(WINDOW_WIDTH); // 设置首选宽度
vbox.setPrefHeight(WINDOW_HEIGHT); // 设置首选高度
vbox.getChildren().addAll(
new Label("modal_id:"),
shareUrlField,
new Label("下载路径:(\\结尾)"),
testPathField,
new Label("等待时间 (秒):"),
testTimeField,
testOpenCheckbox,
downloadButton,
progressBar
);
Scene scene = new Scene(vbox, WINDOW_WIDTH, WINDOW_HEIGHT); // 设置Scene的宽度和高度
primaryStage.setScene(scene);
primaryStage.show();
}
private void downloadVideo(String Url, boolean testOpen, String testPath, int testTime) {
// 在这里调用您的视频下载代码,将用户输入传递给下载方法
System.setProperty("webdriver.chrome.driver", "C:\\chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--headless"); // 启用无头模式
chromeOptions.addArguments("--disable-gpu"); // 禁用GPU加速
chromeOptions.addArguments("--headless", "--no-sandbox"); //禁用沙盒模式
WebDriver driver = new ChromeDriver(chromeOptions);
// //URL
String shareUrl="https://www.douyin.com/video/"+Url;
// //测试地址
// Boolean testOpen=true;
// //下载路径
// String testPath="C:\\Users\\T\\Desktop\\";
// //等待时间
// int testTime=5;
try{
driver.get(shareUrl); // 替换为目标页面的URL
Thread.sleep(testTime*1000);
String localPath=testPath;
String absoluteFilePath = localPath+"screenshot.png"; // 使用绝对文件路径
if(testOpen){
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshot, new File(absoluteFilePath));
}
// 获取页面源代码
String pageSource = driver.getPageSource();
driver.quit();
//打开页面抓取
// WebElement dynamicDataElement = driver.findElement(By.xpath("//*[@id=\"__next\"]/div[1]/div[3]/div/div/div[1]/div[1]/div[2]/div[1]/div[1]/div[1]/div[1]"));
// WebElement dynamicDataElement =driver.findElement(By.cssSelector("#__next > div:nth-child(1) > div:nth-child(3) > div > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1)"));
// String dynamicData = dynamicDataElement.getText();
// System.out.println("Dynamic Data: " + dynamicData);
//无头模式正则
String regex="(?<=)(.*?)(?=)";
// Pattern titlePattern = Pattern.compile(titleRegex);
// Matcher titleMatcher = titlePattern.matcher(pageSource);
// String titleExtractedString=random();
// while (titleMatcher.find()) {
// titleExtractedString = titleMatcher.group();
// }
String titleExtractedString=shareUrl.split("video/")[1];
System.out.println("ID:"+titleExtractedString);
System.out.println("https:"+extractedString);
if(extractedString==null){
Platform.runLater(() ->showErrorAlert("失败","下载失败"));
}
//下载视频
down("https:"+extractedString,localPath,titleExtractedString);
}catch(Exception e){
System.out.println(e.getMessage());
driver.quit();
}
}
public void down(String videoURL,String localPath,String title){
String savePath = localPath+title+".mp4"; // 本地保存视频的文件路径
System.out.println("down——URL: " + videoURL);
try {
URL url = new URL(videoURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 添加自定义请求头,模拟浏览器请求
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");
connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
connection.setRequestProperty("Host", "www.douyin.com");
InputStream inputStream = new ProgressMonitorInputStream(null, "正在下载视频", connection.getInputStream());
FileOutputStream fileOutputStream = new FileOutputStream(savePath);
byte[] buffer = new byte[4096];
int bytesRead;
long totalBytesRead = 0;
long totalBytes = url.openConnection().getContentLength(); // 获取总字节数
while ((bytesRead = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
// 计算下载进度
int progress = (int) ((totalBytesRead * 100) / totalBytes);
Platform.runLater(() ->setProgress(progress));
System.out.println("下载进度: " + progress + "%");
}
inputStream.close();
fileOutputStream.close();
System.out.println("视频下载完成。");
} catch (IOException e) {
e.printStackTrace();
}
}
public void setProgress(int progress){
progressBar.setProgress((double)progress/100);
};
public String random(){
int length = 18;
StringBuilder randomString = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
int digit = random.nextInt(10); // 生成0到9之间的随机数字
randomString.append(digit);
}
String random18DigitNumber = randomString.toString();
return random18DigitNumber;
}
// 弹出错误提示框
private void showErrorAlert(String title, String content) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(content);
alert.showAndWait();
}
}
pom
org.seleniumhq.selenium
selenium-java
3.141.59
commons-io
commons-io
2.11.0
test
org.apache.maven.plugins
maven-assembly-plugin
3.3.0
jar-with-dependencies
sample.main
package
single
编译好编译好的文件 需要下载谷歌浏览器 和对应的驱动文件,驱动文件放在C盘根目录下