當前位置:
首頁 > 知識 > Python爬取B站,鹹魚的正確 GET 姿勢

Python爬取B站,鹹魚的正確 GET 姿勢

分析目標

我們選定 B站的 動畫區 進行測試,打開後我們發現有好多好多圖....

但當我們使用 F12 查看這些圖片的時候,發現並沒有圖片的地址...

這就是目前大多網站使用的 Ajax 技術動態載入數據的鍋,可遇到這種情況這麼辦呢?別急別急,我們知道這些圖片的地址一定是需要載入的,而目前常見WEB傳輸數據的基本就是方式 XML 和 Json (其實是我就知道這兩種...),那好我們去看看請求的 XML 和 Json 文件。

以下省略查找過程....

這個是 MAD·AMV 最新動態的 Json 文件,利用上面相同的方法,我們找到 3D區、短片·配音區、綜合區 以及 右邊排行部分 的相應 json 地址。

找到 Json 數據後,我們需要開始分析如何才能從中拿到 圖片地址了

好在 Chrome 瀏覽器提供了一個 Preview 功能,自動幫我們整理好 數據,如下

這樣就很清晰啦,我們只需要一層層解析拿到 pic 即可。於是我們這樣寫:

我們利用 requests 內置的 json 解碼器,很不幸,報錯:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

它提示說:解碼 Json 數據的時候出了問題,可能是在 第一行 第一列,咦?好奇怪,剛才不是用瀏覽器看過結構了嗎,沒毛病啊,怎麼還在報錯:Σ(  ̄ ̄||)

別急別急,我們先看看原始的 Json 數據長啥樣?用 瀏覽器打開上面的 json 鏈接就可以了。

(/TДT)/ 前面的那些字母是幹嘛的呀,為什麼還有括弧啊!

所以我們知道了 Json 解析錯誤 的原因啦:後面在處理的時候把前面的這部分刪掉就好啦,另外我們也發現了archives這個關鍵字,我們在上一張圖看見過的哦,有印象嗎?啊,你說沒有呀,沒關係,這裡你只需要記著它是一個 List 的數據類型就好了呀!

開碼開碼

先看看 解析部分怎麼寫:

獲取 Json 數據

解析 Json 數據,並保存其中的 所有的圖片鏈接

注意去重

importjson

importrequests

importre

classBiliBiliSpider(object):def__init__(self):self._images = [] self._oldImages = []# 保存已經獲取過的 圖片地址

def_getImages(self, url):content = requests.get(url).text dic = json.loads(re.match(r ^([a-zA-Z0-9_(]+)(.*)())$ , content).group(2)) data = dic[ data ]

# 判斷是 動態區 和 還是 評論區的數據if archives indata: final = data[ archives ]

else: final = data

foriinrange(len(final)): image = final[i][ pic ]

ifimagenotinself._oldImages:# 去重self._images.append(image) self._oldImages.append(image)

defgetResult(self, url):self._getImages(url) temp = self._images self._images = []

returntemp

OK,接下來寫下載器:

獲取需要下載的 圖片地址

進行下載

我這裡是用數字作為圖片的名字保存起來的,數字用一個 count.txt 文件保存,為了好看一點吧...

importrequests

classBiliBiliDownloader(object):

def__init__(self):

self._images = []

defaddNewImages(self, images):

forimageinimages:

self._images.append(image)

# 獲取後綴名defgetFinName(self, url):ifurl[-4:].find( . ) >-1: fin = url[-4:]

else: fin = url[-5:]

returnfin

defimageDownload(self):

withopen( count.txt , rb )asf: temp = int(f.read().decode( utf-8 ))

forurlinself._images: name = images/ + str(temp) + self.getFinName(url)print( Downloading {}... .format(name)) r = requests.get(url)

withopen(name, wb )asf: f.write(r.content) temp +=1self._images = []

withopen( count.txt , wb )asf: f.write(str(temp).encode( utf-8 ))

最後是調度器:

為了防止被當作是 惡意訪問 從而被封 IP,這裡我們選擇犧牲時間,取巧使用 sleep(x) ,讓其等待一段時間之後再發出請求。

fromBiliBiliSpiderimportBiliBiliSpider

fromBiliBiliDownloaderimportBiliBiliDownloader

importtime

classBiliBiliMain(object):def__init__(self):self._spider = BiliBiliSpider() self.downloader = BiliBiliDownloader()

defCrawl(self, url):images = self._spider.getResult(url) self.downloader.addNewImages(images) self.downloader.imageDownload()

if__name__ == __main__ :

# 添加相應位置的 json 文件json_url_MAD = https://xxx... json_url_MAD_rank = https://xxx... ... json_url_list = [] json_url_list.append(json_url_MAD) json_url_list.append(...) ...

bilibili = BiliBiliMain()

# 設置一個標誌位,循環爬取多少次之後自動退出。flag =1whileTrue:

forurlinjson_url_list: bilibili.Crawl(url) time.sleep(30)# 防止被當作是惡意請求。。。time.sleep(100)# 防止被當作是惡意請求。。。flag +=1ifflag >15:

break

運行效果:

總結:

你們可能會有疑問,你這個,根本沒有代理、沒有混淆IP防止反爬、也沒有模擬 Ajax 請求動態抓取云云~

那我可以很負責的告訴你,你!走錯地方了!你要找的技術貼出門右拐!( ̄へ ̄)

關於取巧

我們恰巧使用的是 B站的 Ajax 技術,只要哪個視頻有了最新評論(或者是一下其它的條件),就會使用 Ajax 將最新的數據取出來。就像下面這樣:

所以可能在訪問人數多的時候,更新越快,越有可能獲得更多不同的圖片啦!之後你就可以在吃飯的時候,把它掛起,然後吃飯回來就會發現有好多好多的圖片!(=?ω?=)

關於以後

之後會陸續的更新文章,希望能夠找到小夥伴一起學習呀

關注+轉發

感謝大家

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 python 的精彩文章:

用 Python 做導熱問題的數值計算
2 雖然我用來切西瓜,但Python其實是把屠龍刀
高盛最新調查:Python超過漢語成為未來最重要技能,你準備學哪種編程語言?
數據專家必知必會的 7款Python 工具
為什麼說Python會成為最流行的編程語言?

TAG:python |