今日頭條視訊的地址解析下載
以今日頭條視訊播放頁URL http://www.toutiao.com/a6296462662335201793/ 為例,來說說是如何得到視訊的真實地址的。
在Chrome瀏覽器中開啟上面的連結,然後審查播放器區域的元素,發現是這樣的:
<video id="vjs_video_3_html5_api" class="vjs-tech" preload="auto" autoplay="" src="http://v6.pstatp.com/video/c/c62f4d4320ea43469b490e54240653ab/?Signature=D2cYsGzKaEXraZQnOf72xgJ94%2Bs%3D&Expires=1469172376&KSSAccessKeyId=qh0h9TdcEMrm1VlR2ad/">
<source type="video/mp4" src="http://v6.pstatp.com/video/c/c62f4d4320ea43469b490e54240653ab/?Signature=D2cYsGzKaEXraZQnOf72xgJ94%2Bs%3D&Expires=1469172376&KSSAccessKeyId=qh0h9TdcEMrm1VlR2ad/">
</video>
原來是使用了HTML5的video標籤,該標籤的src屬性值就是視訊的真實地址。是不是很簡單?如果我們想寫個指令碼來自動解析視訊的真實地址,會發現情況不一樣。
說明:以下程式碼片段均使用Python語言。
import requests
from pyquery import PyQuery as pq
r = requests.get('http://www.toutiao.com/a6296462662335201793/')
d = pq(r.content)
d('video') # video元素不存在
d('#video') # id是video的元素是存在的
當我們把播放頁下載下來,並且嘗試提取video元素的時候,發現下載下來的播放頁中根本就沒有video元素。這說明video元素可能是js指令碼動態生成的,該想想其它辦法了。
通過觀察載入播放頁頁面時的網路請求,我們發現如下相關的請求:
http://v7.pstatp.com/b97adb57aaa351e485ed69c5e4852211/5791c279/video/c/c62f4d4320ea43469b490e54240653ab/
http://i.snssdk.com/video/urls/v/1/toutiao/mp4/9583cca5fceb4c6b9ca749c214fd1f90?r=18723666135963302&s=3807690062&callback=tt_playerzfndr
其中,第1個請求就是視訊真實地址,第2個請求返回的是一個JSON字串,內容如下:
{
"code": 0,
"message": "success",
"total": 3,
"data": {
"status": 10,
"video_duration": 0,
"video_id": "9583cca5fceb4c6b9ca749c214fd1f90",
"user_id": "toutiao",
"video_list": {
"video_3": {
"definition": "720p",
"vtype": "mp4",
"main_url": "aHR0cDovL3Y3LnBzdGF0cC5jb20vZmJiZmE2Yjc4ZjM4MThhM2M0OTVhMmRkYjAyOWY5NTAvNTc5\nMWMzODAvdmlkZW8vYy8zNDMwNzcxZjMyNmY0ZDUxOTRiNTYyMzdhNmEyMzFmYy8=\n",
"vwidth": 720,
"backup_url_1": "aHR0cDovL3Y2LnBzdGF0cC5jb20vdmlkZW8vYy8zNDMwNzcxZjMyNmY0ZDUxOTRiNTYyMzdhNmEy\nMzFmYy8/U2lnbmF0dXJlPTMwd25YNHVBYzJ1JTJGdSUyRlNvNjhDM010U1VRVW8lM0QmRXhwaXJl\ncz0xNDY5MTc0MTYwJktTU0FjY2Vzc0tleUlkPXFoMGg5VGRjRU1ybTFWbFIyYWQv\n",
"bitrate": 0,
"vheight": 576,
"size": 0
},
"video_2": {
"definition": "480p",
"vtype": "mp4",
"main_url": "aHR0cDovL3Y0LnBzdGF0cC5jb20vM2ZiYTI0YzVhYzE1NGVlNmIxMGQ4ZTAyZThhNGQxZDMvNTc5\nMWMzODAvdmlkZW8vYy9jNjJmNGQ0MzIwZWE0MzQ2OWI0OTBlNTQyNDA2NTNhYi8=\n",
"vwidth": 600,
"backup_url_1": "aHR0cDovL3Y0LnBzdGF0cC5jb20vM2ZiYTI0YzVhYzE1NGVlNmIxMGQ4ZTAyZThhNGQxZDMvNTc5\nMWMzODAvdmlkZW8vYy9jNjJmNGQ0MzIwZWE0MzQ2OWI0OTBlNTQyNDA2NTNhYi8=\n",
"bitrate": 0,
"vheight": 480,
"size": 0
},
"video_1": {
"definition": "360p",
"vtype": "mp4",
"main_url": "aHR0cDovL3Y2LnBzdGF0cC5jb20vdmlkZW8vYy9iODgwZmI1YzM1NjE0NzJlOThlNGU0Y2U5N2My\nYzg5ZS8/U2lnbmF0dXJlPXBlTWhoNFdLcyUyRkNmRW9pYm4wTVNKUU5tR1lnJTNEJkV4cGlyZXM9\nMTQ2OTE3NDE2MCZLU1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNcm0xVmxSMmFkLw==\n",
"vwidth": 450,
"backup_url_1": "aHR0cDovL3Y3LnBzdGF0cC5jb20vNjFhYTJlN2RlN2YxZTgzNGJiNjg3ZDZmMDZjZGFmNzMvNTc5\nMWMzODAvdmlkZW8vYy9iODgwZmI1YzM1NjE0NzJlOThlNGU0Y2U5N2MyYzg5ZS8=\n",
"bitrate": 0,
"vheight": 360,
"size": 0
}
}
}
}
看看JSON內容,可以看到共有3種清晰度視訊,分別是超清、高清和標清。definition表示清晰度,main_url應該就是視訊真實地址了。main_url的值看起來就是base64編碼後的結果,用base64解碼main_url,得到的就是視訊真實地址。
import base64
main_url = "aHR0cDovL3Y3LnBzdGF0cC5jb20vZmJiZmE2Yjc4ZjM4MThhM2M0OTVhMmRkYjAyOWY5NTAvNTc5\nMWMzODAvdmlkZW8vYy8zNDMwNzcxZjMyNmY0ZDUxOTRiNTYyMzdhNmEyMzFmYy8=\n"
base64.standard_b64decode(main_url)
# output: http://v7.pstatp.com/fbbfa6b78f3818a3c495a2ddb029f950/5791c380/video/c/3430771f326f4d5194b56237a6a231fc/
那麼接下來的問題就是探究上面的第2個請求 http://i.snssdk.com/video/urls/v/1/toutiao/mp4/9583cca5fceb4c6b9ca749c214fd1f90?r=18723666135963302&s=3807690062&callback=tt_playerzfndr 是如何構造的。
在用Chrome的開發者工具監視網路請求的時候可以看到該請求是js指令碼發出的,該js指令碼是 http://s3.pstatp.com/tt_player/player/tt2-player.js?r=customer1
把該js下載下來,prettify一下,使用你最愛的編輯器看看該js到底做了些什麼。
通過研究該js指令碼,發現請求http://i.snssdk.com/video/urls/v/1/toutiao/mp4/9583cca5fceb4c6b9ca749c214fd1f90?r=18723666135963302&s=3807690062&callback=tt_playerzfndr 中的一些引數的含義如下:
- 9583cca5fceb4c6b9ca749c214fd1f90:這是視訊的唯一ID
- 18723666135963302:這是一個隨機數
- 3807690062:這是CRC32校驗值無符號右移0位
視訊的唯一ID可以在播放頁HTML原始碼中找到,即id為video的元素的tt-videoid屬性值。
import requests
from pyquery import PyQuery as pq
r = requests.get('http://www.toutiao.com/a6296462662335201793/')
d = pq(r.content)
vid = d('#video').attr('tt-videoid')
引數r的構造如下:
import random
r = str(random.random())[2:]
引數s的構造如下:
import urlparse
def right_shift(val, n):
return val >> n if val >= 0 else (val + 0x100000000) >> n
url = 'http://i.snssdk.com/video/urls/v/1/toutiao/mp4/%s' % vid
n = urlparse.urlparse(url).path + '?r=' + r
c = binascii.crc32(n)
s = right_shift(c, 0)
引數callback就不管了吧。到此,獲取JSON內容就簡單了:
r = requests.get(url + '?r=%s&s=%s' % (r, s))
print r.json()
相關文章
- 今日頭條:2018抖音短視訊營銷策略通案(附下載)
- 今日頭條:2018今日頭條兩會閱讀大資料(附下載)大資料
- 西瓜視訊&抖音&今日頭條:2021年中視訊發展趨勢報告(附下載)
- 今日頭條實習面試題解析面試題
- 今日頭條:2018年美妝行業洞察(附下載)行業
- 2020今日頭條平臺營銷通案(附下載)
- 巨量算數:今日頭條人群洞察報告(附下載)
- 2024今日頭條汽車營銷白皮書(附下載)
- 今日頭條上央視新聞 很快今日頭條回應廣告“二跳”事件事件
- 巨量算數:2019今日頭條白酒行業白皮書(附下載)行業
- 今日頭條推薦系統架構設計實踐(附下載)架構
- 今日頭條極速版和今日頭條有什麼區別?
- 今日頭條怎麼設定黑色背景?今日頭條app開啟深色模式的技巧APP模式
- 今日頭條怎麼賺錢?頭條號的賺錢思路
- 今日頭條Android面試Android面試
- 今日頭條怎麼搬運影片,短影片搬運案例解析!
- 今日頭條的小遊戲戰術遊戲
- 今日頭條研發面經
- thinkphp仿今日頭條原始碼PHP原始碼
- 清華大學:2019智庫大資料包告–今日頭條版(附下載)大資料
- 【今日頭條】深圳研發中心招聘資訊(動態更新)
- 「前端面試題系列1」今日頭條 面試題和思路解析前端面試題
- android 今日頭條的螢幕適配理解Android
- RSS推送技術——打造自己的今日頭條
- 吳鏑:TiDB 在今日頭條的實踐TiDB
- 朝夕光年——今日頭條的“遊戲據點”遊戲
- 今日頭條:2018上半年手機行業內容營銷白皮書(附下載)行業
- 今日頭條正式釋出小程式
- 【今日頭條】校招內推碼
- 今日頭條 Flutter 架構實踐Flutter架構
- 今日頭條技術架構分析架構
- Downie 4視訊下載軟體 Mac最好用的視訊下載軟體Mac
- 模仿今日頭條app開發遇到的問題APP
- 「nodejs + docker + github pages 」 定製自己的 「今日頭條」NodeJSDockerGithub
- 騰訊禁止今日頭條直播王者榮耀 網友:吃相難看!
- 今日頭條:2024年今日頭條攔截虛假流量150億次 處理違規內容超3億條
- React實戰篇(React仿今日頭條)React
- 記一次今日頭條面試面試
- 用Python爬下今日頭條所有美女,美滋滋!Python