爬蟲實戰(zhàn):超詳細,超級細!如何自動化爬取bilibili視頻

## ***爬蟲實戰(zhàn):如何自動化爬取bilibili視頻***

## **1.**使用的python模塊


import requests

import json

from multiprocessing import Pool

import os

from lxml import etree

import regex


爬取的網(wǎng)站:[B站](https://www.bilibili.com/)完整的代碼在最后

## 2.獲取我們所需要的的網(wǎng)站視頻url


進入某個專區(qū)

比如我現(xiàn)在進入動畫專區(qū),現(xiàn)在我想要按視頻熱度爬取


F12可以幫我們觀察網(wǎng)站隨頁數(shù)的變化

當你點擊某一頁,比如第二頁,你就會發(fā)現(xiàn)在下圖我所定位的6500ms 到7000ms區(qū)間中有一條信息

(當然時間區(qū)間不一定相同,主要是當你點擊時,會出現(xiàn)一個不合群的信息,那這一般就是ajax請求。)

這其實就ajax異步請求

我們所需要的東西都在里面


點擊這個請求

會出現(xiàn)如下界面

很明顯,這個result ,這個英文單詞意義太明顯了。

再次點擊進去


result里面一系列,我們可以觀察我們所爬取的界面

來確定是否是我們所需要的的信息

很明顯的確是我們所需要的,并且是一個json對象


到現(xiàn)在為止我們需要視頻的url,title

也就是里面的arcurl,title

也就是說我們找到了正確的請求,現(xiàn)在我們要返回到請求頭,來構(gòu)造我們的請求頭


我們只需要根據(jù)參數(shù)來構(gòu)造請求頭就可以了

其中很多參數(shù)我們并不知道是什么,但無所謂

我們只需使用控制變量法,一個一個刪除然后再次請求就可以確定哪個參數(shù)是重要的,哪個不重要

這里我就不演示了,

這些參數(shù)我們可能不明白什么意思,但里面還是有一些很明顯的參數(shù),比如page,這個就是頁數(shù),pagesize就是每頁的視頻數(shù)量



referer為防盜鏈

這樣我們就可以請求我們所需要的頁數(shù)


url='https://s.search.bilibili.com/cate/search?'

headers={

? ? 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36',

? ? 'referer': 'https://www.bilibili.com/'

}

params = {

? ? ? ? 'main_ver': 'v3',

? ? ? ? 'search_type': 'video',

? ? ? ? 'view_type': 'hot_rank',

? ? ? ? 'order': 'click',

? ? ? ? 'copy_right': '-1',

? ? ? ? 'cate_id': '24',

? ? ? ? 'page': page,

? ? ? ? 'pagesize': 20,

? ? ? ? 'jsonp': 'jsonp',

? ? ? ? 'time_from': '20200912',

? ? ? ? 'time_to': '20200919'

? ? }

? ? try:

? ? ? ? res = session.get(url, headers=headers, params=params)

? ? ? ? res.raise_for_status()

? ? except Exception as e:

? ? ? ? print(e)


json.loads()可以把字符串變?yōu)閖son

這樣我們就提取了每一頁的視頻信息


result = json.loads(res.text)['result']

? ? for info in result:

? ? ? ? ? description = info['description']

? ? ? ? ? arcurl = info['arcurl']

? ? ? ? ? bvid = info['bvid']

? ? ? ? ? tag = info['tag']

? ? ? ? ? title = info['title']


## 3.真正的爬取視頻

我們再進入某個視頻 F12一下


這里出現(xiàn)了很多后綴為m4s的請求,再根據(jù)B站視頻進度條播放的特點 :陸陸續(xù)續(xù)的加載。

可以確定后綴為m4s的請求 應該是視頻的某一片段。那么我們同樣的只需要構(gòu)造他的請求頭應該可以同樣的獲取他的視頻。


到這里他的請求參數(shù)出現(xiàn)了很大的變化,不在像之前那么簡單易讀,很多參數(shù)很難確定

所以我們換一種方式。我們可以查看他的源代碼仔細觀看


在他的網(wǎng)頁源碼里面居然就有視頻的url,那我們就不需要解析請求頭了,偷個懶直接利用xpath解析源碼好吧。

