爬取B站视频 - m4s与flv文件的那些事

参考链接

爬取B站视频

目录

1. 前言说明
2. 自动化分析
3. 爬取单个视频
4. 批量爬取视频
5. 总结

一、前言说明
  1. 前言
    每次查找资料和研究总是能够发现一些新鲜事【奈何我懂得太少】。这次因为相关的自动化爬虫的原因,继续研究了一下 B 站的 m4s 文件,果然发现了一些有用的东西。不过,这次博文主要目的是,为了记录整个资料查找和研究的过程,算是一个思考过程吧。【写自动化爬虫不太在行,也没有这个需求,而且工具好像也有一大推 emmmm…】。

  2. 额外的说明
    因为之前已经写过两篇文章,一篇是 爬取B站的flv视频,另一个是 爬取 m4s 的视频。这里就有一个问题,既然 B 站从 flv 改到了 m4s,那么分界点在哪里。因为可能有人会认为 B 站传来的视频全部改为 m4s 短视频流格式,其实不然,事实上大概是以某个时间点为界【当然也可以打我的脸】,两边分隔为 flv 和 m4s 的对立派。
    所以,采用二分法,目的是找到分隔点。
    av: 3050442920180827数据分析
    在这里插入图片描述
    在这里插入图片描述
    av: 30504430【iKON】「自存」那些有艺术感的video
    在这里插入图片描述
    在这里插入图片描述
    时间点确定为,2018-08-28
    在这里插入图片描述
    原来,我以为这是一个分隔点,但是后续的 av30504450 又是 flv 文件,所以勉强地认为这个分隔点上下浮动有一定范围,可能是一个衔接的过程。所以,大致在这个视频以前的投稿视频,姑且可以认为是 flv 视频,之后是 m4s 视频。

下面是正文部分

二、自动化分析

测试视频av66476652
在这里插入图片描述

  1. 依旧打开 F12,重新刷新,并找到指定数据包
    在这里插入图片描述
    既然我们的目标是实现自动化爬取 B 站的视频,那么如何获取 URL 是一个关键,而不是打开网页后抓包之后得到指定数据包后下载视频,这两者还是有区别的。
    以下是此数据包的 URL 链接:
    https://cn-zjwz3-dx-v-11.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30080.m4s?expires=1567849800&platform=pc&ssig=Fp1CahgHwsUBCEd45Yo5-Q&oi=2085381866&trid=4d431eaebd8e4536a416728143ba73ebu&nfc=1&nfb=maPYqpoel5MI3qOUX6YpRA==&mid=100938015

  2. 查看 m4s 文件的 URL 请求时提交的参数
    在这里插入图片描述
    从中,我们最多也只能知道 expire 代表了时间戳,platform 代表 pc 主机,mid 号应该是自己的 UID 号,但是其它的我们都不知道。

  3. 尝试搜索这些未知数据,找到了一个有用的数据包
    在这里插入图片描述
    在这里插入图片描述

  4. 格式化 Json 数据,并进一步分析这个数据包
    好像里面就有我们需要的 m4s 的链接,假如解决了 Json 数据包 URL 的获取问题,那么这个问题不就解决了么。

