1. 程式人生 > 實用技巧 >我發現這個up封面確實有點東西,爬取B站視訊的封面圖片

我發現這個up封面確實有點東西,爬取B站視訊的封面圖片

前言

本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯絡我們以作處理。

作者|三丨級丨狗

來源|帝都高階待業專家

緣起

週末在B站刷視訊的時候,鋼琴區一個up的視訊突然拽住了我的眼球,一連翻看了她的幾個視訊之後,我發現這個up每次的封面確實有點東西!

於是突然來了興致,想通過自己為所欲為的技術手段,實現一波兒封面批量自提。

簡單調查了一番,發現這東西用Pyhton爬蟲搞,不僅難度不大而且很有搞頭!於是很快便開始上手捋邏輯。

實施

第一次接觸爬蟲,就想要那種短平快的東西,所以我把邏輯抽離的非常巨集觀:

  1. 想知道目標圖片的網址是什麼?
  2. 通過程式碼訪問這個網址,拿到目標頁面的全部程式碼。
  3. 解析這個程式碼,找到圖片所在區域ID
  4. 遍歷區域內所有的內容,找到每一個img標籤,獲取它的src屬性就是圖片的地址
  5. 通過程式碼+地址下載對應的圖片儲存到本地
  6. 大功告成

上面的這幾步驟基本都能看懂,有幾個步驟需要一些技術支援,分別對應是:

  1. 就是你訪問的地址
  2. urllib2或者requests
  3. BeautifulSoup4
  4. 瀏覽器的F12+選擇器找一下
  5. urllib

我把主邏輯理順後,寫成程式碼也很簡單(這段程式碼不能用哈,不用看太細):

#-*-coding:utf-8-*-
importrequests
frombs4importBeautifulSoup

#指定要爬取的網站url
x=0
defget_images(url):
headers={'Usar-Agent':'Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/72.0.3626.109Safari/537.36'}
req=urllib2.Request(url,headers=headers)#用url地址建立一個request物件
page=urllib2.urlopen(req,timeout=20)#開啟網址
contents=page.read()#獲取原始碼

res=requests.get(url,headers=headers,timeout=(5,5))
print(res.content)
soup=BeautifulSoup(contents,'html.parser')#建立一個soup物件
cover_imgs=soup.find_all('img')#找到img標籤find只找一次,find_all找到所有
forcover_imgincover_img:#遍歷list,選取屬性
link=cover_img.get('src');#獲取src圖片路徑
link.replace(".webp",".png")
print(link);

#下載的檔案,取名字
globalx
urllib.urlretrieve(link,'image\%s.png'%x)
print("DownloadingimageNo.{}".format(x));
x+=1;

forpageinrange(1,10):
url='https://space.bilibili.com/72956117/video?tid=0&page={}&keyword=&order=pubdate'.format(page)
get_images(url)

阻礙

這段程式碼的主邏輯是通的,思路也是完全按照上面的123456來的,但是就當我已經興奮地搓搓小手準備爬圖的時候,卻遇到了很大的障礙:

「res.content拿到的並不是完整頁面的程式碼」

拿到的只是一個主的html加一堆js檔案的載入路徑,並沒有拿到包含著圖片標籤的程式碼。

也就是說,我通過瀏覽器訪問這個網址看到頁面的時候,其實已經進行過多次請求響應了

而我通過程式碼單獨請求這個網址,只拿到了單次請求主頁的內容,所以這麼搞並不能拿到指定的內容。

在這個頁面上通過右鍵檢視原始碼確認了一下。確實,這個頁面的原始碼就是這個樣子滴:

那這就比較難搞了,我該如何獲知瀏覽器發出的其他請求並模擬出來,然後通過返回拿到我想要的東西呢?

要知道一個優秀的爬蟲大佬,那都是web前後端玩兒賊6的大佬,我一個搞C++客戶端的,對這些是一竅不通啊?!一時間讓我有點一籌莫展。

不過怎麼說也是個大廠的網站,讓我一沒摸過爬蟲的人上來說爬就爬了是不是有點太low了。

再想想辦法,只能硬著頭皮看請求了。

柳暗花明

這是我訪問頁面的get請求:

後面跟的請求好多,我也不是很懂,只能是憑感覺找可疑的請求查驗。

感覺上它應該是訪問後臺的某個api介面,反饋回來的是一堆json資料,然後前端根據資料給它渲染成了我們看到的樣子。

功夫不負有心人,就這麼感覺了幾下還真讓我發現了一個可疑的:

看見那個api.開頭我就覺得有門,複製到瀏覽器試了一下,果然!

把這裡面pic的地址扔到瀏覽器裡一看!我的媽直接get到了1768*1080的原圖(在瀏覽器裡F12查詢元素能看到的,只有320*240的webp格式了)!比我電腦螢幕解析度都高,興奮的我大腿都拍腫了!

這個突破口有了,我們回到技術上來!

現在直接從api拿到的是json資料,所以現在思路大改!

根本不需要解析頁面,更不需要什麼bs4,只需要訪問api介面,從資料裡提取出圖片地址,下載圖片就完了。

不僅思路更加簡短,難度也陡然下降。

比剛才的程式碼還要簡單,一共只有20行不到(這個是真的可以跑,注意身體~):

importrequests
importjson
importurllib

x=0
defget_images(url):
headers={'Usar-Agent':'Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/72.0.3626.109Safari/537.36'}
res=requests.get(url,headers=headers,timeout=(5,5))
forvideoinres.json()['data']['list']['vlist']:
globalx
urllib.request.urlretrieve("http:"+video['pic'],'image\%s.jpg'%x)
print("DownloadingimageNo.{}".format(x));
x+=1
forpageinrange(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)

裝上對應的庫後直接python3就可以跑,執行之前要在同級目錄建立一個名為image的資料夾,否則沒路徑會報錯。

舉一反三

有了這個技術手段,其他up主的封面原圖,也不是問題。你需要做的只是:

  • 開啟這個up的個人主頁點投稿
  • 按F12點到network頁面
  • 重新整理頁面,找到大量的webp圖片請求然後開始往上找。找到一個search?xxxx的請求
  • 點選就能看到Request url 項指定的真實api地址
  • 把這個地址替換掉上面程式碼裡的url,執行指令碼就可以下圖片了
  • 爬取的頁數根據需要自己調整range。

爬取的結果,你可以沒人的時候盡情欣賞:

這個爬蟲還是很簡單的,幾乎可以說是入門都沒有的水平了。

PS:如有需要Python學習資料的小夥伴可以加下方的群去找免費管理員領取

可以免費領取原始碼、專案實戰視訊、PDF檔案等