來源:Python 技術(shù)「ID: pythonall」
B 站大家 都熟悉,,尤其是它的舞蹈區(qū)。 有 100W+ 的舞蹈視頻,。 在沒有 wifi 的情況下,,就欣賞不了這些視頻了。 作為一個 python 程序員,,小編就寫一個 Python 腳本在晚上下載舞蹈區(qū)的所有視頻,。
抓取列表首先點開舞蹈區(qū)先選擇宅舞列表。
然后打開 F12 的控制面板,,可以找到一條 https://api.bilibili.com/x/web-interface/newlist?rid=20&type=0&pn=1&ps=20&jsonp=jsonp&callback=jsonCallback_bili_57905715749828263
的 url,,其中 rid 是 B 站的小分類,pn 是頁數(shù),。
小編試著在瀏覽器將地址打開居然報了 404,,可是在控制面板中這個地址的返回值明明就是視頻列表。試著去掉 callback 的參數(shù),,意外的得到了想要的結(jié)果,。
眾所周知 bid 是一個 B 站視頻的唯一 ID,想要獲取 bid 可以從上面 url 的返回值中提取 aid,,然后將 aid 轉(zhuǎn)換為 bid,。
# aid 轉(zhuǎn) bid 代碼取自:https://zhuanlan.zhihu.com/p/117358823 Str = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF' # 準備的一串指定字符串 Dict = {}# 將字符串的每一個字符放入字典一一對應(yīng) , 如 f對應(yīng)0 Z對應(yīng)1 一次類推,。 for i in range(58 ): Dict[Str[i]] = i s = [11 , 10 , 3 , 8 , 4 , 6 , 2 , 9 , 5 , 7 ] # 必要的解密列表 xor = 177451812 add = 100618342136696320 # 這串數(shù)字最后要被減去或加上 def algorithm_enc (av) : ret = av av = int(av) av = (av ^ xor) + add # 將BV號的格式(BV + 10個字符) 轉(zhuǎn)化成列表方便后面的操作 r = list('BV ' ) for i in range(10 ): r[s[i]] = Str[av // 58 ** i % 58 ] return '' .join(r)def find_bid (p) : bids = [] r = requests.get( 'https://api.bilibili.com/x/web-interface/newlist?&rid=20&type=0&pn={}&ps=50&jsonp=jsonp' .format(p)) data = json.loads(r.text) archives = data['data' ]['archives' ] for item in archives: aid = item['aid' ] bid = algorithm_enc(aid) bids.append(bid) return bids
獲取視頻的 CID想要下載 1080 的視頻,,光有 bid 是不夠的,還需要 登錄后 Cookie 中的 SESSDATA 值和 cid ,。
首先登錄 B 站將 Cookie 中的 SESSDATA 復(fù)制到對象頭中,。用地址為 https://api.bilibili.com/x/player/pagelist?bvid=
url 返回 cid。
def get_cid (bid) : url = 'https://api.bilibili.com/x/player/pagelist?bvid=' + bid headers = { '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' , 'Cookie' : 'SESSDATA=182cd036%2C1636985829%2C3b393%2A51' , 'Host' : 'api.bilibili.com' } html = requests.get(url, headers=headers).json() infos = [] data = html['data' ] cid_list = data for item in cid_list: cid = item['cid' ] title = item['part' ] infos.append({'bid' : bid, 'cid' : cid, 'title' : title}) return infos
下載視頻下載視頻的 https://api.bilibili.com/x/player/playurl
來自于每次視頻播放完之后的推薦列表,。
最后使用 urllib.request.urlretrieve 函數(shù)下載視頻,。
def get_video_list (aid, cid, quality) : url_api = 'https://api.bilibili.com/x/player/playurl?cid={}&bvid={}&qn={}' .format(cid, aid, quality) headers = { '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' , 'Cookie' : 'SESSDATA=182cd036%2C1636985829%2C3b393%2A51' , 'Host' : 'api.bilibili.com' } html = requests.get(url_api, headers=headers).json() video_list = [] for i in html['data' ]['durl' ]: video_list.append(i['url' ]) return video_listdef schedule_cmd (blocknum, blocksize, totalsize) : percent = 100.0 * blocknum * blocksize/ totalsize s = ('#' * round(percent)).ljust(100 , '-' ) sys.stdout.write('%.2f%%' % percent + '[' + s + ']' + '\r' ) sys.stdout.flush()def download (video_list, title, bid) : for i in video_list: opener = urllib.request.build_opener() opener.addheaders = [ ('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' ), ('Accept' , '*/*' ), ('Accept-Language' , 'en-US,en;q=0.5' ), ('Accept-Encoding' , 'gzip, deflate, br' ), ('Range' , 'bytes=0-' ), ('Referer' , 'https://www.bilibili.com/video/' +bid), ('Origin' , 'https://www.bilibili.com' ), ('Connection' , 'keep-alive' ), ] filename=os.path.join('D:\\video' , r'{}_{}.mp4' .format(bid,title)) try : urllib.request.install_opener(opener) urllib.request.urlretrieve(url=i, filename=filename, reporthook=schedule_cmd) except : print(bid + "下載異常,文件:" + filename)
總結(jié)本篇介紹了通過爬蟲的方式下載 B 站視頻,,代碼量不多就 130 行左右,。大家也可以擴展一下,,自動下載關(guān)注 up 主的視頻,。
參考[1] AID 轉(zhuǎn) BID https://zhuanlan.zhihu.com/p/117358823