{
	"code": 0,
	"message": "0",
	"ttl": 1,
	"data": {
		"from": "local",
		"result": "suee",
		"message": "",
		"quality": 80,
		"format": "flv",
		"timelength": 229291,
		"accept_format": "hdflv2,flv,flv720,flv480,flv360",
		"accept_description": ["高清 1080P+", "高清 1080P", "高清 720P", "清晰 480P", "流畅 360P"],
		"accept_quality": [112, 80, 64, 32, 16],
		"video_codecid": 7,
		"seek_param": "start",
		"seek_type": "offset",
		"dash": {
			"duration": 230,
			"minBufferTime": 1.5,
			"min_buffer_time": 1.5,
			"video": [{
				"id": 80,
				"baseUrl": "http://cn-zjwz3-dx-v-11.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30080.m4s?expires=1567850700\u0026platform=pc\u0026ssig=S3R6tNYzukQZ6D4M3w-k8g\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"base_url": "http://cn-zjwz3-dx-v-11.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30080.m4s?expires=1567850700\u0026platform=pc\u0026ssig=S3R6tNYzukQZ6D4M3w-k8g\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"backupUrl": null,
				"backup_url": null,
				"bandwidth": 1447135,
				"mimeType": "video/mp4",
				"mime_type": "video/mp4",
				"codecs": "avc1.640028",
				"width": 1920,
				"height": 1080,
				"frameRate": "16000/672",
				"frame_rate": "16000/672",
				"sar": "1:1",
				"startWithSap": 1,
				"start_with_sap": 1,
				"SegmentBase": {
					"Initialization": "0-975",
					"indexRange": "976-1559"
				},
				"segment_base": {
					"initialization": "0-975",
					"index_range": "976-1559"
				},
				"codecid": 7
			}, {
				"id": 64,
				"baseUrl": "http://cn-zjwz3-dx-v-01.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30064.m4s?expires=1567850700\u0026platform=pc\u0026ssig=DCgoPxhgaq52RqUXD07bcw\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"base_url": "http://cn-zjwz3-dx-v-01.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30064.m4s?expires=1567850700\u0026platform=pc\u0026ssig=DCgoPxhgaq52RqUXD07bcw\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"backupUrl": null,
				"backup_url": null,
				"bandwidth": 1009346,
				"mimeType": "video/mp4",
				"mime_type": "video/mp4",
				"codecs": "avc1.64001F",
				"width": 1280,
				"height": 720,
				"frameRate": "16000/672",
				"frame_rate": "16000/672",
				"sar": "1:1",
				"startWithSap": 1,
				"start_with_sap": 1,
				"SegmentBase": {
					"Initialization": "0-974",
					"indexRange": "975-1558"
				},
				"segment_base": {
					"initialization": "0-974",
					"index_range": "975-1558"
				},
				"codecid": 7
			}, {
				"id": 32,
				"baseUrl": "http://cn-zjwz3-dx-v-02.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30032.m4s?expires=1567850700\u0026platform=pc\u0026ssig=f9gUrOa8UYiUpNhRNCc89A\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"base_url": "http://cn-zjwz3-dx-v-02.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30032.m4s?expires=1567850700\u0026platform=pc\u0026ssig=f9gUrOa8UYiUpNhRNCc89A\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"backupUrl": null,
				"backup_url": null,
				"bandwidth": 630670,
				"mimeType": "video/mp4",
				"mime_type": "video/mp4",
				"codecs": "avc1.64001E",
				"width": 852,
				"height": 480,
				"frameRate": "16000/672",
				"frame_rate": "16000/672",
				"sar": "1:1",
				"startWithSap": 1,
				"start_with_sap": 1,
				"SegmentBase": {
					"Initialization": "0-974",
					"indexRange": "975-1558"
				},
				"segment_base": {
					"initialization": "0-974",
					"index_range": "975-1558"
				},
				"codecid": 7
			}, {
				"id": 16,
				"baseUrl": "http://cn-zjwz3-dx-v-11.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30015.m4s?expires=1567850700\u0026platform=pc\u0026ssig=yYHw-JZzw0EDglb2kCv3PQ\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"base_url": "http://cn-zjwz3-dx-v-11.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30015.m4s?expires=1567850700\u0026platform=pc\u0026ssig=yYHw-JZzw0EDglb2kCv3PQ\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"backupUrl": null,
				"backup_url": null,
				"bandwidth": 391335,
				"mimeType": "video/mp4",
				"mime_type": "video/mp4",
				"codecs": "avc1.64001E",
				"width": 640,
				"height": 360,
				"frameRate": "16000/672",
				"frame_rate": "16000/672",
				"sar": "1:1",
				"startWithSap": 1,
				"start_with_sap": 1,
				"SegmentBase": {
					"Initialization": "0-974",
					"indexRange": "975-1558"
				},
				"segment_base": {
					"initialization": "0-974",
					"index_range": "975-1558"
				},
				"codecid": 7
			}],
			"audio": [{
				"id": 30280,
				"baseUrl": "http://cn-zjwz3-dx-v-04.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30280.m4s?expires=1567850700\u0026platform=pc\u0026ssig=Meu6Rudcq5Yelyt__nKxKQ\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"base_url": "http://cn-zjwz3-dx-v-04.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30280.m4s?expires=1567850700\u0026platform=pc\u0026ssig=Meu6Rudcq5Yelyt__nKxKQ\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"backupUrl": null,
				"backup_url": null,
				"bandwidth": 319254,
				"mimeType": "audio/mp4",
				"mime_type": "audio/mp4",
				"codecs": "mp4a.40.2",
				"width": 0,
				"height": 0,
				"frameRate": "",
				"frame_rate": "",
				"sar": "",
				"startWithSap": 0,
				"start_with_sap": 0,
				"SegmentBase": {
					"Initialization": "0-919",
					"indexRange": "920-1503"
				},
				"segment_base": {
					"initialization": "0-919",
					"index_range": "920-1503"
				},
				"codecid": 0
			}, {
				"id": 30216,
				"baseUrl": "http://cn-zjwz3-dx-v-12.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30216.m4s?expires=1567850700\u0026platform=pc\u0026ssig=F_sQRRXyXKP_E1Og8Y0Kww\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"base_url": "http://cn-zjwz3-dx-v-12.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-30216.m4s?expires=1567850700\u0026platform=pc\u0026ssig=F_sQRRXyXKP_E1Og8Y0Kww\u0026oi=2085381866\u0026trid=8e7b80f4881c4966af032947f69736ceu\u0026nfc=1\u0026nfb=maPYqpoel5MI3qOUX6YpRA==\u0026mid=100938015",
				"backupUrl": null,
				"backup_url": null,
				"bandwidth": 67169,
				"mimeType": "audio/mp4",
				"mime_type": "audio/mp4",
				"codecs": "mp4a.40.2",
				"width": 0,
				"height": 0,
				"frameRate": "",
				"frame_rate": "",
				"sar": "",
				"startWithSap": 0,
				"start_with_sap": 0,
				"SegmentBase": {
					"Initialization": "0-919",
					"indexRange": "920-1503"
				},
				"segment_base": {
					"initialization": "0-919",
					"index_range": "920-1503"
				},
				"codecid": 0
			}]
		}
	}
}