好好觀察一下,這個Scripts的位置就可以,然后我們只需要里面的json數(shù)據(jù),所以我們再次定位了一下

[20:]就是這個意思,也可以用正則表達式更簡單的來解決

然后B站的視頻和音頻是分開放的,所以需要兩個url。


? ? ? ? ? ? try:

? ? ? ? ? ? ? ? response = session.get(arcurl, headers=headers)

? ? ? ? ? ? ? ? response.raise_for_status()

? ? ? ? ? ? except Exception as e:

? ? ? ? ? ? ? ? print(e)

? ? ? ? ? ? html = etree.HTML(response.content)

? ? ? ? ? ? video_infos = html.xpath('//head/script[5]/text()')[0][20:]

? ? ? ? ? ? video_json = json.loads(video_infos)

? ? ? ? ? ? VideoURL = video_json['data']['dash']['video'][0]['baseUrl']

? ? ? ? ? ? AudioURl = video_json['data']['dash']['audio'][0]['baseUrl']


## 4.文件存放

因為文件名有一定限制,有些字符不能取,但是B站視頻標題可以有這些字符,所以我們要用正則來替換

違法字符,替換的字符隨你 ,我選擇了 and。

然后先通過os模塊創(chuàng)建文件,

再利用BilibiliDownload函數(shù)下載


re = regex.compile('[/\\:?*><|"]')

? ? ? ? ? ? dirname = re.sub(' and ', title)

? ? ? ? ? ? if not os.path.exists('E:/Bilibili/' + dirname):

? ? ? ? ? ? ? ? os.makedirs('E:/Bilibili/' + dirname)

? ? ? ? ? ? ? ? print('目錄文件創(chuàng)建成功!')

? ? ? ? ? ? # 下載視頻和音頻

? ? ? ? ? ? print('正在下載 "' + dirname + '"? 視頻····')

? ? ? ? ? ? BiliBiliDownload(homeurl=url, url=VideoURL,

? ? ? ? ? ? ? ? ? ? ? ? ? ? name='E:/Bilibili' + '/' + dirname + '/' + dirname + '_Video_.mp4', session=session)

? ? ? ? ? ? print('正在下載 "' + dirname + '" 的音頻····')

? ? ? ? ? ? BiliBiliDownload(homeurl=url, url=AudioURl,

? ? ? ? ? ? ? ? ? ? ? ? ? ? name='E:/Bilibili' + '/' + dirname + '/' + dirname + '_Audio_.mp3',

? ? ? ? ? ? ? ? ? ? ? ? ? ? session=session)


def BiliBiliDownload(url, name, session):

? ? session.options(url=url, headers=headers,verify=False)

? ? # 每次下載1M的數(shù)據(jù)

? ? begin = 0

? ? end = 1024*512-1

? ? flag=0

? ? while True:

? ? ? ? headers.update({'Range': 'bytes='+str(begin) + '-' + str(end)})

? ? ? ? res = session.get(url=url, headers=headers,verify=False)

? ? ? ? if res.status_code != 416:

? ? ? ? ? ? begin = end + 1

? ? ? ? ? ? end = end + 1024*512

? ? ? ? else:

? ? ? ? ? ? headers.update({'Range': str(end + 1) + '-'})

? ? ? ? ? ? res = session.get(url=url, headers=headers,verify=False)

? ? ? ? ? ? flag=1

? ? ? ? with open(name, 'ab') as fp:

? ? ? ? ? ? fp.write(res.content)

? ? ? ? if flag==1:

? ? ? ? ? ? break


我最后使用了多進程,進程池加快了下載速度

## 5.代碼


import requests

import json

from multiprocessing import Pool

import os

from lxml import etree

import regex

headers={

? ? 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36',

? ? 'referer': 'https://www.bilibili.com/'

}

def BiliBiliDownload(homeurl,url, name, session=requests.session()):

? ? session.options(url=url, headers=headers,verify=False)

? ? # 每次下載1M的數(shù)據(jù)

? ? begin = 0

? ? end = 1024*512-1

? ? flag=0

? ? while True:

? ? ? ? headers.update({'Range': 'bytes='+str(begin) + '-' + str(end)})

