python requests bilibili视频下载

代码版

# !/user/bin/env python
# -*- coding:utf-8 -*-
"""
    time: 2018-12-16
    title:B站视频下载
    annotation:
    author: pqx
    email:[email protected]
"""
import os
import re
import time
import shutil
import requests
import hashlib
import urllib.request
from requests.adapters import HTTPAdapter
from xml.dom.minidom import parseString
from moviepy.editor import *

def clean_txt(title):#清洗标题中不能用于命名文件的字符
    rstr = r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'
    title = re.sub(rstr, "_", title)  # 替换为下划线
    return title

def create_folder(name):#创建文件夹
    try:
        if '{}'.format(name) not in os.listdir():#如果不存在
            os.makedirs('{}'.format(name))#则创建
    except:
        return ''

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
def get_one_page_text(url,headers=headers,code='utf-8'):#访问一个页面 返回页面信息
    try:
        s = requests.Session()#保持会话
        s.mount('http://', HTTPAdapter(max_retries=3))#最大重试
        s.mount('https://', HTTPAdapter(max_retries=3))
        r=s.get(url,headers=headers,timeout=15)#超时设置
        r.raise_for_status()#状态码 如果不是200则报错
        r.encoding=code#r.apparent_encoding#字符类型
        return  r.text#返回页面
    except Exception as e:
        t=time.strftime('%Y/%m/%d %H:%M:%S %a')#时间格式化
        with open(r'D:\bilibili_video\Exception.txt','a+',encoding='utf-8') as f:
            f.write('time:{}\n\nurl:{}\n\n{}\n\n'.format(t,url,e))

def get_params(start_url,quality,p):
    html = get_one_page_text(start_url)
    cid = re.search(r'cid=(\d+)&',html).group(1)
    title = clean_txt(re.search(r'

',html).group(1))+'第%sP'%p path = r'D:\bilibili_video\{}'.format(title) create_folder(path) SEC1 = '94aba54af9065f71de72f5508f1cd42e' #上面的SEC已经失效了 ts = str(int(time.time())) #时间戳 params = 'appkey=84956560bc028eb7&cid={}&otype=xml&qn={}&quality={}&type='.format(cid, quality, quality) #otype=json也行!! encrypt = hashlib.md5(bytes(params+SEC1,'utf-8')).hexdigest() video_list=get_down_load_url(params, encrypt, start_url) print('视频cid : %s 共 %s 段' % (cid, len(video_list))) down_load( video_list, start_url, path,title) splice_mp4(path,title) def get_down_load_url(params,encrypt,start_url): url_api = 'https://interface.bilibili.com/v2/playurl?' + params + '&sign=' + encrypt headers = {'Referer':start_url,'User-Agent':'Mozilla/5.0'} html = get_one_page_text(url_api,headers=headers) doc = parseString(html.encode('utf8')) durl = doc.getElementsByTagName('durl') video_list = [] for i in durl: video = i.getElementsByTagName('url')[0] url_video = video.childNodes[0].data video_list.append(url_video) return video_list def down_load(video_list,start_url,path,title): num = 1 for i in video_list: opener = urllib.request.build_opener() opener.addheaders = [ # ('Host', 'upos-hz-mirrorks3.acgvideo.com'), #注意修改host,不用也行 ('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:56.0) Gecko/20100101 Firefox/56.0'), ('Accept', '*/*'), ('Accept-Language', 'en-US,en;q=0.5'), ('Accept-Encoding', 'gzip, deflate, br'), ('Range', 'bytes=0-'), # Range 的值要为 bytes=0- 才能下载完整视频 ('Referer', start_url), # 注意修改referer,必须要加的! ('Origin', 'https://www.bilibili.com'), ('Connection', 'keep-alive') ] print('视频标题 : %s ,第%s段正在下载' % (title, num)) urllib.request.install_opener(opener) urllib.request.urlretrieve(url=i, filename=path+'\\%s-%s.flv'%(title,num)) # 写成mp4也行 title + '-' + num + '.flv' print('视频标题 : %s ,第%s段下载完成' % (title, num)) num += 1 def splice_mp4(path,title): print('合并视频 : %s ' % (title)) LL = sorted(os.listdir(path)) if len(LL)>=2: ll=[] for file in LL: if os.path.splitext(file)[1] == '.flv': filepath = os.path.join(path, file) video = VideoFileClip(filepath) ll.append(video) final_clip = concatenate_videoclips(ll) final_clip.write_videofile(path+'\\{}.mp4'.format(title), fps=24, remove_temp=False) print('视频 : %s 合并完成' % (title)) os.remove('./{}TEMP_MPY_wvf_snd.mp3'.format(title)) # 删文件 elif len(LL)==1: os.rename(os.path.join(path, LL[0]), os.path.join(path, title + ".mp4")) print('视频 : %s 合并完成' % (title)) new_path = r'D:\bilibili_video' shutil.move(path + '\\{}.mp4'.format(title), new_path + '\\{}.mp4'.format(title)) def datas(): quality = input('请输入您要下载视频的清晰度(1080p:80;720p:64;480p:32;360p:15)(填写80或64或32或15):') start = input('请输入您要下载的B站av号或者视频链接地址如:av19956343,或 19956343,或https://www.bilibili.com/video/av19956343:') p=input('请输入您要下载的B站av号P数(只有1p请直接回车或输入数字 如:1)(多选请输入p数 如:1,3,5 以英文","号分隔)(选择范围请输入 如:2-10,以英文"-"号分隔):') if start.replace('av','').isdigit() == True: av_url = 'https://www.bilibili.com/video/av'+start.replace('av','') else: av_url=start start_url_list=[] if p==''or int(p).isdigit()==True: start_url = av_url + '/?p=%s' % p start_url_list.append([start_url,int(p)]) elif ','in p: for p in p.split(','): start_url=av_url+'/?p=%s'%p start_url_list.append([start_url,p]) elif '-'in p: for p in range(int(p.split('-')[0]),int(p.split('-')[1])+1): start_url=av_url+'/?p=%s'%p start_url_list.append([start_url,p]) else: print('输入有误,程序退出') return quality,start_url_list def main (): quality,start_url_list=datas()[0],datas()[1] for start_url in start_url_list: get_params(start_url[0],quality,start_url[1]) if __name__=='__main__': main()

图片版

你可能感兴趣的:(python requests bilibili视频下载)