Java爬取哔哩哔哩视频(可视化)

链接:我的讲解视频https://www.bilibili.com/video/BV14e411Q7oG/
本文仅供学术用途

先上图

在这里插入图片描述

代码

爬虫核心

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.gargoylesoftware.htmlunit.*;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.Executor;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Spider {
    public void catchvideo(String url,String addr) throws IOException {
        //TODO 建立无头浏览器
        WebClient webClient = new WebClient();
        webClient.getOptions().setJavaScriptEnabled(false);
        webClient.getOptions().setCssEnabled(false);
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(true);
        webClient.getOptions().setThrowExceptionOnScriptError(true);
        webClient.addRequestHeader("Referer", "https://www.bilibili.com/index.html");
        webClient.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.40");
        //TODO 设置请求参数,建立请求
        WebRequest webRequest = new WebRequest(new URL(url), HttpMethod.GET);

        //TODO 获取响应体
        Page page = webClient.getPage(webRequest);
        WebResponse webResponse = page.getWebResponse();
        String contentAsString = webResponse.getContentAsString();
//        System.out.println(contentAsString);

        //TODO 模式匹配找视频总数
        Pattern pattern = Pattern.compile("<script>window.__INITIAL_STATE__=(.*?);\\(function\\(\\)");
        Matcher matcher = pattern.matcher(contentAsString);
        String s = null;
        if (matcher.find())
            s = matcher.group(1);
        JSONObject jsonObject = JSON.parseObject(s);
        int videonum = jsonObject.getJSONObject("videoData").getIntValue("videos");
//        System.out.println("视频总数" + videonum);

        //TODO 获取目录名
        pattern = Pattern.compile("<meta data-vue-meta=\"true\" property=\"og:title\" content=\"(.*?)_哔哩哔哩_bilibili\">");
        matcher = pattern.matcher(contentAsString);
        String s1 = null;
        if (matcher.find())
            s1 = matcher.group(1);
        else
            System.out.println("没有找到");
        //目录名去除./&*这些字符
        String content = s1.replaceAll("[/&*_,《》\\s+]", "");
//        System.out.println("目录名" + content);

        //TODO 建立目录
        String dir = addr+"\\" + content + "\\";
        File directory = new File(dir);
        if (!directory.exists())
            directory.mkdirs();

        for (int i = 1; i <= videonum; i++) {
            //TODO 设置请求参数,建立请求
            webRequest = new WebRequest(new URL(url + "?p=" + i), HttpMethod.GET);
//            System.out.println(webRequest);
            //TODO 获取响应体
            page = webClient.getPage(webRequest);
            webResponse = page.getWebResponse();
            contentAsString = webResponse.getContentAsString();
            //TODO 获取视频链接
            pattern = Pattern.compile("<script>window.__playinfo__=(.*?)</script>");
            matcher = pattern.matcher(contentAsString);
            String s2 = null;
            if (matcher.find())
                s2 = matcher.group(1);
            else
                System.out.println("没有找到");
            String videolink = JSON.parseObject(s2).getJSONObject("data").getJSONObject("dash").getJSONArray("video").getJSONObject(0).getString("baseUrl");
            String audiolink = JSON.parseObject(s2).getJSONObject("data").getJSONObject("dash").getJSONArray("audio").getJSONObject(0).getString("baseUrl");
//            System.out.println("视频下载链接\n" + videolink);
//            System.out.println("音频下载链接\n" + audiolink);

            //TODO 获取视频名称
            pattern = Pattern.compile("<title data-vue-meta=\"true\">(.*?)_哔哩哔哩_bilibili</title>");
            matcher = pattern.matcher(contentAsString);
            String s3 = null;
            if (matcher.find())
                s3 = matcher.group(1);
            else
                System.out.println("没有找到");
            //目录名去除./&*这些字符
            String videoname = s3.replaceAll("[/&*_,《》\\s+]", "");
            System.out.println(i + "_________________________" + videoname);
            String videofile = dir + "tmp_" + videoname + ".mp4";
            String audiofile = dir + "tmp_" + videoname + ".mp3";

            //TODO 下载视频
            webRequest = new WebRequest(new URL(videolink), HttpMethod.GET);
            page = webClient.getPage(webRequest);
            webResponse = page.getWebResponse();
            InputStream inputStream = webResponse.getContentAsStream();
            OutputStream outputStream = new FileOutputStream(videofile);
            IOUtils.copy(inputStream, outputStream);
            inputStream.close();
            outputStream.close();


            //TODO 下载音频
            webRequest = new WebRequest(new URL(audiolink), HttpMethod.GET);
            page = webClient.getPage(webRequest);
            webResponse = page.getWebResponse();
            inputStream = webResponse.getContentAsStream();

            outputStream = new FileOutputStream(audiofile);
            IOUtils.copy(inputStream, outputStream);
            inputStream.close();
            outputStream.close();

            //TODO 执行合并命令

            // 创建命令行
            CommandLine commandLine = CommandLine.parse("ffmpeg -i " + videofile + " -i " + audiofile + " -c:v copy -c:a aac -strict experimental " + dir + i + "_" + videoname + ".mp4"); // 使用 Windows cmd 命令作为示例
            // 创建执行器
            Executor executor = new DefaultExecutor();
            // 设置输出流处理器(可选)
            PumpStreamHandler streamHandler = new PumpStreamHandler(System.out, System.err); // 将标准输出和错误输出重定向到控制台
            executor.setStreamHandler(streamHandler);
            // 执行命令
//            System.out.println(commandLine);
            executor.execute(commandLine);
//            int exitValue = executor.execute(commandLine); // 执行命令并获取退出值
//            System.out.println("Exit value: " + exitValue); // 打印退出值(通常为0表示成功)

            File file = new File(audiofile);
            file.delete();

            file = new File(videofile);
            file.delete();
        }
    }
}

