追求一個人不能全靠【感動】。
準時早安晚安,風雨無阻地送三餐,并不會讓對方喜歡上你,甚至有可能會厭惡你。
更加正确的做法是提升自己,讓對方感受到你的【魅力】和【踏實】。
一個女人能愛上你,是愛你的人,而不是你的跪舔。
懂得噓寒問暖,卻毫無追求,認不清現實。
每天想着各種拌飯讨好她,雖然會讓她開心,但并不會讓她産生喜歡,更别談愛上你。
這種男人并不會真正給對方帶來【安全感】,即使對方說了【我愛你】,也不會太長久,舔到最後隻會是一場空。
擷取B站視訊資訊
今天為大家帶來的實戰項目是擷取B站的視訊資訊資料。B站的視訊資訊資料主要有哪些呢?
- 視訊點贊數。
- 視訊投币數
- 視訊收藏數
- 視訊彈幕數
- 視訊播放時長
- 視訊釋出時間
上面所說的幾點内容就是視訊的主要資訊資料,我們的目的就是要将這些資料擷取下來,并将資料儲存到資料庫中。
目标網頁分析
我們爬取的資料是來自《觀察者網》的所有視訊的資料。
對于B站的每一個視訊來說每一個視訊都有一個AV号。
例如,我們點選第一個視訊,在裡面我們就可以看到視訊的各個資料了,比如說:點贊數、投币數、收藏數、彈幕數、視訊播放時長、視訊釋出時間。
看到了嗎?視訊的主要資料剛剛好是在網頁中呈現出來的。
為了確定資料的準确與無誤,我們需要點選Network,檢視Response,看看裡面是不是同樣也包含此類資料,如果包含相同資料的話,說明資料确實包含在網頁中,而不是通過js或者是Ajax異步加載出來的,當然我更希望是通過這兩個手段去渲染資料,我也容易一點。
如上圖所示,資料的确包含在網頁中,也就是說可以通過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文法不需要我再做任何的解釋了吧。
認真閱讀本文的小夥伴一定可以發現這邊擷取的資料還差一個,那就是視訊時長。經過我的仔細查找之後也沒有在響應中找到視訊的播放時長,說實話,我當時瞬間懵了。
于是我傳回上一級連結,
并将頁面重新整理,我很幸運,終于被我給找着了。
在一個頁面中一共有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,然後再調用上面的方法,将資料儲存至資料庫中。
本篇文章隻做簡單的爬蟲知識,不做資料分析。
以本文為例,各位小夥伴們可以去爬取你們喜歡的UP主的視訊詳細資料,可以多爬取一個資料,比如說播放量,做B站視訊Top100的資料分析,來鞏固自己的爬蟲知識和技巧,順便再學習了簡單的資料可視化知識。
最後
别人的建議隻是參考答案,人生沒有标準答案。
你不需要去抄别人,逼自己和别人一模一樣,寫你覺得對的答案就好。
看完文章,覺得對你有幫助的,可以給啃書君點個【在看】,我會繼續努力,和你們一起成長前進。
文章的每一個字都是我用心敲出來的,隻希望對得起每一位關注我的人。
點個【在看】,讓我知道你們也在為人生【拼盡全力】。
我是啃書君,一個專注于學習的人,你懂的越多,你不懂的越多。更多精彩内容,我們下期再見!
respect