? ? ? ? res = session.get(url=url, headers=headers,verify=False)

? ? ? ? if res.status_code != 416:

? ? ? ? ? ? begin = end + 1

? ? ? ? ? ? end = end + 1024*512

? ? ? ? else:

? ? ? ? ? ? headers.update({'Range': str(end + 1) + '-'})

? ? ? ? ? ? res = session.get(url=url, headers=headers,verify=False)

? ? ? ? ? ? flag=1

? ? ? ? with open(name, 'ab') as fp:

? ? ? ? ? ? fp.write(res.content)

? ? ? ? if flag==1:

? ? ? ? ? ? break

def get_Video_url(session,url,page):

? ? params = {

? ? ? ? 'main_ver': 'v3',

? ? ? ? 'search_type': 'video',

? ? ? ? 'view_type': 'hot_rank',

? ? ? ? 'order': 'click',

? ? ? ? 'copy_right': '-1',

? ? ? ? 'cate_id': '24',

? ? ? ? 'page': page,

? ? ? ? 'pagesize': 20,

? ? ? ? 'jsonp': 'jsonp',

? ? ? ? 'time_from': '20200912',

? ? ? ? 'time_to': '20200919'

? ? }

? ? try:

? ? ? ? res = session.get(url, headers=headers, params=params)

? ? ? ? res.raise_for_status()

? ? except Exception as e:

? ? ? ? print(e)

? ? result = json.loads(res.text)['result']

? ? for info in result:

? ? ? ? if int(info['play']) < 50000:

? ? ? ? ? ? description = info['description']

? ? ? ? ? ? arcurl = info['arcurl']

? ? ? ? ? ? bvid = info['bvid']

? ? ? ? ? ? tag = info['tag']

? ? ? ? ? ? title = info['title']

? ? ? ? ? ? try:

? ? ? ? ? ? ? ? response = session.get(arcurl, headers=headers)

? ? ? ? ? ? ? ? response.raise_for_status()

? ? ? ? ? ? except Exception as e:

? ? ? ? ? ? ? ? print(e)

? ? ? ? ? ? html = etree.HTML(response.content)

? ? ? ? ? ? video_infos = html.xpath('//head/script[5]/text()')[0][20:]

? ? ? ? ? ? video_json = json.loads(video_infos)

? ? ? ? ? ? VideoURL = video_json['data']['dash']['video'][0]['baseUrl']

? ? ? ? ? ? AudioURl = video_json['data']['dash']['audio'][0]['baseUrl']

? ? ? ? ? ? # 獲取文件夾的名稱

? ? ? ? ? ? re = regex.compile('[/\\:?*><|"]')

? ? ? ? ? ? dirname = re.sub(' and ', title)

? ? ? ? ? ? if not os.path.exists('E:/Bilibili/' + dirname):

? ? ? ? ? ? ? ? os.makedirs('E:/Bilibili/' + dirname)

? ? ? ? ? ? ? ? print('目錄文件創(chuàng)建成功!')

? ? ? ? ? ? # 下載視頻和音頻

? ? ? ? ? ? print('正在下載 "' + dirname + '"? 視頻····')

? ? ? ? ? ? BiliBiliDownload(homeurl=url, url=VideoURL,

? ? ? ? ? ? ? ? ? ? ? ? ? ? name='E:/Bilibili' + '/' + dirname + '/' + dirname + '_Video_.mp4', session=session)

? ? ? ? ? ? print('正在下載 "' + dirname + '" 的音頻····')

? ? ? ? ? ? BiliBiliDownload(homeurl=url, url=AudioURl,

? ? ? ? ? ? ? ? ? ? ? ? ? ? name='E:/Bilibili' + '/' + dirname + '/' + dirname + '_Audio_.mp3',

? ? ? ? ? ? ? ? ? ? ? ? ? ? session=session)

if __name__ == '__main__':

? ? session=requests.session()

? ? url='https://s.search.bilibili.com/cate/search?'

? ? pool=Pool(8)

? ? for i in range(5):

? ? ? ? pool.apply_async(get_Video_url,(session,url,i+1))

? ? pool.close()

? ? pool.join()


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容