不过事情还是没有我们想象的这么简单,这个 URL 拼接还是非常困难的。

  1. 尝试分析 Json 数据包的 URL 构成
    又是一堆不知道的参数,而且这些参数基本上缺一不可,从这个方法解决还是很困难的。这里的 avid 不等于 av【实力眼瞎】,cid 号倒是可以得出,其它有些控制参数就没办法正常推出。
    在这里插入图片描述
    经过数次努力之后,不得不放弃这条思路(难度很高),转向资料查找的方式,看看大佬们有没有留下这方面的研究。
  2. 经过一番的查找,虽然没有直接找到答案,但是确实找到了希望。
    发现上面那个接口,之前是用来获取 flv 视频链接的,avid 直接就是 av 号,cid 号也可以容易得到,sp 指的是视频的清晰度。
    112: 高清 1080P+
    80: 高清 1080P
    64: 高清 720P
    32: 清晰 480P
    16: 流畅 360P
    https://api.bilibili.com/x/player/playurl?avid={avid}&cid={cid}&qn={sp}&type=&otype=json
    比如:
    测试视频:av9561754
    avid = 9561754
    cid = 15805564【可以使用这个接口http://www.bilibili.tv/widget/getPageList?aid={av号}
    拼接后的链接:https://api.bilibili.com/x/player/playurl?avid=9561754&cid=15805564&qn=80&type=&otype=json,请求访问:
{
	"code": 0,
	"message": "0",
	"ttl": 1,
	"data": {
		"from": "local",
		"result": "suee",
		"message": "",
		"quality": 80,
		"format": "flv",
		"timelength": 187560,
		"accept_format": "flv,flv720,flv360",
		"accept_description": ["高清 1080P", "高清 720P", "流畅 360P"],
		"accept_quality": [80, 64, 16],
		"video_codecid": 7,
		"seek_param": "start",
		"seek_type": "offset",
		"durl": [{
			"order": 1,
			"length": 187560,
			"size": 21283844,
			"ahead": "EhBW5QA=",
			"vhead": "AWQAH//hABxnZAAfrNlAUAW7AWoEBAKAAAADAIAAMgAHjBjLAQAGaOk5yyLA/Pj4AA==",
			"url": "http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/64/55/15805564/15805564-1-80.flv?e=ig8euxZM2rNcNbN3hbUVhoMgnwNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_\u0026uipk=5\u0026nbs=1\u0026deadline=1567873729\u0026gen=playurl\u0026os=ks3u\u0026oi=2085381866\u0026trid=91e009b48e9c4a58beb341f6d02a4b59u\u0026platform=pc\u0026upsig=f6d8cc11b6b3fd33f01461b47fe0ecaf\u0026uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform\u0026mid=100938015",
			"backup_url": null
		}]
	}
}

