| 
 | 1 | +from time import sleep  | 
 | 2 | +import requests, urllib.request, re  | 
 | 3 | +import os, sys,json  | 
 | 4 | + | 
 | 5 | +headers = {  | 
 | 6 | +        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',  | 
 | 7 | +        'Cookie': 'SESSDATA=182cd036%2C1636985829%2C3b393%2A51',  | 
 | 8 | +        'Host': 'api.bilibili.com'  | 
 | 9 | +    }  | 
 | 10 | + | 
 | 11 | + | 
 | 12 | +Str = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'  # 准备的一串指定字符串  | 
 | 13 | +Dict = {}  | 
 | 14 | + | 
 | 15 | +# 将字符串的每一个字符放入字典一一对应 , 如 f对应0 Z对应1 一次类推。  | 
 | 16 | +for i in range(58):  | 
 | 17 | +    Dict[Str[i]] = i  | 
 | 18 | + | 
 | 19 | +s = [11, 10, 3, 8, 4, 6, 2, 9, 5, 7]  # 必要的解密列表  | 
 | 20 | +xor = 177451812   | 
 | 21 | +add = 100618342136696320  # 这串数字最后要被减去或加上  | 
 | 22 | + | 
 | 23 | +def algorithm_enc(av):  | 
 | 24 | +    ret = av  | 
 | 25 | +    av = int(av)  | 
 | 26 | +    av = (av ^ xor) + add  | 
 | 27 | +    # 将BV号的格式(BV + 10个字符) 转化成列表方便后面的操作  | 
 | 28 | +    r = list('BV          ')  | 
 | 29 | +    for i in range(10):  | 
 | 30 | +        r[s[i]] = Str[av // 58 ** i % 58]  | 
 | 31 | +    return ''.join(r)  | 
 | 32 | + | 
 | 33 | +def find_bid(p):  | 
 | 34 | +    bids = []  | 
 | 35 | +    r = requests.get(  | 
 | 36 | +            'https://api.bilibili.com/x/web-interface/newlist?&rid=20&type=0&pn={}&ps=50&jsonp=jsonp'.format(p))  | 
 | 37 | +        | 
 | 38 | +    data = json.loads(r.text)  | 
 | 39 | +    archives = data['data']['archives']  | 
 | 40 | + | 
 | 41 | +    for item in archives:  | 
 | 42 | +        aid = item['aid']  | 
 | 43 | +        # r = requests.get('http://api.bilibili.com/x/web-interface/archive/stat?aid=' + str(aid), headers=headers)  | 
 | 44 | +        # bid = json.loads(r.text)['data']['bvid']  | 
 | 45 | +        bid = algorithm_enc(aid)  | 
 | 46 | +        bids.append(bid)  | 
 | 47 | + | 
 | 48 | +    return bids  | 
 | 49 | + | 
 | 50 | + | 
 | 51 | +def get_cid(bid):  | 
 | 52 | +    url = 'https://api.bilibili.com/x/player/pagelist?bvid=' + bid  | 
 | 53 | + | 
 | 54 | +      | 
 | 55 | +    html = requests.get(url, headers=headers).json()  | 
 | 56 | + | 
 | 57 | +    infos = []  | 
 | 58 | + | 
 | 59 | +    data = html['data']  | 
 | 60 | +    cid_list = data  | 
 | 61 | +    for item in cid_list:  | 
 | 62 | +        cid = item['cid']  | 
 | 63 | +        title = item['part']  | 
 | 64 | +        infos.append({'bid': bid, 'cid': cid, 'title': title})  | 
 | 65 | +    return infos  | 
 | 66 | + | 
 | 67 | + | 
 | 68 | +# 访问API地址  | 
 | 69 | +def get_video_list(aid, cid, quality):  | 
 | 70 | +    url_api = 'https://api.bilibili.com/x/player/playurl?cid={}&bvid={}&qn={}'.format(cid, aid, quality)  | 
 | 71 | +    headers = {  | 
 | 72 | +        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',  | 
 | 73 | +        'Cookie': 'SESSDATA=182cd036%2C1636985829%2C3b393%2A51',  | 
 | 74 | +        'Host': 'api.bilibili.com'  | 
 | 75 | +    }  | 
 | 76 | +    html = requests.get(url_api, headers=headers).json()  | 
 | 77 | +    video_list = []  | 
 | 78 | + | 
 | 79 | +    for i in html['data']['durl']:  | 
 | 80 | +        video_list.append(i['url'])  | 
 | 81 | +    return video_list  | 
 | 82 | + | 
 | 83 | + | 
 | 84 | +# 下载视频  | 
 | 85 | + | 
 | 86 | +def schedule_cmd(blocknum, blocksize, totalsize):  | 
 | 87 | +    percent = 100.0 * blocknum * blocksize/ totalsize  | 
 | 88 | +    s = ('#' * round(percent)).ljust(100, '-')  | 
 | 89 | +    sys.stdout.write('%.2f%%' % percent + '[' + s + ']' + '\r')  | 
 | 90 | +    sys.stdout.flush()  | 
 | 91 | + | 
 | 92 | +#  下载视频  | 
 | 93 | +def download(video_list, title, bid):  | 
 | 94 | +    for i in video_list:  | 
 | 95 | +        opener = urllib.request.build_opener()  | 
 | 96 | +        # 请求头  | 
 | 97 | +        opener.addheaders = [  | 
 | 98 | +            ('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'),  | 
 | 99 | +            ('Accept', '*/*'),  | 
 | 100 | +            ('Accept-Language', 'en-US,en;q=0.5'),  | 
 | 101 | +            ('Accept-Encoding', 'gzip, deflate, br'),   | 
 | 102 | +            ('Range', 'bytes=0-'),    | 
 | 103 | +            ('Referer', 'https://www.bilibili.com/video/'+bid),  | 
 | 104 | +            ('Origin', 'https://www.bilibili.com'),  | 
 | 105 | +            ('Connection', 'keep-alive'),  | 
 | 106 | + | 
 | 107 | +        ]  | 
 | 108 | + | 
 | 109 | +        filename=os.path.join('D:\\video', r'{}_{}.mp4'.format(bid,title))   | 
 | 110 | + | 
 | 111 | +        try:  | 
 | 112 | +            urllib.request.install_opener(opener)  | 
 | 113 | +            urllib.request.urlretrieve(url=i, filename=filename, reporthook=schedule_cmd)   | 
 | 114 | +        except:  | 
 | 115 | +            print(bid + "下载异常,文件:" + filename)  | 
 | 116 | + | 
 | 117 | +if __name__ == '__main__':  | 
 | 118 | +    # algorithm_enc(545821176)  | 
 | 119 | +    bids = find_bid(1)  | 
 | 120 | +    print(len(bids))  | 
 | 121 | +    for bid in bids:  | 
 | 122 | +        sleep(10)  | 
 | 123 | +        cid_list = get_cid(bid)  | 
 | 124 | + | 
 | 125 | +        for item in cid_list:  | 
 | 126 | +            cid = item['cid']  | 
 | 127 | +            title = item['title']  | 
 | 128 | +            title = re.sub(r'[\/\\:*?"<>|]', '', title)  # 替换为空的  | 
 | 129 | +            bid = item['bid']  | 
 | 130 | +            video_list = get_video_list(bid, cid, 80)  | 
 | 131 | +          | 
 | 132 | +            download(video_list, title, bid)  | 
0 commit comments