今天一不小心,把抖爸爸給爬了


引言

今天躺在床上刷抖音的時候,正好刷到「基地邊緣」的有關 SpaceX 的科普視頻,忽然我就想,這個視頻我能怎么把它搞下來呢?

分析

在抖音上點擊分享的時候可以有下載的選項,但是這個就下載到手機上了,我想把這種科普視頻保存起來,下到手機上以后還得通過各種方式導到電腦上,這就很不方便了。

不過還好抖音提供了「復制鏈接」的功能,先把這個鏈接復制下來,在瀏覽器上打開手機模擬,看看能不能打開這個鏈接。

這里我拿到的鏈接如下:

https://v.douyin.com/JefvNdx/

在瀏覽器上輸入這個鏈接以后,可以看到頁面進行了一次跳轉,剛才的短連接也變成了另一個長鏈接(這里其實是通過 302 進行了重定向):

https://www.iesdouyin.com/share/video/6834090710124236043/?region=CN&mid=6834090817913670407&u_code=15afkgm1a&titleType=title&utm_source=copy_link&utm_campaign=client_share&utm_medium=android&app=aweme

頁面變成這樣了,我抱着試試看的心態,點擊了一下播放,竟然還能播放,抖音真的是良心啊,我還以為會直接跳轉到 APP 下載頁面,視頻能播放出來,基本上想把這個視頻爬下來這件事兒就已經成功了一半了。

還是老方法,打開 Chrome 的 F12 ,進入 network 標簽,點擊一下播放,看看能不能拿到視頻源的地址。

結果在我刷新頁面的時候,直接發現了一個請求,這個請求可就 NB 了,直接返回這個視頻的所有信息。

請求連接如下:

https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=6834090710124236043&dytk=8667a137523322dcea2304b86a7570cd9e707167df185ed8bdda723dc84d5477

這個地址其實后面的參數穿不穿都沒有影響,這里的 item_ids 應該就是這個視頻的 id ,和上面那個鏈接里面直接更在 video 后面的 id 是一致的。

返回的 json 數據我就不貼了,太長了,反正我在這個數據里面找到了視頻源的信息:

https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f7b0000brbp0h64tqbtfrkkjqlg&ratio=720p&line=0

這個鏈接 Copy 出來,在瀏覽器中直接輸入后,成功播放了當前的視頻:

眼神好的同學估計已經發現了瀏覽器地址中的變化,這個地址並不是我們剛才 Copy 出來的地址,這是啥情況呢?

接着打開 F12 看 network :

可以看到,我們原始的訪問鏈接被 302 重定向到了下面這個地址:

http://v26-dy.ixigua.com/f2a61958ae617965d3d42815b13b516e/5eda87f9/video/tos/cn/tos-cn-ve-15/23a5f6a323584ae69b04a65d5ca289b7/?a=1128&br=3213&bt=1071&cr=0&cs=0&dr=0&ds=3&er=&l=20200606005756010019017107165572F4&lr=aweme_search_suffix&mime_type=video_mp4&qs=0&rc=anRudXd0N2tzdTMzZWkzM0ApOTg5ODw5ZDtnNzg4OWQ4O2dpZ2hjX3EzLV9fLS00LS9zcy1fLzIzMmM2YS02MjQtNC46Yw%3D%3D&vl=&vr=

本來我以為是需要訪問重定向后的鏈接才能下載視頻,后面實際上測試的結果是使用之前的鏈接就可以。

編碼

到這里,我們就可以開始寫代碼了,完整代碼如下:

import requests
import re

# 創建一個請求頭
headers = {
    'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
}

# 分享路徑
share_url = "https://v.douyin.com/JefvNdx/"

session = requests.Session()
res = session.get(share_url, headers = headers)

# 獲取視頻 id
item_ids = re.compile(r'itemId: "([0-9]+)"').findall(res.text)[0]

# 拼接請求
item_info_url = f"https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids={item_ids}"
res_json = session.get(item_info_url, headers = headers).json()

# 獲取視頻源路徑
vedio_url = res_json['item_list'][0]['video']['play_addr']['url_list'][0]

res = requests.get(vedio_url, headers = headers)
with open('demo.mp4', 'wb') as fb:
    fb.write(res.content)

print("視頻下載完成~~~")

代碼我就不多做解釋了,注釋已經寫得很清楚了。

批量爬取

到這里,問題又來了,我如果想要下載這個人所有的科普視頻呢?難道要我一個一個去分享鏈接么?

這也太傻了,我打開了這個人的主頁,在右上角的分享按鈕中再次發現了「復制鏈接」,太好了,抖爸爸又給我們提供接口了。

這次我獲取到的鏈接是:

https://v.douyin.com/Je5WLg6/

閑話少說,接着在 Chrome 中打開分析請求,選擇 XHR ,直接看到第一個請求:

https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid=MS4wLjABAAAAFTNkHANuPtZKteVQsBaMwaIHoSMh3nxqJDOXEDHUnlg&count=21&max_cursor=0&aid=1128&_signature=fJp6thAXIkOb7YKwZF36KXyaeq&dytk=fd2ba6076e7bb73e31504e51bc4baf08

這個請求的響應里面,再次看到了各個視頻的詳細信息:

這個 aweme_list 數組里面對應了 20 條視頻信息,我看到第一條視頻信息里面有一個 aweme_id 的值是 6834090710124236043 ,這和我們上面獲取到的那個視頻的值完全是一樣的嘛。

其實我只需要把 aweme_list 里面的所有的 aweme_id 解析出來,套在前面的程序上,我就可以把這 20 條視頻下載回來了(偷個小懶,這部分的代碼我就不寫了)。

注意,我這里說的是這 20 條視頻,那為什么拿不到所有視頻?

因為我看到前面那個鏈接里面有一個參數是 _signature 簽名,而這個接口的數據又是分頁給出來的,雖然后面有一個 count 意思是返回多少數據,但是我只能得到默認的 20 條數據,更多的數據是沒辦法獲得的,除非分析抖音的前端 JavaScript 代碼,找到 _signature 這個簽名規則,否則我們是沒有辦法篡改這個請求的參數的。

示例代碼

如果有需要獲取源碼的同學可以在公眾號回復「抖音」進行獲取。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM