《高阶前端指北》之JavaScript爬虫速成-视频下载(第四弹)

视频存储

当前各大视频厂商都在升级视频存储架构,对于多数开发者来说,爬视频不像以前那么容易Get了。视频常规的存储方式有两种:

云端加密

阿里云和腾讯云都提供了对应的加密模式,甚至还提供了管道流的处理任务。你可以将录制好的视频上传到云端,云端可以实现:清晰,压缩,切割为更易保存的ts文件,加密等服务。

以阿里云加密为例,此类加密最难破解,每个文件都有独立的加密钥匙,通过子账号+播放凭证管理权限,并且它的key存储在内存中。

m3u8

通过此种方式可以存储ts片段,分段下载,每个ts都拥有同一个解密key。此类加密方式破解相对容易一些,曲折点在于寻找m3u8的地址,然后通过视频处理工具ffmpeg下载并合并即可。

视频商转码技术

类似爱奇艺,优酷这些视频商,为了稳住饭碗,一般会通过转码方式加密。设计特定的格式和密钥技术,阻止破解。并且只有通过特定的客户端才能解密和解码视频。 非重点,不多说。

视频破解

我们以常见的m3u8的加密为例,刨析其核心技术点。通过观察m3u8文件,我们可以看到它存储了每个ts的文件名称,通过目标地址拼接就可以下载。

有很多直接解析m3u8的在线网站,甚至你在夜晚看的Video也是这样的地址。

你以为如此简单就太小看视频的攻防战了,多数情况下你看到的是这样的文件内容

这是因为他们对ts文件做了加密,需要在m3u8和JS代码中找到解密的key和方法。具体的需要根据每个站点不同来寻找。有兴趣可以看我之前基于python开发的Lagou爬虫库,不过目前他们也升级了加密算法。

解析m3u8

const fs= require("fs");
var source = fs.readFileSync("aslkdas.m3u8","utf-8"); //读取 m3u8
var arr= source.split("
");
arr = arr.filter((item)=>{
	return item.match(/.ts$/);
}); 

down.js

const request = require("request");
const fs= require("fs");
const path= require("path");
const child_process = require('child_process');
const fsextra = require('fs-extra');

module.exports = function(opt){
	opt = opt || {};
	var arr = opt.arr || []; //所有 ts的文件名或者地址
	var host = opt.host || ""; //下载 ts 的 域名,如果 arr 里面的元素已经包含,可以不传
	var outputName = opt.name ||`output${(new Date()).getTime()}.mp4`; //导出视频的名称
	
	const tsFile = path.join(__dirname,`./source/${arr[0].split(".")[0]}`,);
	createDir(tsFile);//递归创建文件
	console.log("本次资源临时文件:",tsFile);
	
	const resultDir = path.join(__dirname,"./result");
	createDir(resultDir);//递归创建文件
	const resultFile = path.join(resultDir,outputName);
	
	var localPath = [] ; //下载到本地的路径
	//开始下载ts文件
	load();
	function load(){
		if(arr.length > 0){
			var u =arr.shift();
			var url = host + u;
			console.log("progress---:",url);
			down(url);
		}else{
			//下载完成
			console.log("下载完成--开始生成配置");
			localPath.unshift("ffconcat version 1.0");
			try{
				fs.writeFileSync(path.join(tsFile,"./input.txt"), localPath.join("
") , undefined, 'utf-8')
			}catch(e){
				console.log("写入配置出错--",e);
				return ;
			}
			
			//开始依赖配置合成
			console.log("开始合成-----");
			child_process.exec(`cd ${tsFile} &&ffmpeg -i input.txt -acodec copy -vcodec copy -absf aac_adtstoasc ${resultFile}`,function(error, stdout, stderr){
				if(error){
					console.error("合成失败---",error);
				}else{
					console.log("合成成功--",stdout);
					//删除临时文件
					fsextra.remove(tsFile, err => {
					if (err) return console.error("删除文件是失败",err)
					console.log('删除文件成功!')
					});
				}
			});
		}
	}
	
	//下载 ts 文件
	function down(url){
		var p = url.split("?")[0];
		var nm = path.parse(p);
		var nme = nm["name"] + nm["ext"];
		rpath = path.join(tsFile,nme);
		
		localPath.push(`file ${nme}`); //缓存本地路径,用来合成
		
		request({
		url:url,
		headers:{
		'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
		'X-Requested-With': 'XMLHttpRequest'
		}
		},function (err, response, body) {
	if (!err && response.statusCode == 200) {
				load();
	}else{
				console.log("错误",err)
			}
	}).pipe(fs.createWriteStream(rpath));
	}
	
	

	//递归的创建文件夹
	function mkdirs(dirpath) {
	if (!fs.existsSync(path.dirname(dirpath))) {
	mkdirs(path.dirname(dirpath));
	}
	fs.mkdirSync(dirpath);
	}
	 
	function createDir(myPath){
	fs.existsSync(myPath) == false && mkdirs(myPath);
	}
}

// ffmpeg -i input.txt -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4 

最后我们调用即可。

总结

本节课有些含蓄,毕竟学习为主,很多地方只能看破不说破,毕竟各位小可爱都是搞研发的。只要知其一便能破其百,对于研发来说语言只是一个工具而已。

下节课,我会开发一个基于js的爬虫脚手架,便于各位同学学习和研究爬虫原理。

如果喜欢我的文章,麻烦点个赞评个论收个藏关个注

手绘图,手打字,纯原创,摘自未发布的书籍:《高阶前端指北》,转载请获得本人同意。

最后,为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值