效果
代码
BilibiliVideoDurationCrawler
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BilibiliVideoDurationCrawler {
private static final Pattern VIDEO_PART_PATTERN = Pattern.compile("\"part\":\"(.*?)\",\"duration\":(\\d+),");
public static void main(String[] args) {
String url = "https://www.bilibili.com/video/BV1834y1676P/";
List<VideoPart> videoParts = new ArrayList<>();
try {
videoParts = getVideoPartsFromUrl(url);
} catch (IOException | ParseException e) {
System.err.println("获取视频信息失败:" + e.getMessage());
return;
}
if (!videoParts.isEmpty()) {
for (int i = 0; i < videoParts.size(); i++) {
String progress = getProgressStr(videoParts, i);
System.out.println("p" + (i + 1) + " " + videoParts.get(i).getPart() + " " + progress);
}
}
}
public static List<VideoPart> getVideoPartsFromUrl(String url) throws IOException, ParseException {
Document doc = Jsoup.connect(url).userAgent("Mozilla/5.0").get();
Elements elements = doc.select("script");
List<String> result = new ArrayList<>();
for (Element element : elements) {
Matcher matcher = VIDEO_PART_PATTERN.matcher(element.html());
while (matcher.find()) {
result.add("Part: " + matcher.group(1) + ", Duration: " + matcher.group(2));
}
}
List<VideoPart> videoParts = new ArrayList<>();
long totalDuration = 0;
for (String str : result) {
String[] parts = str.split(", ");
String part = parts[0].split(": ")[1];
long duration = Long.parseLong(parts[1].split(": ")[1]);
totalDuration += duration;
VideoPart videoPart = new VideoPart(part, duration);
videoParts.add(videoPart);
}
VideoPart.setTotalDuration(totalDuration);
return videoParts;
}
public static String getProgressStr(List<VideoPart> videoParts, int p) {
if (videoParts == null || p < 0 || p >= videoParts.size()) {
throw new IllegalArgumentException("Invalid video parts or index p");
}
long totalLength = VideoPart.getTotalDuration();
long lengthBeforeP = 0;
for (int i = 0; i <= p; i++) {
lengthBeforeP += videoParts.get(i).getDuration();
}
double progress = (double) lengthBeforeP / (totalLength == 0 ? 1 : totalLength) * 100;
return String.format("%.2f%%", progress);
}
}
VideoPart
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Date;
@Data
@AllArgsConstructor
public class VideoPart {
public VideoPart(String part,long duration){
this.part = part;
this.duration = duration;
}
public static void setTotalDuration(long totalDuration) {
VideoPart.totalDuration = totalDuration;
}
public static long getTotalDuration() {
return totalDuration;
}
public void Duration2NeedTime(){
this.needTime = new Date(duration*1000);
}
private String part;
private long duration;
private Date needTime;
private double progress;
private static long totalDuration =-1;
}