一声诸、需求
當我們?yōu)g覽視頻網頁時殊橙,有可能想要下載下來某個視頻衬衬,或者想要跳過臭長的廣告(慎),但是現(xiàn)在的網站往往不提供直接下載mp4或其他格式的視頻文件的功能刁笙。我們通過使用Python
配合Chrome
瀏覽器破花,可以獲取到騰訊視頻
的視頻真實地址,直接下載視頻文件疲吸。
-
為什么使用
Python
:很簡單座每,專注自己需要的事情,同樣的功能摘悴,使用其他語言峭梳,可能要自己寫http
實現(xiàn),寫幾百行代碼烦租,但是用Python
延赌,20多行代碼就可以了。
二叉橱、實現(xiàn)
以下以小豬佩奇
某一集為例,看看如何得到視頻地址者蠕。
https://v.qq.com/x/cover/bzfkv5se8qaqel2/b0020buglwx.html
有一種思路是:使用Chrome
瀏覽器的開發(fā)者工具窃祝,監(jiān)控網頁加載過程中發(fā)出的每個請求和服務器的回復,從中查找關于視頻信息的蛛絲馬跡踱侣。當發(fā)現(xiàn)可疑的request
時粪小,查看該請求發(fā)出的所有參數(shù)內容,使用Python
拼裝相應的參數(shù)抡句,并構造虛假的http請求頭探膊,模擬成用戶通過網頁的點擊,向服務器發(fā)出請求待榔,獲取服務器回復內容逞壁,然后從回復內容中解析出視頻地址流济。
根據(jù)以前的經驗,這些網站的開發(fā)者腌闯,在移動端的功能實現(xiàn)會相對簡單一些绳瘟,我們更容易識別和抓取,因此我們解析的時候使用瀏覽器模擬成移動端姿骏,如圖:
我們用
Python
糖声,拼接出圖中方框Request的URL地址,填入參數(shù)分瘦,發(fā)出GET
請求蘸泻,就可以得到一個包含視頻信息的json
字符串。GET請求的URL是:
http://h5vv.video.qq.com/getinfo?
問號后面由很多包含參數(shù)名稱和值的組合構成嘲玫,例如otype=json&platform=11&defnpayver=1&appver=3.4.40
其中一個重要的參數(shù)vid
悦施,就是視頻地址本身提供的:
當我們發(fā)出get請求,得到的
json
數(shù)據(jù)類似這樣:
{
"dltype": 1,
"exem": 0,
"fl": {
"cnt": 4,
"fi": [
{
"id": 10203,
"name": "sd",
"lmt": 0,
"sb": 1,
"cname": "標清;(270P)",
"br": 37,
"profile": 1,
"drm": 0,
"video": 1,
"audio": 1,
"fs": 5705248,
"super": 0,
"hdr10enh": 0,
"sname": "標清",
"resolution": "270P",
"sl": 0
},
{
"id": 10212,
"name": "hd",
"lmt": 0,
"sb": 1,
"cname": "高清;(480P)",
"br": 42,
"profile": 1,
"drm": 0,
"video": 1,
"audio": 1,
"fs": 10092707,
"super": 0,
"hdr10enh": 0,
"sname": "高清",
"resolution": "480P",
"sl": 0
},
{
"id": 10201,
"name": "shd",
"lmt": 0,
"sb": 1,
"cname": "超清;(720P)",
"br": 62,
"profile": 1,
"drm": 0,
"video": 1,
"audio": 1,
"fs": 19246460,
"super": 0,
"hdr10enh": 0,
"sname": "超清",
"resolution": "720P",
"sl": 1
},
{
"id": 10209,
"name": "fhd",
"lmt": 3,
"sb": 1,
"cname": "藍光;(1080P)",
"br": 67,
"profile": 1,
"drm": 0,
"video": 1,
"audio": 1,
"fs": 40730393,
"super": 0,
"hdr10enh": 0,
"sname": "藍光",
"resolution": "1080P",
"sl": 0
}
]
},
"fp2p": 2,
"hs": 0,
"ip": "113.110.230.111",
"ls": 0,
"preview": 299,
"s": "o",
"sfl": {
"cnt": 0
},
"tstid": 3,
"tm": 1574871391,
"vl": {
"cnt": 1,
"vi": [
{
"br": 62,
"ch": 0,
"cl": {
"fc": 1,
"ci": [
{
"idx": 1,
"cs": 19246460,
"cd": "299.96",
"cmd5": "f579ecf14d0aa58c0bc846f40ebe0c7c",
"vkey": "",
"urllist": [],
"keyid": "q0020tfo8j7.10201.1"
}
]
},
"ct": 21600,
"drm": 0,
"dsb": 0,
"fclip": 1,
"fmd5": "f579ecf14d0aa58c0bc846f40ebe0c7c",
"fn": "q0020tfo8j7.p201.mp4",
"fs": 19246460,
"fst": 5,
"fvkey": "6D7FDA1832CC88940F6F20E281EE9727639DF6B0D70FFF73083818AB45289A0507A0FD280B370536D0918C1A3564AA34F9698B83C61A88962F765BBF7EA67010F5B4D1D11737658D783A86ED5A5EA22933C2838506DEC3B16C1223E7727442E18A1AA2630567BFD436C4353F31F5A0E5",
"head": 0,
"hevc": 0,
"iflag": 0,
"level": 0,
"lnk": "q0020tfo8j7",
"logo": 1,
"mst": 8,
"pl": [
{
"cnt": 3,
"pd": [
{
"cd": 2,
"h": 45,
"w": 80,
"r": 10,
"c": 10,
"fmt": 40001,
"fn": "q1",
"url": "http: //puui.qpic.cn/video_caps/0/"
},
{
"cd": 2,
"h": 90,
"w": 160,
"r": 5,
"c": 5,
"fmt": 40002,
"fn": "q2",
"url": "http://puui.qpic.cn/video_caps/0/"
},
{
"cd": 2,
"h": 135,
"w": 240,
"r": 5,
"c": 5,
"fmt": 40003,
"fn": "q3",
"url": "http://puui.qpic.cn/video_caps/0/"
}
]
}
],
"share": 1,
"sp": 0,
"st": 2,
"tail": 0,
"td": "299.96",
"ti": "恐龍先生弄丟了",
"tie": 0,
"type": 1036,
"ul": {
"ui": [
{
"url":"http://113.105.141.22/vlive.qqvideo.tc.qq.com/AF094anUFAellJsZIYnUozoSnZLLcgP480IDBq7WleyE/uwMROfz2r5zCIaQXGdGnC2dfKb2-hlZWyQT_tzD-Vsr
eqSpl/",
"vt": 203,
"dtc": 0,
"dt": 2
},
{
"url": "http: //lmsjy.qq.com/uwMROfz2r5zCIaQXGdGnCmdfKb0i2sHXl3M2Wy9RmDZEeplY/",
"vt": 170,
"dtc": 0,
"dt": 2
},
{
"url": "http://lmbsy.qq.com/uwMROfz2r5zCIaQXGdGmm2dfKb0Pk2-yYlV7ZrIrO9TJ-LqW/",
"vt": 130,
"dtc": 0,
"dt": 2
},
{
"url": "http://video.dispatch.tc.qq.com/uwMROfz2r5zCIaQXGdGmlWdfKb2svKK_VNuAbg616jtBjIn0/",
"vt": 0,
"dtc": 0,
"dt": 2
}
]
},
"vh": 720,
"vid": "b0020buglwx",
"videotype": 106,
"vr": 0,
"vst": 2,
"vw": 1280,
"wh": 1.7777778,
"wl": {
"wi": []
},
"uptime": 1465198419,
"fvideo": 0,
"cached": 1,
"fvpint": 0,
"swhdcp": 0
}
]
}
}
看到這其中包含很多的url
地址趁冈,可以確定視頻地址的信息就在其中歼争,不過還需要分析一下,怎么樣根據(jù)這些數(shù)據(jù)把視頻地址拼接出來渗勘。
其實瀏覽器也是根據(jù)這個json
數(shù)據(jù)沐绒,通過調用js
腳本獲取到視頻地址,但是如果要通過解析js
腳本獲取地址就會很麻煩旺坠,尤其是考慮到js
腳本可能經過了壓縮和加密乔遮。所以還是通過瀏覽器開發(fā)者工具,查看瀏覽器實際get
請求中的數(shù)據(jù)格式取刃,以供參考蹋肮。
經測試其中有些參數(shù)可以不傳入。最終代碼如下璧疗,只需傳入一個網址坯辩,就可以獲取到mp4格式視頻的一個url(默認就是最高清晰度)。
import requests
import re
import json
headers = {
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
def getTencentVideoUrl(url):
vid = url.split('/')[-1][:-5]
url = 'http://h5vv.video.qq.com/getinfo?otype=json&platform=11&defnpayver=1&appver=3.4.40&defn=fhd&vid=' + vid
html = requests.get(url, headers=headers).text
# 獲取json數(shù)據(jù)
p = re.compile(r'({.*})', re.S)
jsonstr = re.findall(p, html)[0]
json_data = json.loads(jsonstr)
print(jsonstr)
# 解析json數(shù)據(jù)獲取url
fvkey = json_data['vl']['vi'][0]['fvkey']
keyid = json_data['vl']['vi'][0]['cl']['ci'][0]['keyid'].split('.')
filename = keyid[0] + '.p' + keyid[1][2:] + '.' + keyid[2] + '.mp4'
baseUrl = json_data['vl']['vi'][0]['ul']['ui'][3]['url'] # 實際數(shù)據(jù)中有多個cdn可供選擇
result = baseUrl + filename + '?vkey=' + fvkey
return result
if __name__ == '__main__':
url = input('請輸入騰訊視頻網址:')
print('視頻下載地址:\n', getTencentVideoUrl(url))
三崩侠、問題:
- 實際上有些視頻是分成了多個小部分漆魔,這時就會需要獲取每個視頻的地址,下載下來然后再拼接成一個完整的視頻文件却音,如果想要做的話也是可以的改抡,自動下載多段視頻,然后自動合并成1個完整的文件系瓢。
這里可能就不能只發(fā)送一次get
請求了阿纤,而是根據(jù)視頻分割成了多少個,發(fā)送多次請求夷陋。