最近刚好需要用今日头条下载视频,顺手分析一哈。以下代码用易语言实现,调用精易模块。
以下面这个链接为例:
https://m.toutiaoimg.cn/group/6639312069814387208/?iid=52858674052&app=news_article×tamp=1548677621&group_id=6639312069814387208
浏览器F12开发者模式抓包。
直接打开链接
https://m.toutiaoimg.cn/group/6639312069814387208/?iid=52858674052&app=news_article×tamp=1548677621&group_id=6639312069814387208
发现会重定向到
https://www.365yg.com/a6639312069814387208
对比一下,我们发现重定向后的链接构成
“https://www.365yg.com/”+“a”+“6639312069814387208”
都是从分享链接里提取出来的,这样就能拼接出重定向的链接了。
简单的查看一下抓到的数据,发现这个链接返回的是json数据,我们来看一下
axiosJsonpCallback1(
{
"data":
{
"status": 10,
"user_id": "toutiao",
"video_id": "v020040b0000bg5kplamac2pmifihea0",
"validate": "",
"enable_ssl": false,
"poster_url": "http://p3.pstatp.com/origin/1309f00086e340a768a52",
"video_duration": 187.52,
"media_type": "video",
"auto_definition": "480p",
"video_list":
{
"video_1":
{
"definition": "480p",
"vtype": "mp4",
"vwidth": 854,
"vheight": 480,
"bitrate": 561547,
"size": 14787848,
"quality": "normal",
"codec_type": "h264",
"logo_type": "xigua_share",
"encrypt": false,
"file_hash": "06af3b5e000603801a46588107a53ea0",
"file_id": "0b1b01fc455a43a0b279942fa800e1ab",
"main_url": "aHR0cDovL3YxLXR0Lml4aWd1YS5jb20vNWI4OTYzZWY5MmY4NGJiZTk1YzQ1MjU5ZGYwMThmOWQvNWM1MTIwYmQvdmlkZW8vbS8yMjA0MzI4ZTllNGI4MTI0MWYyODk3ODRhYTdiMDYxNmQzZDExNjExMDI1NjAwMDA5OTIyNTNhZGIwNmYvP3JjPU0yaHNiSE5tY0c5dWFqTXpaVGN6TTBBcFFIUkFielUwTkRjMk16UXpNemM0TkRZek5EVnZRR2d6ZFNsQVpqTjFLV1J6Y21kNWEzVnlaM2x5YkhoM1pqYzJRRjVsWTJvdlhsNXRNbDh0TFMwdEwzTnpMVzhqYnlNdUx6VXVNQzh0TGk4eExTMHVOaTA2STI4ak9tRXRjU002WUhacFhHSm1LMkJlWW1ZclhuRnNPaU16TGw0JTNE",
"backup_url_1": "aHR0cDovL3YzLXR0Lml4aWd1YS5jb20vMWYzN2Y3OGRmNDc3ZjU2OWY0NGQ1ZTNmYmFkOTcxZWIvNWM1MTIwYmQvdmlkZW8vbS8yMjA0MzI4ZTllNGI4MTI0MWYyODk3ODRhYTdiMDYxNmQzZDExNjExMDI1NjAwMDA5OTIyNTNhZGIwNmYvP3JjPU0yaHNiSE5tY0c5dWFqTXpaVGN6TTBBcFFIUkFielUwTkRjMk16UXpNemM0TkRZek5EVnZRR2d6ZFNsQVpqTjFLV1J6Y21kNWEzVnlaM2x5YkhoM1pqYzJRRjVsWTJvdlhsNXRNbDh0TFMwdEwzTnpMVzhqYnlNdUx6VXVNQzh0TGk4eExTMHVOaTA2STI4ak9tRXRjU002WUhacFhHSm1LMkJlWW1ZclhuRnNPaU16TGw0JTNE",
"p2p_verify_url": "",
"user_video_proxy": 1,
"socket_buffer": 12634740,
"preload_size": 327680,
"preload_interval": 60,
"preload_min_step": 5,
"preload_max_step": 10,
"spade_a": ""
}
},
"dynamic_video": null
},
"message": "success",
"code": 0,
"total": 1
})
基本上能确定,json数据中的main_url后面跟的就是我们需要的真实地址。
aHR0cDovL3YxLXR0Lml4aWd1YS5jb20vNWI4OTYzZWY5MmY4NGJiZTk1YzQ1MjU5ZGYwMThmOWQvNWM1MTIwYmQvdmlkZW8vbS8yMjA0MzI4ZTllNGI4MTI0MWYyODk3ODRhYTdiMDYxNmQzZDExNjExMDI1NjAwMDA5OTIyNTNhZGIwNmYvP3JjPU0yaHNiSE5tY0c5dWFqTXpaVGN6TTBBcFFIUkFielUwTkRjMk16UXpNemM0TkRZek5EVnZRR2d6ZFNsQVpqTjFLV1J6Y21kNWEzVnlaM2x5YkhoM1pqYzJRRjVsWTJvdlhsNXRNbDh0TFMwdEwzTnpMVzhqYnlNdUx6VXVNQzh0TGk4eExTMHVOaTA2STI4ak9tRXRjU002WUhacFhHSm1LMkJlWW1ZclhuRnNPaU16TGw0JTNE
经过base64解码后,就能看到真实地址了。
http://v1-tt.ixigua.com/5b8963ef92f84bbe95c45259df018f9d/5c5120bd/video/m/2204328e9e4b81241f289784aa7b0616d3d1161102560000992253adb06f/?rc=M2hsbHNmcG9uajMzZTczM0ApQHRAbzU0NDc2MzQzMzc4NDYzNDVvQGgzdSlAZjN1KWRzcmd5a3VyZ3lybHh3Zjc2QF5lY2ovXl5tMl8tLS0tL3NzLW8jbyMuLzUuMC8tLi8xLS0uNi06I28jOmEtcSM6YHZpXGJmK2BeYmYrXnFsOiMzLl4%3D
第一步我们已经分析出了真实地址是get下面这个地址,返回的json数据。
https://ib.365yg.com/video/urls/v/1/toutiao/mp4/v020040b0000bg5kplamac2pmifihea0?r=2211418769496476&s=3032069104&aid=1364&vfrom=xgplayer&callback=axiosJsonpCallback1&_=1548816876260
分析一下这个链接的参数组成:
r:2211418769496476
s:3032069104
aid:1364
vfrom:xgplayer
callback:axiosJsonpCallback1
_:1548816876260
通过抓取多个视频链接对比,发现固定不变的参数有如下三个:
aid:1364
vfrom:xgplayer
callback:axiosJsonpCallback1
变化的参数有如下三个:
r:2211418769496476
s:3032069104
_:1548816876260
其中,参数“_”很容易能猜到是一个现行时间戳,因为刚好是13位数。
我们来分析参数“r”和“s”。
一般来说,会变的参数,要么是服务器返回的,要么就是js动态生成的。我们直接搜参数数据,发现找不到。那猜想这是js生成的。通过抓包也发现,这个地址来源与js文件。
js文件地址为https://s3.pstatp.com/toutiao/xigua_video/pc/static/js/vendor.240e4dd12b798ea9.js
所以我们来看看这个js文件。算了不分析了。今日头条更新过了,js文件又臭又长没有以前的好分析,但是算法没有太大变化。
参数“r”的构成,是十六位随机数。
参数“s”是由crc32校验后得到的数据。加密数据为:
url = “/video/urls/v/1/toutiao/mp4/” + video_id + “?r=2211418769496476”
video_id通过正则可从网页返回html代码中获取(https://www.365yg.com/a6639312069814387208)
CRC32校验我们用dll命令来实现:
.DLL命令 RtlComputeCrc32, 整数型, "ntdll.dll", "RtlComputeCrc32"
.参数 码表, 整数型
.参数 数据, 字节集, 传址
.参数 长度, 整数型
子程序 取字节集CRC32值()写法如下:
.子程序 取字节集CRC32值, 文本型, 公开, 获取字节集CRC32 8个字节
.参数 字节集, 字节集, , 字节集
.参数 结果转小写, 逻辑型, 可空, 是否输出为小写
.局部变量 结果, 文本型
结果 = 取十六进制文本 (RtlComputeCrc32 (0, 字节集, 取字节集长度 (字节集)))
结果 = 格式化文本 (“%08s”, 结果)
.如果 (结果转小写)
返回 (到小写 (结果))
.否则
返回 (到大写 (结果))
调用CRC32校验子程序,算出参数“s”。
url = “/video/urls/v/1/toutiao/mp4/” + video_id + “?r=2211418769496476”
s = 到文本 (进制_十六到十 (取字节集CRC32值 (到字节集 (url))))
这样就能算出参数s的值。
所需参数已经分析出来,下面就是拼接链接。get访问,得到json数据,取出main_url即可大功告成。
通过测试发现,6个参数中,只有s参数是需要变动的,其他参数都可以固定或者是省略。
r:2211418769496476
s:3032069104
aid:1364
vfrom:xgplayer
callback:axiosJsonpCallback1
_:1548816876260
如上,参数s是crc32校验值是必须的,随机数r也是必须值,因为用来算出参数s。其他的都可以省略。
url = “https://ib.365yg.com/video/urls/v/1/toutiao/mp4/” + video_id + “?r=2211418769496476”+ “&s=” + s
url = “https://ib.365yg.com/video/urls/v/1/toutiao/mp4/v020040b0000bg5kplamac2pmifihea0?r=2211418769496476&s=3032069104”
以上就是拼接的链接
https://ib.365yg.com/video/urls/v/1/toutiao/mp4/v020040b0000bg5kplamac2pmifihea0?r=2211418769496476&s=3032069104
然后get访问得到json数据,正则匹配出main_url在经过base64解码得到真实地址。
mainUrl = 到文本 (编码_BASE64解码 (mainUrl))
真实地址为:
http://v1-tt.ixigua.com/5b8963ef92f84bbe95c45259df018f9d/5c5120bd/video/m/2204328e9e4b81241f289784aa7b0616d3d1161102560000992253adb06f/?rc=M2hsbHNmcG9uajMzZTczM0ApQHRAbzU0NDc2MzQzMzc4NDYzNDVvQGgzdSlAZjN1KWRzcmd5a3VyZ3lybHh3Zjc2QF5lY2ovXl5tMl8tLS0tL3NzLW8jbyMuLzUuMC8tLi8xLS0uNi06I28jOmEtcSM6YHZpXGJmK2BeYmYrXnFsOiMzLl4%3D
(1)打开链接,会重定向跳转。然后从跳转后的网页中取出video_id;
(2)找到参数s的算法,算出s拼接出url,get访问得到包含真实地址main_url的json数据;
(3)用正则取出,或者是json数据解析,得到main_url等其他数据。
.版本 2
.子程序 解析链接
.局部变量 video_id, 文本型
.局部变量 rText, 文本型
.局部变量 url, 文本型
.局部变量 return, 文本型
.局部变量 s, 文本型
.局部变量 mainUrl, 文本型
.局部变量 fText, 文本型
.局部变量 链接, 文本型
链接 = 编辑框1.内容
.判断开始 (寻找文本 (链接, “group/”, , 假) ≠ -1)
fText = 文本_取出中间文本 (文本, “up/”, “/”, , )
.如果真 (寻找文本 (fText, “a”, , 假) = -1)
fText = “a” + fText
.如果真结束
url = “https://www.365yg.com/” + fText
.判断 (寻找文本 (链接, “cn/a”, , 假) ≠ -1)
fText = 文本_取出中间文本 (文本, “cn/”, “/”, , )
.如果真 (寻找文本 (fText, “a”, , 假) = -1)
fText = “a” + fText
.如果真结束
url = “https://www.365yg.com/” + fText
.判断 (寻找文本 (链接, “item”, , 假) ≠ -1)
fText = 文本_取出中间文本 (文本, “em/”, “/”, , )
.如果真 (寻找文本 (fText, “a”, , 假) = -1)
fText = “a” + fText
.如果真结束
url = “https://www.365yg.com/” + fText
.默认
url = 链接
.判断结束
rText = 网页_访问S (url)
fName = 正则_匹配vName (rText)
video_id = 正则_匹配vID (rText)
url = “/video/urls/v/1/toutiao/mp4/” + video_id + “?r=2211418769496476”
s = 到文本 (进制_十六到十 (取字节集CRC32值 (到字节集 (url))))
url = “https://ib.365yg.com” + url + “&s=” + s
rText = 网页_访问S (url)
mainUrl = 正则_匹配url (rText)
mainUrl = 到文本 (编码_BASE64解码 (mainUrl))
调试输出(mainUrl)