時間:2020-11-14來源:www.outletmksalestore.com作者:電腦系統城
運行效果:
完整代碼
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# !/usr/bin/python # -*- coding:utf-8 -*- # time: 2019/07/21--20:12 __author__ = 'Henry' ''' 項目: B站動漫番劇(bangumi)下載 版本2: 無加密API版,但是需要加入登錄后cookie中的SESSDATA字段,才可下載720p及以上視頻 API: 1.獲取cid的api為 https://api.bilibili.com/x/web-interface/view?aid=47476691 aid后面為av號 2.下載鏈接api為 https://api.bilibili.com/x/player/playurl?avid=44743619&cid=78328965&qn=32 cid為上面獲取到的 avid為輸入的av號 qn為視頻質量 注意: 但是此接口headers需要加上登錄后'Cookie': 'SESSDATA=3c5d20cf%2C1556704080%2C7dcd8c41' (30天的有效期)(因為現在只有登錄后才能看到720P以上視頻了) 不然下載之后都是最低清晰度,哪怕選擇了80也是只有480p的分辨率!! ''' import requests, time, urllib.request, re from moviepy.editor import * import os, sys, threading, json import imageio # 訪問API地址 def get_play_list(aid, cid, quality): url_api = 'https://api.bilibili.com/x/player/playurl?cid={}&avid={}&qn={}' . format (cid, aid, quality) 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' , 'Cookie' : 'SESSDATA=13bd2abb%2C1619949439%2C2815d*b1' , # 登錄B站后復制一下cookie中的SESSDATA字段,有效期1個月 'Host' : 'api.bilibili.com' } html = requests.get(url_api, headers = headers).json() # print(html) # 當下載會員視頻時,如果cookie中傳入的不是大會員的SESSDATA時就會返回: {'code': -404, 'message': '啥都木有', 'ttl': 1, 'data': None} if html[ 'code' ] ! = 0 : print ( '注意!當前集數為B站大會員專享,若想下載,Cookie中請傳入大會員的SESSDATA' ) return 'NoVIP' video_list = [] for i in html[ 'data' ][ 'durl' ]: video_list.append(i[ 'url' ]) print (video_list) return video_list # 下載視頻 ''' urllib.urlretrieve 的回調函數: def callbackfunc(blocknum, blocksize, totalsize): @blocknum: 已經下載的數據塊 @blocksize: 數據塊的大小 @totalsize: 遠程文件的大小 ''' def Schedule_cmd(blocknum, blocksize, totalsize): speed = (blocknum * blocksize) / (time.time() - start_time) # speed_str = " Speed: %.2f" % speed speed_str = " Speed: %s" % format_size(speed) recv_size = blocknum * blocksize # 設置下載進度條 f = sys.stdout pervent = recv_size / totalsize percent_str = "%.2f%%" % (pervent * 100 ) n = round (pervent * 50 ) s = ( '#' * n).ljust( 50 , '-' ) f.write(percent_str.ljust( 8 , ' ' ) + '[' + s + ']' + speed_str) f.flush() # time.sleep(0.1) f.write( '\r' ) def Schedule(blocknum, blocksize, totalsize): speed = (blocknum * blocksize) / (time.time() - start_time) # speed_str = " Speed: %.2f" % speed speed_str = " Speed: %s" % format_size(speed) recv_size = blocknum * blocksize # 設置下載進度條 f = sys.stdout pervent = recv_size / totalsize percent_str = "%.2f%%" % (pervent * 100 ) n = round (pervent * 50 ) s = ( '#' * n).ljust( 50 , '-' ) print (percent_str.ljust( 6 , ' ' ) + '-' + speed_str) f.flush() time.sleep( 2 ) # print('\r') # 字節bytes轉化K\M\G def format_size(bytes): try : bytes = float (bytes) kb = bytes / 1024 except : print ( "傳入的字節格式不對" ) return "Error" if kb > = 1024 : M = kb / 1024 if M > = 1024 : G = M / 1024 return "%.3fG" % (G) else : return "%.3fM" % (M) else : return "%.3fK" % (kb) # 下載視頻 def down_video(video_list, title, start_url, page): num = 1 print ( '[正在下載第{}話視頻,請稍等...]:' . format (page) + title) currentVideoPath = os.path.join(sys.path[ 0 ], 'bilibili_video' , title) # 當前目錄作為下載目錄 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' ), ] urllib.request.install_opener(opener) # 創建文件夾存放下載的視頻 if not os.path.exists(currentVideoPath): os.makedirs(currentVideoPath) # 開始下載 if len (video_list) > 1 : urllib.request.urlretrieve(url = i, filename = os.path.join(currentVideoPath, r '{}-{}.flv' . format (title, num)), reporthook = Schedule_cmd) # 寫成mp4也行 title + '-' + num + '.flv' else : urllib.request.urlretrieve(url = i, filename = os.path.join(currentVideoPath, r '{}.flv' . format (title)), reporthook = Schedule_cmd) # 寫成mp4也行 title + '-' + num + '.flv' num + = 1 # 合并視頻(20190802新版) def combine_video(title_list): video_path = os.path.join(sys.path[ 0 ], 'bilibili_video' ) # 下載目錄 for title in title_list: current_video_path = os.path.join(video_path ,title) if len (os.listdir(current_video_path)) > = 2 : # 視頻大于一段才要合并 print ( '[下載完成,正在合并視頻...]:' + title) # 定義一個數組 L = [] # 遍歷所有文件 for file in sorted (os.listdir(current_video_path), key = lambda x: int (x[x.rindex( "-" ) + 1 :x.rindex( "." )])): # 如果后綴名為 .mp4/.flv if os.path.splitext( file )[ 1 ] = = '.flv' : # 拼接成完整路徑 filePath = os.path.join(current_video_path, file ) # 載入視頻 video = VideoFileClip(filePath) # 添加到數組 L.append(video) # 拼接視頻 final_clip = concatenate_videoclips(L) # 生成目標視頻文件 final_clip.to_videofile(os.path.join(current_video_path, r '{}.mp4' . format (title)), fps = 24 , remove_temp = False ) print ( '[視頻合并完成]' + title) else : # 視頻只有一段則直接打印下載完成 print ( '[視頻合并完成]:' + title) if __name__ = = '__main__' : start_time = time.time() # 用戶輸入番劇完整鏈接地址 # 1. https://www.bilibili.com/bangumi/play/ep267692 (用帶ep鏈接) # 2. https://www.bilibili.com/bangumi/play/ss26878 (不要用這個ss鏈接,epinfo的aid會變成'-1') print ( '*' * 30 + 'B站番劇視頻下載小助手' + '*' * 30 ) print ( '[提示]: 1.如果您想下載720P60,1080p+,1080p60質量的視頻,請將35行代碼中的SESSDATA改成你登錄大會員后得到的SESSDATA,普通用戶的SESSDATA最多只能下載1080p的視頻' ) print ( ' 2.若發現下載的視頻質量在720p以下,請將35行代碼中的SESSDATA改成你登錄后得到的SESSDATA(有效期一個月),而失效的SESSDATA就只能下載480p的視頻' ) start = input ( '請輸入您要下載的B站番劇的完整鏈接地址(例如:https://www.bilibili.com/bangumi/play/ep267692):' ) ep_url = start 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' } html = requests.get(ep_url,headers = headers).text ep_info = re.search(r 'INITIAL_STATE__=(.*?"]});' , html).group( 1 ) # print(ep_info) ep_info = json.loads(ep_info) print (ep_info) # print('您將要下載的番劇名為:' + ep_info['mediaInfo']['title']) # 字段格式太不統一了 y = input ( '請輸入1或2 - 1.只下載當前一集 2.下載此番劇的全集:' ) # 1.如果只下載當前ep id_list = [] if y = = '1' : try : id_list.append([ep_info[ 'videoData' ][ 'aid' ], ep_info[ 'videoData' ][ 'cid' ], ep_info[ 'videoData' ][ 'title' ] + ' ' + ep_info[ 'videoData' ][ 'title' ]]) except : id_list.append([ep_info[ 'videoData' ][ 'aid' ], ep_info[ 'videoData' ][ 'cid' ], '第' + str (ep_info[ 'videoData' ][ 'index' ]) + '話 ' + ep_info[ 'videoData' ][ 'index_title' ]]) # 2.下載此番劇全部ep else : for i in ep_info[ 'epList' ]: # if i['badge'] == '': # 當badge字段為'會員'時,接口返回404 try : id_list.append([i[ 'aid' ], i[ 'cid' ], i[ 'titleFormat' ] + ' ' + i[ 'title' ]]) except : id_list.append([i[ 'aid' ], i[ 'cid' ], '第' + str (i[ 'index' ]) + '話 ' + i[ 'index_title' ]]) # qn參數就是視頻清晰度 # 可選值: # 116: 高清1080P60 (需要帶入大會員的cookie中的SESSDATA才行,普通用戶的SESSDATA最多只能下載1080p的視頻,不帶入SESSDATA就只能下載480p的) # 112: 高清1080P+ (hdflv2) (需要大會員) # 80: 高清1080P (flv) # 74: 高清720P60 (需要大會員) # 64: 高清720P (flv720) # 32: 清晰480P (flv480) # 16: 流暢360P (flv360) print ( '請輸入您要下載視頻的清晰度(1080p60:116;1080p+:112;1080p:80;720p60:74;720p:64;480p:32;360p:16; **注意:1080p+,1080p60,720p60都需要帶入大會員的cookie中的SESSDATA才行,普通用戶的SESSDATA最多只能下載1080p的視頻):' ) quality = input ( '請輸入116或112或80或74或64或32或16:' ) threadpool = [] title_list = [] page = 1 print (id_list) for item in id_list: aid = str (item[ 0 ]) cid = str (item[ 1 ]) title = item[ 2 ] title = re.sub(r '[\/\\:*?"<>|]' , '', title) # 替換為空的 print ( '[下載番劇標題]:' + title) title_list.append(title) start_url = ep_url video_list = get_play_list(aid, cid, quality) start_time = time.time() # down_video(video_list, title, start_url, page) # 定義線程 if video_list ! = 'NoVIP' : th = threading.Thread(target = down_video, args = (video_list, title, start_url, page)) # 將線程加入線程池 threadpool.append(th) page + = 1 # 開始線程 for th in threadpool: th.start() # 等待所有線程運行完畢 for th in threadpool: th.join() # 最后合并視頻 print (title_list) combine_video(title_list) end_time = time.time() # 結束時間 print ( '下載總耗時%.2f秒,約%.2f分鐘' % (end_time - start_time, int (end_time - start_time) / 60 )) # 如果是windows系統,下載完成后打開下載目錄 currentVideoPath = os.path.join(sys.path[ 0 ], 'bilibili_video' ) # 當前目錄作為下載目錄 if (sys.platform.startswith( 'win' )): os.startfile(currentVideoPath) |
以上就是利用python 下載bilibili視頻的詳細內容
2022-03-01
PHP如何從txt文件中讀取數據詳解2022-03-01
分享5個方便好用的Python自動化腳本2021-03-29
Python中pycharm編輯器界面風格修改方法