在B站看学习视频很方便,不会出现度娘的那种未知原因被和谐的情况,有时候可能想下载视频到本地,这时候发现在视频页面没有下载按钮。
B站视频下载
通过修改URL来进入下载页面,在bilibili
前面加入kan
即可。
示例:原地址:https://www.bilibili.com/video/av45556406
==>https://www.kanbilibili.com/video/av45556406
即可进入下载页面
点击下载地址
即可到达下载地址页面,选择清晰度,也可选择批量下载,通过复制下载链接,使用迅雷下载到本地即可。
下载完成之后本地视频文件如下:
发现文件名称与B站显示的名称不一致,不知道每节视频的题目内容,观看很不方便,因此我们需要修改文件名。
修改文件名
java代码如下:
package com.example.sql;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
/**
* @author Administrator
* @date 2019/6/30 19:50
*/
public class RenameFile {
private static final String TITLE = "title=";
private static final String SPAN_CLASS_S_1 = "<span class=\"s1\">";
private static final String STR = "-1-80";
private static final String FLV_STR = "-分片1.flv";
public static void main(String[] args) {
final Map<String, String> fileName = getFileName();
System.out.println("===================================================");
final Map<String, String> downloadNameMap = getDownloadNameMap();
// 要遍历的路径
String path = "E:\\学习视频\\Java编程方法论\\响应式 之 Reactor-Netty讲解 全集";
// 获取其file对象
File file = new File(path);
// 遍历path下的文件和目录,放在File数组中
File[] fs = file.listFiles();
// 遍历File[]数组
for (int i = 0; i < fs.length; i++) {
File f = fs[i];
// 若非目录(即文件),则打印
if (!f.isDirectory())
{
String pNum = downloadNameMap.get(f.getName());
if (!StringUtils.isEmpty(pNum)) {
String newName = fileName.get(pNum);
FixFileName(f, newName);
}
}
}
}
public static Map<String, String> getFileName() {
Map<String, String> result = new HashMap<>(72);
try {
// 构造一个BufferedReader类来读取文件
BufferedReader br = new BufferedReader(new FileReader(new File("C:\\Users\\Administrator\\Desktop\\b.txt")));
String s = null;
// 使用readLine方法,一次读一行
while ((s = br.readLine()) != null) {
// System.out.println("读取内容:" + s);
String substring = null;
if (s.contains(TITLE)) {
final int start = s.indexOf(TITLE) + 7;
final int end = s.indexOf("van-icon-videodetails_play") - 12;
substring = s.substring(start, end);
System.out.println("###标题###:" + substring);
}
String pNum = null;
if (s.contains(SPAN_CLASS_S_1)) {
final int pStart = s.indexOf(SPAN_CLASS_S_1) + 17;
final int pEnd = s.indexOf(SPAN_CLASS_S_1) + 20;
pNum = s.substring(pStart, pEnd);
pNum = pNum.replace("<", "");
System.out.println("###pNum###:" + pNum);
}
if (!StringUtils.isEmpty(substring) && !StringUtils.isEmpty(pNum)) {
result.put(pNum, substring);
}
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static Map<String, String> getDownloadNameMap() {
Map<String, String> result = new HashMap<>(72);
try {
// 构造一个BufferedReader类来读取文件
BufferedReader br = new BufferedReader(new FileReader(new File("C:\\Users\\Administrator\\Desktop\\a.txt")));
String s = null;
// 使用readLine方法,一次读一行
while ((s = br.readLine()) != null) {
// System.out.println("读取内容:" + s);
String substring = null;
if (s.contains(STR)) {
final int start = s.indexOf(STR) - 8;
final int end = s.indexOf(STR) + 9;
substring = s.substring(start, end);
System.out.println("###标题###:" + substring);
}
String pNum = null;
if (s.contains(FLV_STR)) {
final int pStart = s.indexOf(FLV_STR) - 3;
final int pEnd = s.indexOf(FLV_STR);
pNum = s.substring(pStart, pEnd);
pNum = pNum.replace("-", "");
System.out.println("###pNum###:" + pNum);
}
if (!StringUtils.isEmpty(substring) && !StringUtils.isEmpty(pNum)) {
result.put(substring, pNum);
}
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 通过文件路径直接修改文件名
*
* @param f 需要修改的文件
* @param newFileName 需要修改的文件的名称
* @return
*/
private static String FixFileName(File f, String newFileName) {
if (f == null) { // 判断原文件是否存在(防止文件名冲突)
return null;
}
String filePath = f.getPath();
newFileName = newFileName.trim();
// 文件名不能为空
if ("".equals(newFileName) || (newFileName == null)) {
return null;
}
String newFilePath = null;
// 判断是否为文件夹
if (f.isDirectory()) {
newFilePath = filePath.substring(0, filePath.lastIndexOf("\\")) + "\\" + newFileName;
} else {
newFilePath = filePath.substring(0, filePath.lastIndexOf("\\")) + "\\" + newFileName
+ filePath.substring(filePath.lastIndexOf("."));
}
File nf = new File(newFilePath);
try {
// 修改文件名
f.renameTo(nf);
} catch (Exception err) {
err.printStackTrace();
return null;
}
return newFilePath;
}
}
在桌面放了两个txt文件,a.txt中存储的是下载页的HTML代码片段(包含段落号与下载到本地的文件名),b.txt中存储的是视频播放页的HTML代码(包含视频正确名称与段落号)。
在下载页面通过F12查看页面代码,然后选中右侧播放列表名称,如图:
右键选中,Copy==>Copy element,然后复制到b.txt即可。
下载链接处理类似:
复制保存后的txt文本如下:
a.txt:
b.txt:
其中a.txt需要一个换行处理,在notpad++中使用替换即可:
换行之后的a.txt如下图:
准备好两个txt文件之后即可运行程序。
执行之后结果如下:
注:Java代码只是一个随手写的小工具,仅供参考