既然对 flv 可行,那么对于 m4s 呢?avid 和 cid 号依旧可以用上述办法取得,但是之前的其它参数可不好搞,这可真是个难题!

  1. 抱着试一试的心态,尝试拼接链接
    av:66476652
    cid:115287880
    拼接链接:https://api.bilibili.com/x/player/playurl?avid=66476652&cid=115287880&qn=80&type=&otype=json,并访问,返回结果:
{
	"code": 0,
	"message": "0",
	"ttl": 1,
	"data": {
		"from": "local",
		"result": "suee",
		"message": "",
		"quality": 80,
		"format": "flv",
		"timelength": 229306,
		"accept_format": "hdflv2,flv,flv720,flv480,flv360",
		"accept_description": ["高清 1080P+", "高清 1080P", "高清 720P", "清晰 480P", "流畅 360P"],
		"accept_quality": [112, 80, 64, 32, 16],
		"video_codecid": 7,
		"seek_param": "start",
		"seek_type": "offset",
		"durl": [{
			"order": 1,
			"length": 229306,
			"size": 50769135,
			"ahead": "",
			"vhead": "",
			"url": "http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-80.flv?e=ig8euxZM2rNcNbUBhbUVhoMB7WNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_\u0026uipk=5\u0026nbs=1\u0026deadline=1567874137\u0026gen=playurl\u0026os=ks3u\u0026oi=2085381866\u0026trid=8f17d24721884478ac9ec0f330bd211cu\u0026platform=pc\u0026upsig=8972303e4863144b7bcddc295faccab2\u0026uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform\u0026mid=100938015",
			"backup_url": null
		}]
	}
}

竟然可以这样直接返回 flv 视频文件,这真是没有想到的。既然返回了 flv 文件,那么接下来的自动化过程就变得容易了,通过这个接口的拼接访问,返回的链接,就可以轻松下载到视频。接下来问题其实从如何爬取 m4s 视频又转化到如何爬取 flv 视频【应该是这样没错】。

  1. 后续的额外说明
    注意看这个 api 链接:
    https://api.bilibili.com/x/player/playurl?avid=66476652&cid=115287880&qn=80&type=&otype=json
    可以将它拆分为:
    https://api.bilibili.com/x/player/playurl
    avid=66476652
    cid=115287880
    qn=80
    type=
    otype=json
    基本上就是原始 http 链接,拼接请求参数【这种方式是直接将参数写在链接里 Get 请求报文,与 Post 不同】,说明这些参数理论上可以改变、增加、删减,只是返回的内容不一样。
    删减为最基本的请求链接:
    https://api.bilibili.com/x/player/playurl?avid=66476652&cid=115287880
    这就是它的最简形式,不能再简单了,否则服务器返回出错,删减多余控制参数的好处是,方便看链接。
    改变参数 qn:
    https://api.bilibili.com/x/player/playurl?avid=66476652&cid=115287880&qn=16
    qn=16:"length":229306,"size":13297215
    qn=80:"length":229306,"size":38226097
    清晰度改变,视频大小变大了。
    增加参数 fnval:
    https://api.bilibili.com/x/player/playurl?avid=66476652&cid=115287880&fnval=1
    无 fnval:upos-hz-mirrorkodou.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-64.flv
    有 fnval:mirrorcosu.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-6.mp4
    有这个参数的帮忙,就能直接下载 mp4,怎么说 mp4 比较通用。
