天天看點

爬取B站視訊資訊竟如此簡單!!擷取B站視訊資訊最後

追求一個人不能全靠【感動】。

準時早安晚安,風雨無阻地送三餐,并不會讓對方喜歡上你,甚至有可能會厭惡你。

更加正确的做法是提升自己,讓對方感受到你的【魅力】和【踏實】。

一個女人能愛上你,是愛你的人,而不是你的跪舔。

懂得噓寒問暖,卻毫無追求,認不清現實。

每天想着各種拌飯讨好她,雖然會讓她開心,但并不會讓她産生喜歡,更别談愛上你。

這種男人并不會真正給對方帶來【安全感】,即使對方說了【我愛你】,也不會太長久,舔到最後隻會是一場空。

擷取B站視訊資訊

今天為大家帶來的實戰項目是擷取B站的視訊資訊資料。B站的視訊資訊資料主要有哪些呢?

  • 視訊點贊數。
  • 視訊投币數
  • 視訊收藏數
  • 視訊彈幕數
  • 視訊播放時長
  • 視訊釋出時間

上面所說的幾點内容就是視訊的主要資訊資料,我們的目的就是要将這些資料擷取下來,并将資料儲存到資料庫中。

目标網頁分析

我們爬取的資料是來自《觀察者網》的所有視訊的資料。

對于B站的每一個視訊來說每一個視訊都有一個AV号。

例如,我們點選第一個視訊,在裡面我們就可以看到視訊的各個資料了,比如說:點贊數、投币數、收藏數、彈幕數、視訊播放時長、視訊釋出時間。

爬取B站視訊資訊竟如此簡單!!擷取B站視訊資訊最後
爬取B站視訊資訊竟如此簡單!!擷取B站視訊資訊最後

看到了嗎?視訊的主要資料剛剛好是在網頁中呈現出來的。

為了確定資料的準确與無誤,我們需要點選Network,檢視Response,看看裡面是不是同樣也包含此類資料,如果包含相同資料的話,說明資料确實包含在網頁中,而不是通過js或者是Ajax異步加載出來的,當然我更希望是通過這兩個手段去渲染資料,我也容易一點。

爬取B站視訊資訊竟如此簡單!!擷取B站視訊資訊最後

如上圖所示,資料的确包含在網頁中,也就是說可以通過Python正常的進行模拟通路并擷取到我們想要的資料。

分析到這裡,我就先把本次爬取的代碼架構先寫出來吧

# 擷取網頁資訊
def get_html(url):
    pass

# 解析資料
def parse_html(html):
    pass

# 儲存資料
def save_data(data):
    pass

           

擷取網頁資訊

接下來就是将網頁中我們需要的資料提取出來,這裡我選擇使用xpath來提取資料。

相對來說xpath比較簡單,具體代碼如下所示:

def parse_html(html):
    html = etree.HTML(html)
    title = html.xpath('//span[contains(@class, "tit")]/text()')[0]
    danmu = int(re.findall('\d+', html.xpath('//span[@class="dm"]/text()')[0])[0])
    times = html.xpath('//div[@class="video-data"]/span[3]/text()')[0]
    like = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="like"]/@title')[0])[0])
    coin =int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[2]/@title')[0])[0])
    collect = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="collect"]/@title')[0])[0])
    return title, danmu, times, like, coin, collect
           

我對上面的代碼做簡單的說明:

title代表的是視訊的标題;

danmu代表的是視訊的彈幕數;

times代表的是視訊釋出時間;

like代表的是是點贊數;

coin代表的是投币數;

collect代表的是收藏數。

相信xpath文法不需要我再做任何的解釋了吧。

認真閱讀本文的小夥伴一定可以發現這邊擷取的資料還差一個,那就是視訊時長。經過我的仔細查找之後也沒有在響應中找到視訊的播放時長,說實話,我當時瞬間懵了。

于是我傳回上一級連結,

并将頁面重新整理,我很幸運,終于被我給找着了。

爬取B站視訊資訊竟如此簡單!!擷取B站視訊資訊最後

在一個頁面中一共有30個視訊,視訊的标題、ID号、播放時長都在這面了。從上圖可以很明顯的看出,資料是通過Ajax異步加載出來的json資料。

擷取所有視訊的連結與時間

