UNPKG

bk

Version:

Download bilibili videos;B站视频下载;支持新版BV号;支持分P及一键多P下载;支持多质量选择;

140 lines (124 loc) 4.13 kB
const ktool = require('ktool'); const progress = require('progress-stream'); const ProgressBar = require('./progress-bar'); const outVideo = require('./outVideo'); const url = require('url'); const http = require('http'); const https = require('https'); let myCookie = ''; const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:56.0) Gecko/20100101 Firefox/56.0'; const apiUrlA = 'https://api.bilibili.com/x/web-interface/view?'; const apiUrlB = 'https://api.bilibili.com/x/player/playurl?'; // const apiUrlB = 'https://api.bilibili.com/x/player/wbi/playurl?'; const getVideoInfo = async function(bvid) { // console.log('myCookie:',myCookie); const infoStr = '' + await ktool.promi(ktool.httpGet)(apiUrlA + 'bvid=' + bvid, { 'headers': { 'User-Agent': UA, 'Cookie': myCookie } }); const info = JSON.parse(infoStr); // console.log('getVideoInfo:%j',info); if (info.data) { return info.data; } console.error('无video数据:%j',info); return null; }; const getDownloadInfo = async function(bvid, cid, qualityNum) { // console.log('myCookie:',myCookie); const infoStr = '' + await ktool.promi(ktool.httpGet)(apiUrlB + `bvid=${bvid}&cid=${cid}&qn=${qualityNum}&otype=json`, { 'headers': { 'User-Agent': UA, 'Cookie': myCookie } }); const info = JSON.parse(infoStr); if (info.data) { return info.data; } console.error('无download数据:%j',info); return null; }; const httpGet = function(uri, bvid, filename, str, writeStream, reject) { // console.log('uri:---->', uri); const opts2 = url.parse(uri); opts2.headers = { 'User-Agent': UA, 'Accept': '*/*', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate, br', 'Range': 'bytes=0-', // 'Content-Type': 'application/octet-stream', 'Referer': 'https://www.bilibili.com/video/' + bvid + '/', 'Origin': 'https://www.bilibili.com', 'Connection': 'keep-alive' }; const httpWraper = (uri.startsWith('https')) ? https : http; httpWraper.get(opts2, function(res2) { if (res2.statusCode === 302) { // console.log('headers:%j', res2.headers); const u2 = res2.headers.location; console.log('302:---->get again'); res2.destroy(); httpGet(u2, bvid, filename, str, writeStream, reject); return; } if (res2.statusCode !== 200 && res2.statusCode !== 206) { //206是正常状态 console.error('http get statusCode is ' + res2.statusCode); console.log('headers:%j', res2.headers); res2.destroy(); reject(new Error('statusCode')); return; } // console.log('======> will pipe, statusCode:', res2.statusCode); res2.pipe(str).pipe(writeStream); // res2.on('data', function(chunk) { // bodyBuf = Buffer.concat([bodyBuf, chunk]); // }); res2.on('end', function() { }); }).on('error', function(e) { if (e.code !== 'HPE_INVALID_CONSTANT') { //此异常可忽略 console.error('onEEEEE', e); reject(e); } }); }; function downloadFile(bvid, totalSize, totalTime, uri, filename) { return new Promise(function(resolve, reject) { // console.log('downloadFile: uri:'+uri+',filename:'+filename,bvid,totalSize,totalTime); const pb = new ProgressBar('下载进度', 50); const str = progress({ time: 1000 }); str.on('progress', function(progress) { pb.render({ completed: progress.transferred ? progress.transferred : 0, total: totalSize }); }); const writeStream = outVideo.createOutWriteStream(filename); httpGet(uri, bvid, filename, str, writeStream, reject); writeStream.on('finish', function(err) { if (err) { return reject(err); } writeStream.end(); console.log('\n下载完成:' + filename); resolve({ name: filename, time: totalTime }); }); }); } const setCookie = function(newCookie) { myCookie = newCookie; }; exports.getVideoInfo = getVideoInfo; exports.getDownloadInfo = getDownloadInfo; exports.downloadFile = downloadFile; exports.setCookie = setCookie; //