三、爬取单个视频

既然都得到了视频的 URL,不再写写爬取视频,总感觉少了点什么。依旧使用强大而懒人的抓包工具 Fiddler 作为演示。不过之前是抓数据包,改它的请求头,提交并保存在本地上;这次的话爬不到了,需要全部自行构造一遍,不过也没有多大的区别。

  1. 提取指定视频的 flv 链接
    http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-80.flv?e=ig8euxZM2rNcNbUBhbUVhoMB7WNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_\u0026uipk=5\u0026nbs=1\u0026deadline=1567874137\u0026gen=playurl\u0026os=ks3u\u0026oi=2085381866\u0026trid=8f17d24721884478ac9ec0f330bd211cu\u0026platform=pc\u0026upsig=8972303e4863144b7bcddc295faccab2\u0026uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform\u0026mid=100938015
    不过这里要注意一点,Json 文件把所有的 & 转化为了 \u0026,不能直接请求这个链接,不然会直接报错的。修改以下的链接:
    http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/80/78/115287880/115287880-1-80.flv?e=ig8euxZM2rNcNbUBhbUVhoMB7WNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1567874137&gen=playurl&os=ks3u&oi=2085381866&trid=8f17d24721884478ac9ec0f330bd211cu&platform=pc&upsig=8972303e4863144b7bcddc295faccab2&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=100938015
    这样的链接才是一个正确的链接。
  2. 打开 Fiddler,刷新视频,重新抓包
    在这里插入图片描述
  3. 为了简单获取 headers 头部,直接将拖入 Composer 中
    在这里插入图片描述
  4. 稍微改一改 headers 头部的内容,并将链接替换为之前的 flv 链接,并点击 Excute 执行构造测试
    在这里插入图片描述
    请求成功!
    在这里插入图片描述
  5. 查看数据包的响应头,获取文件大小
    在这里插入图片描述
  6. 重新修改 Composer 中的头部,将 range 范围修改一下
    在这里插入图片描述
    等待一阵时间,可以看到,已经下载成功了!
    在这里插入图片描述
  7. 导出视频
    在这里插入图片描述
    在这里插入图片描述
  8. 查看爬取到的视频文件

在这里插入图片描述
看起来没有什么问题
在这里插入图片描述
爬取成功~~!O(∩_∩)O哈哈!

四、批量爬取视频

批量爬取视频的最好办法就是,用编程实现视频的重复爬取任务,从而解放自己的双手。在这里简单地用 Python 实现视频爬取的过程【复杂的我也不会】。

import requests
import os, sys

