?【軟核干貨】如何爬取B站視頻的封面圖片
作者? |? 三級(jí)狗
來源 | 原? 創(chuàng)
緣起
周末在B站刷視頻的時(shí)候,紅燈區(qū)...啊呸!鋼琴區(qū)一個(gè)up的視頻突然拽住了我的眼球,一連翻看了她的幾個(gè)視頻之后,我發(fā)現(xiàn)這個(gè)up每次的封面確實(shí)有點(diǎn)東西!
于是突然來了興致,想通過自己為所欲為的技術(shù)手段,實(shí)現(xiàn)一波兒封面批量自提。
簡(jiǎn)單調(diào)查了一番,發(fā)現(xiàn)這東西用Pyhton爬蟲搞,不僅難度不大而且很有搞頭!于是很快便開始上手捋邏輯。
實(shí)施
第一次接觸爬蟲,就想要那種短平快的東西,所以我把邏輯抽離的非常宏觀:
先知道目標(biāo)圖片的網(wǎng)址是什么? 通過代碼訪問這個(gè)網(wǎng)址,拿到目標(biāo)頁(yè)面的全部代碼。 解析這個(gè)代碼,找到圖片所在區(qū)域ID 遍歷區(qū)域內(nèi)所有的內(nèi)容,找到每一個(gè)img標(biāo)簽,獲取它的src屬性就是圖片的地址 通過代碼+地址下載對(duì)應(yīng)的圖片保存到本地 大功告成
上面的這幾步驟基本都能看懂,有幾個(gè)步驟需要一些技術(shù)支持,分別對(duì)應(yīng)是:
就是你訪問的地址 urllib2或者requests BeautifulSoup4 瀏覽器的F12+選擇器找一下 urllib
我把主邏輯理順后,寫成代碼也很簡(jiǎn)單(這段代碼不能用哈,不用看太細(xì)):
#?-*-?coding:utf-8?-*-
import?requests
from?bs4?import?BeautifulSoup
#指定要爬取的網(wǎng)站url
x?=?0
def?get_images(url):
????headers?=?{'Usar-Agent':'Mozilla/5.0?(Windows?NT?6.1;?WOW64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/72.0.3626.109?Safari/537.36'}
????req?=?urllib2.Request(url,headers=headers)#?用url地址創(chuàng)建一個(gè)request對(duì)象
????page?=?urllib2.urlopen(req,timeout=20)#打開網(wǎng)址
????contents?=?page.read()?#?獲取源碼
????res?=?requests.get(url,headers=headers,timeout=(5,5))
????print?(res.content)
????soup?=?BeautifulSoup(contents,'html.parser')?#?創(chuàng)建一個(gè)soup對(duì)象
????cover_imgs?=?soup.find_all('img')#?找到img標(biāo)簽??find只找一次,find_all找到所有
????for?cover_img?in?cover_img:#?遍歷list,選取屬性
????????link?=?cover_img.get('src');#獲取src圖片路徑
????????link.replace(".webp",".png")
????????print?(link);
????????#下載的文件,取名字
????????global?x
????????urllib.?urlretrieve(link,'image\%s.png'%x)
????????print?("Downloading?image?No.{}".format(x));
????????x?+=?1;
for?page?in?range(1,10):
????url?=?'https://space.bilibili.com/72956117/video?tid=0&page={}&keyword=&order=pubdate'.format(page)
????get_images(url)
阻礙
這段代碼的主邏輯是通的,思路也是完全按照上面的123456來的,但是就當(dāng)我已經(jīng)興奮地搓搓小手準(zhǔn)備爬圖的時(shí)候,卻遇到了很大的障礙:
「res.content拿到的并不是完整頁(yè)面的代碼」
拿到的只是一個(gè)主的html加一堆js文件的加載路徑,并沒有拿到包含著圖片標(biāo)簽的代碼。
也就是說,我通過瀏覽器訪問這個(gè)網(wǎng)址看到頁(yè)面的時(shí)候,其實(shí)已經(jīng)進(jìn)行過多次請(qǐng)求響應(yīng)了
而我通過代碼單獨(dú)請(qǐng)求這個(gè)網(wǎng)址,只拿到了單次請(qǐng)求主頁(yè)的內(nèi)容,所以這么搞并不能拿到指定的內(nèi)容。
在這個(gè)頁(yè)面上通過右鍵查看源代碼確認(rèn)了一下。確實(shí),這個(gè)頁(yè)面的源代碼就是這個(gè)樣子滴:
那這就比較難搞了,我該如何獲知瀏覽器發(fā)出的其他請(qǐng)求并模擬出來,然后通過返回拿到我想要的東西呢?
要知道一個(gè)優(yōu)秀的爬蟲大佬,那都是web前后端玩兒賊6的大佬,我一個(gè)搞C++客戶端的,對(duì)這些是一竅不通?。?!一時(shí)間讓我有點(diǎn)一籌莫展。
不過怎么說也是個(gè)大廠的網(wǎng)站,讓我一沒摸過爬蟲的人上來說爬就爬了是不是有點(diǎn)太low了。
再想想辦法,只能硬著頭皮看請(qǐng)求了。
柳暗花明
這是我訪問頁(yè)面的get請(qǐng)求:
后面跟的請(qǐng)求好多,我也不是很懂,只能是憑感覺找可疑的請(qǐng)求查驗(yàn)。
感覺上它應(yīng)該是訪問后臺(tái)的某個(gè)api接口,反饋回來的是一堆json數(shù)據(jù),然后前端根據(jù)數(shù)據(jù)給它渲染成了我們看到的亞子。
功夫不負(fù)有心人,就這么感覺了幾下還真讓我發(fā)現(xiàn)了一個(gè)可疑的:
看見那個(gè)api.開頭我就覺得有門,復(fù)制到瀏覽器試了一下,果然!
把這里面pic的地址扔到瀏覽器里一看!我的媽直接get到了1768*1080的原圖(在瀏覽器里F12查找元素能看到的,只有320*240的webp格式了)!比我電腦屏幕分辨率都高,興奮的我大腿都拍腫了!
這個(gè)突破口有了,我們回到技術(shù)上來!
現(xiàn)在直接從api拿到的是json數(shù)據(jù),所以現(xiàn)在思路大改!
根本不需要解析頁(yè)面,更不需要什么bs4,只需要訪問api接口,從數(shù)據(jù)里提取出圖片地址,下載圖片就完了。
不僅思路更加簡(jiǎn)短,難度也陡然下降。
比剛才的代碼還要簡(jiǎn)單,一共只有20行不到(這個(gè)是真的可以跑,注意身體~):
import?requests
import?json
import?urllib
x?=?0
def?get_images(url):
????headers?=?{'Usar-Agent':'Mozilla/5.0?(Windows?NT?6.1;?WOW64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/72.0.3626.109?Safari/537.36'}
????res?=?requests.get(url,headers=headers,timeout=(5,5))
????for?video?in?res.json()['data']['list']['vlist']:
????????global?x
????????urllib.request.urlretrieve("http:"+video['pic'],'image\%s.jpg'%x)
????????print?("Downloading?image?No.{}".format(x));
????????x?+=?1
for?page?in?range(1,10):
????url?=?'https://api.bilibili.com/x/space/arc/search?mid=72956117&ps=30&tid=0&pn={}&keyword=&order=pubdate&jsonp=jsonp'.format(page)
????get_images(url)
?裝上對(duì)應(yīng)的庫(kù)后直接python3就可以跑,執(zhí)行之前要在同級(jí)目錄創(chuàng)建一個(gè)名為
?image的文件夾,否則沒路徑會(huì)報(bào)錯(cuò)。
舉一反三
有了這個(gè)技術(shù)手段,其他up主的封面原圖,也不是問題。你需要做的只是:
打開這個(gè)up的個(gè)人主頁(yè)點(diǎn)投稿 按F12點(diǎn)到network頁(yè)面 刷新頁(yè)面,找到大量的webp圖片請(qǐng)求然后開始往上找。找到一個(gè)search?xxxx的請(qǐng)求 點(diǎn)擊就能看到Request url 項(xiàng)指定的真實(shí)api地址 把這個(gè)地址替換掉上面代碼里的url,執(zhí)行腳本就可以下圖片了 爬取的頁(yè)數(shù)根據(jù)需要自己調(diào)整range。
爬取的結(jié)果,你可以沒人的時(shí)候盡情欣賞:
這個(gè)爬蟲還是很簡(jiǎn)單的,幾乎可是說是入門都沒有的水平了。
真的要把爬蟲這門技術(shù)發(fā)展成可以掙錢吃飯的手藝,那難度就不是這個(gè)量級(jí)了,想要有所精進(jìn)的同學(xué),我個(gè)人非常推薦去看老陳的博客(https://www.cnblogs.com/c-x-a)和崔大的文章(https://cuiqingcai.com/)。
不吹不黑他們的文章憑借扎實(shí)的技術(shù)和清晰的思維邏輯,往公安局送了不少搞爬蟲的人(逃....
后記
當(dāng)然這個(gè)爬蟲只是爬取了男生喜歡看的
本來還想搞一個(gè)爬蟲爬一些女生喜歡看的,后來在糾結(jié)肌肉猛男和奶油小生的時(shí)候突然發(fā)覺:如果我知道女孩子喜歡什么?我怎么可能現(xiàn)在還單身?既然我現(xiàn)在還是單身,說明我根本不明白女生喜歡什么。
我都不知道人家喜歡什么我還給人家瞎爬個(gè)屁哦!
于是果斷放棄了這部分女粉的訴求。
實(shí)在不甘心的女同學(xué)可以私信留言告訴我你想看什么,我看有沒有時(shí)間搞。
最后關(guān)于這個(gè)UP主,大家爬爬圖片就好,我本意是不想給她帶哪怕一個(gè)人頭的流量的。
她早年的視頻封面風(fēng)格還是這樣的:
那時(shí)候還是挺正經(jīng)的,后來發(fā)覺擦邊球漲粉的套路后就一發(fā)不可收拾了
另外主要不想帶流量的原因是我在了解過程中也發(fā)現(xiàn):這個(gè)UP似乎在外網(wǎng)發(fā)表過一些臺(tái)獨(dú)言論,因此每次發(fā)視頻評(píng)論彈幕都比視頻熱鬧。而這UP從來都視而不見,建議B站能夠嚴(yán)查!