通過對上面的分析,我已經有了大體的思路了。三十個視訊的ID号都在這裡了,這個是第一頁視訊的所有資訊,首先我必須知道它所給的API在不同的頁面會有什麼變化。

# 第一頁
https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn=1&keyword=&order=pubdate&jsonp=jsonp

# 第二頁
https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn=2&keyword=&order=pubdate&jsonp=jsonp

# 第三頁
https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn=3&keyword=&order=pubdate&jsonp=jsonp
           

變化的參數就是pn,随着頁面的變化而變化。

是以,我在這裡定義了兩個方法,分别擷取視訊的連結與視訊的播放時長。

具體代碼如下:

# 擷取1-10頁的視訊連結
def get_url():
    urls = []
    # times = []
    for page in range(1, 10):
        api_url = f'https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn={page}&keyword=&order=pubdate&jsonp=jsonp'
        data = requests.get(api_url, headers=headers).json()
        bvids = jsonpath.jsonpath(data, '$.data..vlist..bvid')
        time.sleep(0.5)
        url = ['https://www.bilibili.com/video/'+bvid for bvid in bvids]
        urls.extend(url)
    return urls

# 擷取1-10頁的視訊播放時長
def get_length():
    times = []
    for page in range(1, 10):
        api_url = f'https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn={page}&keyword=&order=pubdate&jsonp=jsonp'
        data = requests.get(api_url, headers=headers).json()
        length = jsonpath.jsonpath(data, '$.data..vlist..length')
        times.extend(length)
        time.sleep(0.5)
    return times
           

修改擷取網頁資訊代碼

現在我是已經成功拿到視訊的播放時長了,為了友善存儲,是以,需要将在擷取網頁資訊代碼中來調用擷取視訊播放時長的方法即可。修改之後的代碼如下:

def parse_html(html):
    global pages
    lengths = get_length()

    html = etree.HTML(html)
    title = html.xpath('//span[contains(@class, "tit")]/text()')[0]
    danmu = int(re.findall('\d+', html.xpath('//span[@class="dm"]/text()')[0])[0])
    times = html.xpath('//div[@class="video-data"]/span[3]/text()')[0]
    like = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="like"]/@title')[0])[0])
    coin =int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[2]/@title')[0])[0])
    collect = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="collect"]/@title')[0])[0])

    return title, danmu, times, like, coin, collect, lengths[pages]
           

因為,擷取的播放時長,是放在一個清單中,是以,我在定義了一個全局變量:pages,當我調用完**save_data()**方法之後使pages加1即可。

這個pages其實表示的是每個視訊的播放時長。

儲存資料

本次儲存的資料是放在MySQL資料庫中,具體代碼如下所示:

def save_data(data):
    host = 'localhost'
    user = 'root'
    password = '密碼'
    port = 3306
    db = pymysql.connect(host=host, user=user, password=password, port=port, db='bilibli')
    cursor = db.cursor()
    sql = 'insert into data3(title, danmu, vediotime, likecount, coin, collect, vediolength) values (%s, %s, %s, %s, %s, %s, %s)'
    print(data)

    try:
        cursor.execute(sql, data)
        db.commit()
        print('插入成功')
    except Exception as e:
        print(e)
        db.rollback()
        print('插入失敗')
           

注意在此之前必須要先建立好資料庫bilibli和資料表data3,然後再調用上面的方法,将資料儲存至資料庫中。

爬取B站視訊資訊竟如此簡單!!擷取B站視訊資訊最後

本篇文章隻做簡單的爬蟲知識,不做資料分析。

以本文為例,各位小夥伴們可以去爬取你們喜歡的UP主的視訊詳細資料,可以多爬取一個資料,比如說播放量,做B站視訊Top100的資料分析,來鞏固自己的爬蟲知識和技巧,順便再學習了簡單的資料可視化知識。

最後

别人的建議隻是參考答案,人生沒有标準答案。

你不需要去抄别人,逼自己和别人一模一樣,寫你覺得對的答案就好。

看完文章,覺得對你有幫助的,可以給啃書君點個【在看】,我會繼續努力,和你們一起成長前進。

文章的每一個字都是我用心敲出來的,隻希望對得起每一位關注我的人。

點個【在看】,讓我知道你們也在為人生【拼盡全力】。

我是啃書君,一個專注于學習的人,你懂的越多,你不懂的越多。更多精彩内容,我們下期再見!

respect