class BilibiliCrawler():
    def  __init__(self, qn=80, output=''):
        # 初始化

        if output:
            path = os.getcwd()+'\\'
            path += output
            if not os.path.exists(path):
                os.mkdir(path)
                output = path + '\\'
                 
        self.qn = qn
        self.output = output
        self.cid_url = 'https://api.bilibili.com/x/player/pagelist?aid={}&jsonp=jsonp'
        self.flv_url = 'https://api.bilibili.com/x/player/playurl?avid={}&cid={}&qn={}&type=&otype=json'
        self.headers1 = {'host': 'api.bilibili.com',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}
        self.headers2 = {'host':'',
            'Origin': 'https://www.bilibili.com',
            'Referer': 'https://www.bilibili.com/video/ac{}',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}

        
    def getCid(self, url):
        # 得到 cid
        data = requests.get(url, headers=self.headers1).json()
        detail = data['data'][0]
        cid = detail['cid']
        name = detail['part']
        duration = detail['duration']
        return cid, name, duration
        
        
    def getFlv(self, url):
        # 得到 flv
        data = requests.get(url, headers=self.headers1).json()
        durl = data['data']['durl'][0]
        size = durl['size']
        url = durl['url']
        length = durl['length']
        return length, size, url

    def download(self, url, filename='None.flv'):
        # 下载
        size = 0
        response = requests.get(url, headers=self.headers2, stream=True, verify=False)
        chunk_size = 1024
        content_size = int(response.headers['content-length'])
        if response.status_code == 200:
            sys.stdout.write('  [文件大小]:%0.2f MB\n' % (content_size / chunk_size / 1024))
            filename = os.path.join(self.output, filename)
            with open(filename, 'wb') as file:
                for data in response.iter_content(chunk_size = chunk_size):
                    file.write(data)
                    size += len(data)
                    file.flush()
                    sys.stdout.write('  [下载进度]:%.2f%%' % float(size / content_size * 100) + '\r')
                    if size / content_size == 1:
                        print('\n')
        else:
            print('下载出错')

    def start(self, av):
        # 开始
        cid, name ,duration = self.getCid(self.cid_url.format(av))
        length, size, flv = self.getFlv(self.flv_url.format(av, cid, self.qn))
        host = flv.split('/')[2]
        self.headers2['host'] = host
        filename = name.replace(' ', '_') + '.flv'
        print("name: {0} duration:{1}s".format(filename, duration))
        self.download(flv, filename)


if __name__ == '__main__':
    bilibili = BilibiliCrawler(qn=80, output="download")
    avlist = ['66476652', '66551946']
    for i in avlist:
        bilibili.start(av=i)

使用方法就是填入 av 号,控制台打开【因为添加了进度条,不过代码可能还有 bug,发现后再修吧】。

五、总结

个人认为,爬取视频只要选择自己认为方便和喜欢的方式就行,现在爬取工具这么多,也不用一定要自己编程实现,当然这也是个不错的方法锻炼自己的编程手艺。
本来还想写点的,发现写的也差不多了,那就先写到这里,以后想到别的可能会继续添加在里面。

后记

emm… 关于 80 清晰视频,还需要登录信息的,就是 Cookie 值。如果需要爬高清的,就自行添加一下头部吧。上次没有弄清楚,诶~~!

后记的后记

将 HTML 播放器,改为 flash 播放器,可以直接看到 flv 的链接。

点我回顶部

 
 
 
 
 
 
 
Fin.

  • 25
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
m4s视频音频文件合并是指将m4s视频文件和相应的音频文件合并为一个完整的视频文件。通常,视频和音频在传输或下载过程中会被分割成多个.m4s文件,这些文件包含了视频和音频的片段。要播放这些文件,需要将它们合并成一个完整的视频文件。 合并视频和音频文件可以通过使用各种工具和软件来完成。其中,一个常用的工具是nplay。nplay是一个多媒体播放器,它可以播放和处理多种音视频文件格式。 要使用nplay合并.m4s视频和音频文件,首先需要将这些文件导入到nplay中。可以通过打开nplay并选择“导入”选项来实现。然后,选择.m4s视频文件和相应的音频文件,并将它们添加到nplay的播放列表中。 接下来,可以通过拖动和调整文件顺序来确保视频和音频以正确的顺序合并。将.m4s视频文件拖动到音频文件前面,确保它们按照正确的时间顺序排列。 然后,选择“合并”或“导出”选项来合并视频和音频文件。nplay会将这些文件合并成一个完整的视频文件,并保存在指定的位置。在此过程中,nplay会自动处理音频和视频的同步和合并。 完成后,可以通过在nplay中播放合并后的视频文件来确认合并是否成功。还可以将这个合并的视频文件导出到其他设备或媒体平台上进行进一步的使用和共享。 总而言之,m4s视频音频文件合并是通过使用nplay等工具将.m4s视频和音频文件合并为一个完整的视频文件的过程。这样可以方便地播放和处理分割的音视频文件

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值