初学python 很多高级的东西都还不知道,多以代码很臃肿
其实下视频最简单的方法就是用手机浏览器,像夸克啊之类的,自带的播放器打开视频播放网站,然后点击浏览器提供的下载功能,他其实也是通过解析网站的m3u8下载
但是问题在于公司的无线网把我们的外网都墙了,流量又限速,又是个影迷,就想着用电脑下好视频,传到手机上看。走起
* 通过我长时间的观察,一般视频网站,m3u8链接都是放在播放器的script中,所以使用 BeautifulSoup 在页面源代码中获取到包含 .m3u8 的script并提取出链接即可
content = requests.get(htmlUrl,headers=headers).text bsObj = BeautifulSoup(content,"html.parser") index = 0 for scriptItem in bsObj.findAll("script"): index += 1 if '.m3u8' in str(scriptItem): m3u8Start = str(scriptItem).find("\"url\":\"")+7 m3u8End = str(scriptItem).find(".m3u8")+5 m3u8Url = str(scriptItem)[m3u8Start:m3u8End].replace('\\','') global m3u8Url_before m3u8Url_before="https://" + m3u8Url.split('/')[2] #获取到m3u8文件,并保存m3u8的域名,防止ts链接为相对路径时,进行拼接
* 这里拿到的m3u8可能时最终的链接也可能时源链接,区别在于,最终链接里是包含 /hls/ 的,所以需要判断拿到的m3u8是否包含hls
# 链接是源链接时,需要加载出带有“hls”的链接 if 'hls' not in m3u8Url: content = requests.get(m3u8Url,headers=headers).text count = 0 nList = [] #存储出现换行位置的数组,用于后面取后两个换行位置之间的为m3u8链接 for item in list(content): count += 1 if item == '\n': nList.append(count) m3u8Url_hls = str(content)[nList[-2]:nList[-1]] # 判断此m3u8链接是否为绝对路径 if 'http' not in m3u8Url_hls: m3u8Url_hls = m3u8Url_before + m3u8Url_hls else: m3u8Url_before = ''
else:
if index == len(list(bsObj.findAll("script"))):
print("在页面Script中未找到相关m3u8链接。。。")
* 拿到m3u8链接后,开始获取所有的ts链接,并存储到本地的txt文件中,后期判断,如果有这个文件,就跳过以上两步
def tsList(): #存储ts链接到本地txt文件 with open('E:/python/xxx/' + name + '.txt','r') as f: if '.ts' in f.read(): print('ts视频链接均已存储,无需重复请求') else: print('开始获取并存储ts链接') with open('E:/python/xxx/' + name + '.txt','r') as f: m3u8Url = f.readlines()[0].strip() # requests得到m3u8文件内容 content = requests.get(m3u8Url,headers=headers) print(content.text)
#获取ts视频的加密链接,如果有的话,请求该链接,获取解密key并存储到相同txt中 jiami=re.findall('#EXT-X-KEY:(.*)\n',content.text) if len(jiami)>0: key=str(re.findall('URI="(.*)"',jiami[0]))[2:-2] if 'http' not in key: m3u8Start = m3u8Url.find("\"url\":\"")+7 m3u8End = m3u8Url.find(".m3u8")+5 m3u8Url = m3u8Url[m3u8Start:m3u8End].replace('\\','') m3u8Url_before="https://" + m3u8Url.split('/')[2] else: m3u8Url_before = '' keycontent= requests.get(m3u8Url_before + key,headers).text with open('E:/python/xxx/' + name + '.txt','a') as f: f.write(keycontent + '\n') else:
#如果没有加密的话,直接使用00000000000进行占位,用于下载时的判断 with open('E:/python/xxx/' + name + '.txt','a') as f: f.write('000000000000')
#开始请求m3u8链接,并通过链接的正则匹配出所有的ts文件链接 if(content.status_code == 200): pattern = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+') # 匹配每一个ts链接 content = content.text.split(",") index = 0 for item in content: index += 1 url = str(pattern.findall(item))[2:-2] with open('E:/python/xxx/' + name + '.txt','a') as f: f.write(url + '\n') Download()
* 以上,前期准备已完成,顺利的话,xxx.txt长这样
未完待续