How to use Nodejs to download the video of station B with one click

How to download video from station B with one click

In order to easily download the video of station B, I wrote a small tool with Nodejs, and I used ibilithis library to download at the beginning, but because of the problem of not being able to customize the download directory, it was inconvenient to modify, so I built a wheel.

Warehouse address , welcome star.

Features

  • Download individual works based on URL
  • Download all works according to the homepage URL of the UP master
  • Option to download video or audio

Environmental requirements

Node and npm are required to use this tool. If you don't have it, you can go to the official website to download and install it.

use

Install:

npm i bilibili-save-nodejs
复制代码

Using command line tools

bili-download
复制代码

Choose what and how to download based on the command line menu

Entrainment of private goods: one-click star chase, download all videos of Jiu San :

bili-download -d
复制代码

Using the Node.js API

Function name effect
download download
downloadByVedioPath Download a single work based on the video URL
downloadByHomePath Download all works according to the UP homepage

API parameters

Note: The parameters of the three functions are in the form of objects.

download

parameter name Is it necessary Ranges meaning
downloadRange Yes ['byAuthor','byVedio'] According to author homepage URL or work URL
downloadType Yes ['mp4','mp3'] Download video or audio
downloadPath Yes none Legal work URL or UP home page URL
downloadFolder no none The full path to the storage directory , the default value is used by default

Directory defaults:

  • /videoVideo: In a folder under the root directory
  • /audioAudio: in a folder under the root directory

demo:

const { download } = require("bilibili-download-nodejs");
download({
  downloadRange: "byAuthor",
  downloadType: "mp4",
  downloadPath: "https://space.bilibili.com/313580179",
})
  .then(() => console.log("下载成功"))
  .catch((e) => console.log("下载出错"));
复制代码

downloadByVedioPath & downloadByHomePath

参数名 是否必须 取值范围 含义
type ['mp4','mp3'] 下载视频音频
url 合法的作品 URL
folder 存储目录的完整路径

demo:

const { downloadByVedioPath, downloadByHomePath } = require("./download.js");
const path = require("path");

// 下载单个作品的视频
downloadByVedioPath({
  url: "https://www.bilibili.com/video/BV1AL4y1L7cg",
  type: "mp4",
  folder: path.join(__dirname, "/foo"),
})
  .then(() => console.log("下载成功"))
  .catch((e) => console.log("下载出错"));

// 下载UP主所有作品的音频
downloadByHomePath({
  url: "https://space.bilibili.com/313580179",
  type: "mp3",
  folder: path.join(__dirname, "/bar"),
})
  .then(() => console.log("下载成功"))
  .catch((e) => console.log("下载出错"));
复制代码

原理介绍

介绍完用法,简单介绍本项目的原理。

根据视频 URL 下载视频

根据 URL 获取 bvid

bvid 是现在 b 站视频的唯一标识,也是后续操作的必备参数。但为了方便使用,直接复制作品的 URL 更好理解和操作。

其实 bvid 就存在于 URL 之中,只需要做简单的字符串操作:

const urlList = url.split("/");
const bvid = urlList[urlList.length - 1].split("?")[0];
复制代码

根据 bvid 获取 cid 数组与作品标题

对于多 p 视频,仅通过 bvid 无法确定请求的是哪一 p 视频,此时 cid 起到了唯一标识视频的作用。通过浏览器抓包分析接口,可知获取 cid 的方法为:

const getCidByBvid = async (bvid) => {
  const res = await axios.get("https://api.bilibili.com/x/web-interface/view", {
    params: {
      bvid,
    },
  });
  return res.data.data.pages.map((item) => item.cid);
};
复制代码

该接口用于查询作品信息,因此获取作品标题的方法为:

const getTitleByBvid = async (bvid) => {
  const res = await axios.get("https://api.bilibili.com/x/web-interface/view", {
    params: {
      bvid,
    },
  });
  return res.data.data.title;
};
复制代码

根据 bvid 获取视频下载地址数组

  1. 首先,根据 bvid 获取 cid 数组
  2. 对于每个 cid,与 bvid 一起唯一标识了视频,进行请求
  3. 根据下载类型的不同(视频或音频),传入参数会不同。

参数含义:

  • fnval设为 16 时,音视频将会分离,此时可以达到只下载音频的目的
  • qn参数标识清晰度,对照如下
清晰度 字段取值
4K 120
1080p+ 112
1080p 80
720p 64
480p 32
360p 16

完整实现代码为:

const getDownloadPathById = async (bvid, type) => {
  const cidList = await getCidByBvid(bvid);
  const result = [];
  for (const cid of cidList) {
    const params = {
      bvid,
      cid,
      qn: 112,
    };
    if (type === "mp3") {
      params.fnval = 16;
    }
    const res = await axios.get("https://api.bilibili.com/x/player/playurl", {
      params,
    });
    result.push(
      type === "mp3"
        ? res.data.data.dash.audio[0].baseUrl
        : res.data.data.durl[0].url
    );
  }
  return result;
};
复制代码

根据下载地址下载资源

getDownloadPathById返回的是下载地址,但直接在浏览器打开会报错,这是因为 request header 必须带有 referer 字段。

通过抓包可知, referer 字段取值就是视频地址,因此:

const getRefererByBvid = (bvid) => `https://www.bilibili.com/video/${bvid}`;
复制代码

下载资源的思路是:

  • 检查目标文件是否存在,若存在不重复下载
  • 根据 bvid 获取 referer 字段
  • 请求资源
  • 写入文件

完整实现:

const downloadResource = async ({ url, referer, folder, title, type }) => {
  const target = path.join(folder, `${title}.${type}`);
  if (fs.existsSync(target)) {
    console.log(`视频 ${title} 已存在`);
    return Promise.resolve();
  }
  const res = await axios.get(url, {
    headers: {
      referer,
    },
    responseType: "stream",
  });
  console.log(`开始下载:${title}.${type}`);
  const writer = fs.createWriteStream(target);
  res.data.pipe(writer);
  return new Promise((resolve, reject) => {
    writer.on("finish", resolve);
    writer.on("error", reject);
  });
};
复制代码

Download video according to UP homepage URL

Get mid from UP homepage URL

mid is the unique identifier of each B station user. Also for the convenience of understanding and use, the exposed interface uses the UP home page URL, and performs string processing to obtain the mid:

const getMidByUrl = (url) => {
  const reg = /space.bilibili.com\/(?<mid>\d+)/;
  return url.match(reg).groups?.mid;
};
复制代码

Get the video homepage address according to the up main mid

According to the packet capture, three parameters are required to obtain homepage information:

  • mid: account ID
  • ps: number of videos per page
  • pn: current page number

Using the default number of 30 per page, the operation to get the home page can be written as:

const getHomeUrl = (mid, currentPage) =>
  `https://api.bilibili.com/x/space/arc/search?mid=${mid}&ps=30&pn=${currentPage}`;
复制代码

By capturing and analyzing the returned data, the returned result is data.list.vlistthe video information, in which bvid can be obtained, and the subsequent download process is the same as above.

refer to

Guess you like

Origin juejin.im/post/7087973085097230349