Java 使用递归方法遍历B站下载文件并解析重命名
目录
背景
出于学习和日常使用方便的目的,且考虑到有的资源过一段时间会失效,所以有时会下载B站的音频,视频,进行存放保留,下面介绍下载和下载之后解析文件的方法,仅供学习交流使用,请勿未经许可盗取UP主视频盈利。(以下操作均以安卓手机为例,iOS和PC端方法可能不一样)
操作方法
总的思路就是:将手机中下载好的B站视频,转到电脑上存储,并重命名即可(直接在电脑上下载,下载的文件都是加密过的,无法直接使用,当然,最简单的方法就是油猴上面下载两个插件,直接下载了,但是插件有的很不好用,而且一段时间后就不太稳定,下载画质也有的有限制,所以还是我想还是自己写一个方法,解决一下,并做一个分享,同时欢迎大佬有更简单更好的方法,在评论区可以留言交流)
例如,我使用PC端下载好一个鬼畜视频,将下载的目录打开后发现修改文件名后缀,并不能打开,文件内容应该是加密或者处理过的 (或者有其他办法,我暂时没有去找)
这里我是直接用手机把文件都去下载好,然后将手机和电脑通过USB线进行数据传输,在电脑上,找到手机下载的文件路径是:
此电脑\手机名\内部存储设备\Android\data\tv.danmaku.bili\download
与PC端不同的是手机端没有对文件进行加密,仅仅修改了文件的后缀名,反过来只要将音频和视频文件后缀名修改成正常的,即可直接观看使用了,但是文件很多的情况下,一个一个修改效率太低,于是我写了一个方法,使用Java去直接遍历这个文件夹,并根据文件信息进行重命名,效率将会大大提高很多。
package com.ss.system.util;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class BilibiliUtils {
public static void main(String[] args) {
// 创建一个 File 对象,指向 "D:\\UP" 目录,这是程序开始搜索的根目录。
File rootDir = new File("D:\\UP");
// 调用 processDirectory 方法来处理该目录及其子目录。
processDirectory(rootDir);
}
// 声明一个私有的静态方法 processDirectory,接受一个 File 对象作为参数。
private static void processDirectory(File dir) {
// if (dir.isDirectory()) 确保传入的 File 对象是一个目录。
if (dir.isDirectory()) {
// dir.listFiles() 返回一个 File 数组,包含目录中的所有文件和子目录。
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
// 递归处理子目录:如果是子目录,递归调用 processDirectory 方法来进一步处理。
if (file.isDirectory()) {
processDirectory(file);
// 如果找到名为 entry.json 的文件,调用 processJsonFile 方法进行处理。
} else if (file.getName().equalsIgnoreCase("entry.json")) {
processJsonFile(dir);
}
}
}
}
}
// 声明一个私有的静态方法 processJsonFile,接受一个 File 对象作为参数,这个 File 对象应指向包含 entry.json 文件的目录。
private static void processJsonFile(File jsonDir) {
// new File(jsonDir, "entry.json") 创建一个指向 entry.json 文件的 File 对象。
File jsonFile = new File(jsonDir, "entry.json");
if (jsonFile.exists()) {
// 使用 FileReader 和 Scanner 读取文件内容。
try (FileReader reader = new FileReader(jsonFile);
Scanner scanner = new Scanner(reader)) {
// scanner.useDelimiter("\\A").next() 读取整个文件内容为一个字符串。
String jsonString = scanner.useDelimiter("\\A").next();
// 使用 JsonParser 解析 JSON 字符串,并转换为 JsonObject。
JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
String title = jsonObject.get("title").getAsString();
String ownerName = jsonObject.get("owner_name").getAsString();
String newBaseName = title + " - " + ownerName;
System.out.println("New base name: " + newBaseName);
// 调用 searchAndRenameFiles 方法,在当前目录中查找 video.m4s 和 audio.m4s 文件并进行重命名。
searchAndRenameFiles(jsonDir, newBaseName);
} catch (IOException e) {
System.out.println("Failed to read or process JSON file: " + e.getMessage());
}
} else {
System.out.println("entry.json not found in directory: " + jsonDir.getAbsolutePath());
}
}
private static void searchAndRenameFiles(File startDir, String newBaseName) {
File[] files = startDir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
// Recursively search in subdirectories
searchAndRenameFiles(file, newBaseName);
} else if (file.getName().equalsIgnoreCase("video.m4s")) {
renameFileIfNeeded(file, newBaseName + ".mp4");
} else if (file.getName().equalsIgnoreCase("audio.m4s")) {
renameFileIfNeeded(file, newBaseName + ".mp3");
}
}
}
}
private static void renameFileIfNeeded(File file, String newName) {
if (file.exists()) {
File newFile = new File(file.getParent(), newName);
boolean success = file.renameTo(newFile);
if (success) {
System.out.println("Renamed to: " + newFile.getAbsolutePath());
} else {
System.out.println("Failed to rename: " + file.getAbsolutePath());
}
} else {
System.out.println("File not found: " + file.getAbsolutePath());
}
}
}
可以看到文件夹下面的所有文件,已经解析并重命名OK了。
更新(新增一个功能,将指定目录下所有 .mp3
文件复制到 D:\UP
,可以在 searchAndRenameFiles
方法中添加复制逻辑。)
package com.ss.system.util;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Scanner;
public class BilibiliUtils {
public static void main(String[] args) {
// 创建一个 File 对象,指向 "D:\\UP" 目录,这是程序开始搜索的根目录。
File rootDir = new File("D:\\UP");
// 调用 processDirectory 方法来处理该目录及其子目录。
processDirectory(rootDir);
}
// 声明一个私有的静态方法 processDirectory,接受一个 File 对象作为参数。
private static void processDirectory(File dir) {
// if (dir.isDirectory()) 确保传入的 File 对象是一个目录。
if (dir.isDirectory()) {
// dir.listFiles() 返回一个 File 数组,包含目录中的所有文件和子目录。
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
// 递归处理子目录:如果是子目录,递归调用 processDirectory 方法来进一步处理。
if (file.isDirectory()) {
processDirectory(file);
// 如果找到名为 entry.json 的文件,调用 processJsonFile 方法进行处理。
} else if (file.getName().equalsIgnoreCase("entry.json")) {
processJsonFile(dir);
}
}
}
}
}
// 声明一个私有的静态方法 processJsonFile,接受一个 File 对象作为参数,这个 File 对象应指向包含 entry.json 文件的目录。
private static void processJsonFile(File jsonDir) {
// new File(jsonDir, "entry.json") 创建一个指向 entry.json 文件的 File 对象。
File jsonFile = new File(jsonDir, "entry.json");
if (jsonFile.exists()) {
// 使用 FileReader 和 Scanner 读取文件内容。
try (FileReader reader = new FileReader(jsonFile);
Scanner scanner = new Scanner(reader)) {
// scanner.useDelimiter("\\A").next() 读取整个文件内容为一个字符串。
String jsonString = scanner.useDelimiter("\\A").next();
// 使用 JsonParser 解析 JSON 字符串,并转换为 JsonObject。
JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
String title = jsonObject.get("title").getAsString();
String ownerName = jsonObject.get("owner_name").getAsString();
String newBaseName = title + " - " + ownerName;
System.out.println("New base name: " + newBaseName);
// 调用 searchAndRenameFiles 方法,在当前目录中查找 video.m4s 和 audio.m4s 文件并进行重命名。
searchAndRenameFiles(jsonDir, newBaseName);
} catch (IOException e) {
System.out.println("Failed to read or process JSON file: " + e.getMessage());
}
} else {
System.out.println("entry.json not found in directory: " + jsonDir.getAbsolutePath());
}
}
private static void searchAndRenameFiles(File startDir, String newBaseName) {
File[] files = startDir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
searchAndRenameFiles(file, newBaseName);
} else if (file.getName().equalsIgnoreCase("video.m4s")) {
renameFileIfNeeded(file, newBaseName + ".mp4");
} else if (file.getName().equalsIgnoreCase("audio.m4s")) {
renameFileIfNeeded(file, newBaseName + ".mp3");
} else if (file.getName().toLowerCase().endsWith(".mp3")) {
copyMp3File(file);
}
}
}
}
private static void renameFileIfNeeded(File file, String newName) {
if (file.exists()) {
File newFile = new File(file.getParent(), newName);
boolean success = file.renameTo(newFile);
if (success) {
System.out.println("Renamed to: " + newFile.getAbsolutePath());
} else {
System.out.println("Failed to rename: " + file.getAbsolutePath());
}
} else {
System.out.println("File not found: " + file.getAbsolutePath());
}
}
private static void copyMp3File(File mp3File) {
File destDir = new File("D:\\UP");
if (!destDir.exists()) {
destDir.mkdirs();
}
File destFile = new File(destDir, mp3File.getName());
try {
Files.copy(mp3File.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
System.out.println("Copied: " + mp3File.getAbsolutePath() + " to " + destFile.getAbsolutePath());
} catch (IOException e) {
System.out.println("Failed to copy: " + mp3File.getAbsolutePath() + " - " + e.getMessage());
}
}
}
声明
下载文件的方法,网上帖子有很多,我只是借用了他们的方法,并简化了我自己保存文件的繁琐操作,请大家不要怀有恶意,也感谢B站的UP主上传分享的视频,B站如果后期修复,将移动端文件也加密了那这个方法也不奏效了,破解加密那个跟现在文件解析重命名就不是一个等级的工作了,大家也且用且珍惜吧。
本文仅作为一个分享,希望大家在保存文件的时候,可以方便一点,减少不必要的手动操作,本着技术中立原则,仅作为学习交流,请大家自行使用,不要去以此盗取他人视频商用。
原文地址:https://blog.csdn.net/weixin_49171365/article/details/142433495
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!