使用 Python 下載 B 站視頻

文 |?某某白米飯
來源:Python 技術(shù)「ID: pythonall」

B 站,一個月活用戶達到 1.72 的視頻網(wǎng)站,有時候會因為某些未知的原因?qū)е路湃胧詹貖A的視頻失效,為了防止視頻被和諧、被失效,身為 Pythonista 來擼一個 B 站的視頻下載器。
分析頁面
首先我們在 B 站點開一個視頻(https://www.bilibili.com/video/BV1Vh411Z7j5)用 F12 分析一波,在下圖中可以看到有多個 m4s 結(jié)尾的鏈接,并且響應的類型是 video/mp4。

把面板打到 Elements 界面,找到一個 window.playinfo 的 javascript 變量,并且內(nèi)容和上圖中的 url 類似,都是 m4s 鏈接,目標已找到。

獲取標題和鏈接
抓取視頻頁面,并用 BeautifulSoup 模塊解析頁面,獲取視頻標題和鏈接(https://www.bilibili.com/video/BV17K4y1x7gs)。
def __init__(self, bv):# 視頻頁地址self.url = 'https://www.bilibili.com/video/' + bv# 下載開始時間self.start_time = time.time()def get_vedio_info(self):try:headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'}response = requests.get(url = self.url, headers = headers)if response.status_code == 200:bs = BeautifulSoup(response.text, 'html.parser')# 取視頻標題video_title = bs.find('span', class_='tit').get_text()# 取視頻鏈接pattern = re.compile(r"window\.__playinfo__=(.*?)$", re.MULTILINE | re.DOTALL)script = bs.find("script", text=pattern)result = pattern.search(script.next).group(1)temp = json.loads(result)# 取第一個視頻鏈接for item in temp['data']['dash']['video']:if 'baseUrl' in item.keys():video_url = item['baseUrl']breakreturn {'title': video_title,'url': video_url}except requests.RequestException:print('視頻鏈接錯誤,請重新更換')
示例結(jié)果:
{'title': '《屬于周杰倫的情歌王2.0》安安靜靜的回憶有杰倫陪伴的20年','url': 'http://cn-jszj-dx-v-06.bilivideo.com/upgcxcode/34/57/214635734/214635734_nb2-1-30080.m4s?expires=1595538100&platform=pc&ssig=Q5uom_rGdPasJhHBvna8tw&oi=3027480765&trid=347f5dc41e9647e2a6dce48286d0b478u&nfc=1&nfb=maPYqpoel5MI3qOUX6YpRA==&cdnid=2725&mid=0&cip=222.186.35.71&orderid=0,3&logo=80000000'}
下載視頻
下載視頻使用 urllib 模塊的 urlretrieve(url, filename=None, reporthook=None) 方法,它可以將遠程數(shù)據(jù)直接下載到本地。
def download_video(self, video):title = re.sub(r'[\/:*?"<>|]', '-', video['title'])url = video['url']filename = title + '.mp4'opener = urllib.request.build_opener()opener.addheaders = [('Origin', 'https://www.bilibili.com'),('Referer', self.url),('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36')]urllib.request.install_opener(opener)urllib.request.urlretrieve(url = url, filename = filename)
示例結(jié)果:

一個視頻下載完成。
進度條
現(xiàn)在還缺一個進度條,沒有進度條的下載工具是一個沒有靈魂的下載工具。

def schedule(self, blocknum, blocksize, totalsize):'''urllib.urlretrieve 的回調(diào)函數(shù):param blocknum: 已經(jīng)下載的數(shù)據(jù)塊:param blocksize: 數(shù)據(jù)塊的大小:param totalsize: 遠程文件的大小:return:'''percent = 100.0 * blocknum * blocksize / totalsizeif percent > 100:percent = 100s = ('#' * round(percent)).ljust(100, '-')sys.stdout.write("%.2f%%" % percent + '[ ' + s +']' + '\r')sys.stdout.flush()
示例結(jié)果:

最后更新一下下載視頻的代碼,加入 reporthook 參數(shù)。
urllib.request.urlretrieve(url = url, filename = filename, reporthook = self.schedule)總結(jié)
簡單的一個 B 站視頻下載工具到這就完成了,有興趣的話大伙可以試試下載 B 站的番劇,似乎和普通的視頻不一樣。
PS:公號內(nèi)回復「Python」即可進入Python 新手學習交流群,一起 100 天計劃!
老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點一下,如果感覺文章內(nèi)容不錯的話,記得分享朋友圈讓更多的人知道!


【代碼獲取方式】
識別文末二維碼,回復:200727