前言
最近一直想要寫一個抖音爬蟲來批量下載抖音的短視頻,但是經過幾天的摸索我發現了一個很嚴重的問題......抖音實在是難爬!從一開始的網頁分析中就有着很多的坑,但是這幾天的摸索也不是一無所獲,我鼓搗出來了一個問題版的抖音爬蟲(操作較為復雜),所以我也想通過這篇博客來記錄下我分析網頁的過程,也想請教一下路過大佬們,歡迎各位大佬指出問題!
抖音爬蟲制作
選定網頁
想要爬取抖音上面的視頻,就要先找到可以刷小視頻的地址,於是我就開始在網上尋找網頁版的抖音。經過一番尋找,發現抖音根本就沒有網頁版的這個板塊,打開的網頁大多都是如下圖所示提示你下載app的網頁:
想要爬取小視頻的內容,沒有網頁地址可不行。於是我又想到了另一種尋找網頁的方法:
首先我打開了手機抖音,選定了一個喜歡的抖音號,使用復制鏈接的方法來嘗試是否可以在網頁中打開:
將鏈接粘貼到記事本中,發現它是長這個樣子的
ok,到現在為止,我已經選定了將這個頁面作為我獲取數據的起始頁面
選定起始頁之后,我的下一步想法是要去獲取這些小視頻的單獨的網頁地址,於是我又點擊了下面的這些小視頻。這里惡心的地方出現了,無論我點擊哪一個小視頻,彈出來的都是強迫你下載app的界面
於是我又想嘗試上面獲取到網頁的操作來獲取視頻的地址,再次打開手機上的抖音,在這個漫威的賬號下隨便打開一個視頻,點擊右下角的分享,復制它的鏈接:
這個鏈接地址長這個樣子:
打開的確實是視頻頁,點擊播放按鈕也可以播放視頻,所以這就是我們需要記住的第二個頁面。
分析網頁
現在又出現了一個比較麻煩的事情,在瀏覽器中輸入網址過后,跳轉到了視頻的播放頁,但是此時的播放頁地址經過了重定向生成了非常長的一串地址,乍一看毫無規律可講
正常來說請求第一種鏈接https://v.douyin.com/wGqCNG/和第二種重定向之后的鏈接都可以獲取到信息,但是我發現第一種鏈接地址是找不到規律的,所以我猜測第二種網址的規律會更加的好找,先把鏈接地址復制到記事本中:
看了這么長一串的鏈接,鏈接包含的內容也是非常多的,對分析規律有着很大的干擾,於是我試着精簡一下這個鏈接(刪掉鏈接里面的一些內容,看看是否還能找到頁面)經過了一次又一次的嘗試,我所得到的最簡單的網址如下:
這個網址依舊可以打開視頻頁,如果在刪掉一點東西,出來的就是抖音的宣傳頁,所以這個網址就是我所需要的最簡單網址
就一個網址當然是分析不出規律的,於是我又用同樣的方法來得到兩個新網址:
精簡網址之后,將三個網址放在一起觀察:
不難發現,這三個網址的區別就在於數字的不同
接下來猜測:這串數字會不會是每個視頻的Id值?
隨后我打開漫威影業抖音號,右擊檢查,按下ctrl+f搜索內容,在搜索框內分別搜索https://www.iesdouyin.com/share/video/6802189485015633160/?mid=6802184753988471559鏈接中的6802189485015633160和6802189485015633160兩個值
第一個值順利找到,就是我們所猜測的id值,但是搜索第二個值卻得不到任何的返回
這就叫我非常苦惱了,我開始想其他的辦法來獲取到這個值,我嘗試了抓包和其他的一些方法,但是都沒有找到這個值的相關信息。
我經過了一番思考,突然間冒出了一個想法:這個值是不是隨機生成的?
然后我做了一個小小的嘗試,我將這個值改成了隨便的一個數
然而神奇的是,這個網址請求出了數據(去掉這個mid鍵不出數據,將mid隨機賦值卻可以得到數據emmm)
提取id構造網址
經過剛剛的分析,我發現我們想要提取的數據就只有一個id值,然后再用Id值替換掉網址中的數字就可以得到相應的視頻頁面了
id是這段代碼的最重要的部分,經過前面曲折又困難的網頁分析之后,我認為提取id只需要從網頁中用表達式提取數據就可以了,但是我沒想到的是這一步也是比較困難的
我先是在主頁右擊了檢查,然后仔細的觀察了elements里面的元素,我發現id就儲存在elements之中
接着我就想辦法獲得這個頁面中的id信息,我嘗試了直接請求,發現輸出的數據中沒有Id信息; 我又加上了請求頭,依舊沒有id值輸出(這個頁面的元素是動態加載的,雖然不能一次獲取全部Id,但是也不至於一個沒有) ;然后我想到了selenium自動化測試模塊,使用webdriver打開網址打印源碼,可是輸出還是沒變
我查了百度的一些方法,也做了一些嘗試,發現這個頁面所做的反爬確實很難破解。於是我就只能換一條路去嘗試
在谷歌開發者工具中,點擊network選項卡,刷新界面 隨着我刷新的操作,在XHR選項卡下出現了一個名字很奇怪的數據包
點擊他的preview選項卡,點出他的下拉菜單,這里面存儲的正是小視頻的Id信息。但是需要注意的是,這個包里面只存儲了0-20序列的共21條信息
但是從這個主頁中我可以知道,它一共發布了64個短視頻,所以我推斷他還有三個數據包沒有加載出來 ---->我滾動下拉條,觀察有沒有數據包
滾動到最后,驗證了我的猜想,這個頁面有四個數據包且為動態加載
好了,我們已經分析出來了這個網頁的構造,先不要管一共有幾個數據包,先以一個數據包為例提取id信息:
將user-agaent加到請求頭中(這個網頁必須要加請求頭,不然獲取不到數據)
請求得到數據:
當前乍一看好像這個代碼沒有問題,但是在執行四五次之后,會出現請求不到數據或返回False的情況,一開始我以為是ip被限制的原因,但是加上了ip池之后也是一樣的結果,后來我才發現:請求不到數據是因為之前請求的url被禁用了,要在抖音詳情頁刷新一下,再把新的數據包的網址復制過來才能重新得到數據(我也不知道這是什么類型的反爬,希望知道的老哥可以告訴我一下)
*我之所以把這個網址分成兩部分來寫,是因為當網址請求不到數據的時候,改變的是末尾的_signature=random_field字段,在請求不到數據的時候只需重新復制一下這個字段就可以了,會簡化一點點代碼
拼接數據包鏈接
上面提取Id的時候講到,我們先拿一個數據包做例子,但是我們要爬的這個用戶的全部視頻,所以就要將它所有的數據包地址都訪問一遍
想要得到這些數據包的地址,就需要分析他們的網址構造,我把這四個數據包的網址全部復制到記事本中,逐個分析他們構造規律
不難看出,這四個數據包的區別就在於max_cursor后面的值的不同,而這個值正好就包包含在它前一個數據包之中,這就說明我們可以從前一個數據包中提取到下一個數據包的max_curso值,從而構造出下一個數據包的鏈接地址
可是第四個數據包也包含着max_cursor的值,我們該在何時停止構造下一個數據包呢?
我把最后一個數據包的max_cursor值復制下來並替換到構造的數據包鏈接中,發現可以跳轉到一個新的網址,這個網址中也有max_cursor的值,但是這個值為0
也可以多找幾個網址測試,最后的結果指向都是0,所以我們可以通過if語句來判斷這個值為0的時候就終止循環
構造網址代碼:
獲取視頻地址
現在我們已經可以成功的進入獲取到視頻頁面了,復雜的網頁分析基本已經結束了,后續操作就變得簡單了
先打開小視頻的頁面,右擊檢查,查看元素
經過檢查發現,這個源代碼中並沒有視頻地址,點擊了一下播放按鍵,視頻的地址才會加載出來
看到這種動態加載的機制,我們首先就應該想到selenium自動化測試工具,步驟是先用selenium打開視頻頁面,再點擊播放按鈕,將此時已經刷新完的網頁源代碼保存,
再從中提取到視頻的真正網址,最后再將調試好的webdriver設置為無界面模式
實現代碼:
下載視頻
視頻的真實網址我們已經獲得了,接下來只剩下最后一步的操作了---->下載視頻
視頻下載的操作就非常簡單了:
全部代碼
實現結果
可以看到這些視頻已經下載到本地了,我們在打開本地文件夾看一下
可以播放!至此我這個問題版的抖音爬蟲就做完了
待解決的問題
- 如何獲取主頁中所有的id地址
- 為什么請求的url后綴會一直變化,該怎么破解
其實所有的問題都指向了一個地方:該怎么獲取小視頻的id 如果大佬們有更好的方法可以獲取id值,希望大佬們可以不吝提出建議讓我把這個爬蟲的功能再完善!感謝各位!