可视化代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

public class SwingDemo {
    public static void main(String[] args) {
        JFrame jFrame = new JFrame("Swing frame");
        //设置关闭退出程序
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new JPanel();
        jFrame.setContentPane(panel);
        jFrame.setLocationRelativeTo(null);
        panel.setLayout(new FlowLayout());

        JLabel jLabel = new JLabel("下载地址");
        JTextField jTextField = new JTextField(20);
        jTextField.setToolTipText("下载地址");
        JButton download = new JButton("下载");

        panel.add(jLabel);
        panel.add(jTextField);
        panel.add(download);


        JLabel jLabel1 = new JLabel("文件保存位置");
        JTextField jTextField1 = new JTextField(20);
        jTextField1.setText("D:\\videos\\");
        jTextField1.setToolTipText("文件保存位置");
        JButton fileaddr = new JButton("选择文件夹");

        panel.add(jLabel1);
        panel.add(jTextField1);
        panel.add(fileaddr);

        fileaddr.addActionListener(e -> {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int returnValue = fileChooser.showOpenDialog(null);
            if (returnValue == JFileChooser.APPROVE_OPTION) {
                File selectedFile = fileChooser.getSelectedFile();
                jTextField1.setText(selectedFile.getAbsolutePath());
            }
        });

        download.addActionListener(e -> {
            String url = jTextField.getText()+"/";
            String fileAddr = jTextField1.getText();
            System.out.println(url);
            System.out.println(fileAddr);
            try {
                Spider spider = new Spider();
                spider.catchvideo(url,fileAddr);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        });

        //自适应
        jFrame.pack();
        jFrame.setVisible(true);

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/152597.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系列二十六、idea安装javap -c

一、概述 javap -c是一个能够将.java文件反编译为.class文件的指令&#xff0c;例如我在idea中编写了一个Car.java文件&#xff0c;我想看看这个类被编译后长什么样的&#xff0c;就可以使用该指令进行查看。 二、配置 2.1、 Java Bytecode Decompiler File>Settings>Pl…

大数据分析与应用实验任务八

大数据分析与应用实验任务八 实验目的 进一步熟悉pyspark程序运行方式&#xff1b;熟练掌握pysaprk RDD基本操作相关的方法、函数。 实验任务 进入pyspark实验环境&#xff0c;在图形界面的pyspark命令行窗口中完成下列任务&#xff1a; 在实验环境中自行选择路径新建以自…

非对口专业测试人,婉拒猎头、放弃6份高薪offer,你敢信?

从非对口的国贸专业&#xff0c;步入测试之路&#xff1b;从红色旅游小城湘潭&#xff0c;迈入国际化都市上海。“明确方向-及时实践-谨慎选择-踏实扎根-计划未来”。她的每一步&#xff0c;都走得格外坚定有力......话不多说&#xff0c;让我们一起来看看这位小姐姐的成长故事…

PyTorch:张量与矩阵

PyTorch 是一个基于 Python 的科学计算包&#xff0c;专门针对深度学习研究&#xff0c;提供了丰富的工具和库。在 PyTorch 中&#xff0c;张量&#xff08;tensor&#xff09;是深度学习的核心数据结构&#xff0c;它可以看作是可以进行自动微分的多维数组。张量不仅可以代表标…

DSVPN简介

定义 动态智能VPN&#xff08;Dynamic Smart Virtual Private Network&#xff09;&#xff0c;简称DSVPN&#xff0c;是一种在Hub-Spoke组网方式下为公网地址动态变化的分支之间建立VPN隧道的解决方案。 目的 越来越多的企业希望建立Hub-Spoke方式的IPSec VPN网络将企业总部…

Linux学习第42天:Linux RS232/485/GPS 驱动实验:天外来客

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 Linux的学习笔记今天更新到了第42天。鉴于国往笔记内容整理中出现的问题&#xff0c;我尽量按照平时学习时笔记的要求进行优化。尽量不再大段大段的贴代码。而是…

解决Tomcat中文乱码

cmd乱码如图&#xff1a; idea中运行Tomcat控制台出现乱码&#xff1a; 解决办法&#xff1a; 找到两个idea的vmoptions配置文件&#xff0c;在文件中追加-Dfile.encodingUTF-8 -Dfile.encodingUTF-8保存退出。 重启idea重新运行Tomcat&#xff1a; maven、tomcat 超级详…

什么是 SSL?SSL/TLS是如何工作的?HTTP和HTTPS有什么区别?

SSL 代表安全套接字层&#xff0c;是指用于加密、保护和验证互联网上之通信的协议。尽管 SSL 在一段时间前已被称为 TLS&#xff08;传输层安全性&#xff09;的更新协议代替&#xff0c;但“SSL”仍是该技术的常用术语。 SSL/TLS 的主要用例是保护客户端和服务器之间的通信安…

解决requests库中session.verify参数失效的问题

在使用requests库进行HTTP请求时&#xff0c;如果在环境变量中设置了’REQUESTS_CA_BUNDLE’&#xff0c;并且在session对象中设置了verify参数为False&#xff0c;那么API请求会使用环境变量中的值而不是session对象中的值。这是因为在requests库中&#xff0c;当session对象中…

Find My婴儿车|苹果Find My技术与婴儿车结合,智能防丢,全球定位

婴儿车是一种为婴儿户外活动提供便利而设计的工具车&#xff0c;是宝宝最喜爱的散步交通工具&#xff0c;更是妈妈带宝宝上街购物时的必须品。随着现在三胎的放开&#xff0c;婴儿车市场已经迎来上升的趋势。 在智能化加持下&#xff0c;防丢功能的加入使得人们日益关心物品的…

深度学习YOLO图像视频足球和人体检测 - python opencv 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov5算法5 数据集6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习YOLO图像视频足球和人体检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非…

TEMU要求提交RSL Report 铅镉RSL邻苯项目化学物质检测报告

TEMU要求提交RSL Report 铅镉RSL邻苯项目化学物质检测报告 如果您在亚马逊上销售商品&#xff0c;则必须遵守所有适用的欧盟和地方法律法规&#xff0c;以及适用于这些商品和商品信息的亚马逊政策。要在亚马逊上销售某些商品&#xff0c;( xxdu2016 )您需要向我们提供 REACH 符…

mybatis-plus3.5.3.1 支持不同数据源sql适配

mybatis-plus3.5.3.1 支持不同数据源sql适配 背景 最近公司要求支持国产数据库达梦&#xff0c;人大金仓&#xff0c;高斯等数据库&#xff0c;这些数据库与mysql的语法有一些差异&#xff0c;需要做一些兼容操作。 解决问题 1.不同数据库分页不同 2.支持通过参数控制执行…

Spi机制的必要性

SpringBoot 为啥单独加载类路径下spring.factories文件中的类&#xff1f; SpringBoot 应用运行过程中存在两种类型的类初始化&#xff1a;一部分为已经提前装载到IOC容器中的bean&#xff0c;另一部分则为实时new的bean。 IOC容器中的bean包含&#xff1a;启动类所在包路径下…

Docker的3主3从redis集群配置(扩容和缩容配置)

3主3从redis集群配置 1、关闭防火墙启动docker后台服务 systemctl start docker2、新建6个docker容器redis实例 docker run -d --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly …

基于Vue+SpringBoot的城市桥梁道路管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥梁4.2 新增城市桥梁4.3 编辑城市桥梁4.4 删除城市桥梁4.5 查询单个城市桥梁 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的城市桥梁道路管理系统&#xff0c;支持…

小型机房380V断电报警门磁开关状态检测远程控制RTU

在现代社会中&#xff0c;小型机房起到了至关重要的作用&#xff0c;为各种系统和设备提供稳定的电力供应。然而&#xff0c;由于各种原因&#xff0c;如供电故障、设备故障或非法侵入等&#xff0c;机房的正常运行可能会受到威胁。为了保障机房的安全和可靠性&#xff0c;我们…

了解七大经典排序算法,看这一篇就足够了!!!

✏️✏️✏️好&#xff0c;那么今天给大家分享一下七大经典排序算法&#xff01; 清风的CSDN博客 &#x1f61b;&#x1f61b;&#x1f61b;希望我的文章能对你有所帮助&#xff0c;有不足的地方还请各位看官多多指教&#xff0c;大家一起学习交流&#xff01; 动动你们发财的…

java Could not resolve placeholder

1、参考&#xff1a;https://blog.csdn.net/yu1812531/article/details/123466616 2、配置文件: 3、在application.properties中设置要使用的配置文件

最简单的测试Jquery-jquery是否正常工作的代码

01-运行后在页面上显示“jQuery is working!” 代码如下&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>it is title</title><meta name"viewport" content"widthdevice-width,in…