获取今日头条西瓜视频下载地址
程序员文章站
2024-03-25 18:25:52
...
获取今日头条西瓜视频下载地址
通过该方式可以通过今日头条和西瓜视频的视频详情页面获取,视频的下载地址和播放地址(该地址是动态生成的)。
实现方式
通过该网站可以实现上述功能,但是必须访问该网页,还需要手动输入地址。具体如下:
通过分析,其实调用的是http://service.iiilab.com/video/toutiao
接口。我们通过network查看请求head:
首先请求类型是POST
请求参数包括三个:
- link,我们输入的视频详情url
- r ,随机数
- s, 随机数
我们使用postman模拟请求试试,并不可以直接请求,说明另外两个参数还是必须的
分析请求过程
上面的放个行不通,只能通过分析代码找出r
和 s
参数的生成规则。首先找到调用的js文件。通过Chrome浏览器的Sources发现静态资源,具体如下:
我们需要再次确定解析视频的提交方法就在该js中,具体如下:
没有输入视频地址,前端有提示请先将视频链接粘贴到上面的输入框
错误信息。通过该关键字在js文件中查找。在该js文件中有一个submit方法,并且上面的错误提示信息也在该方法中
这个方法主要是校验,核心方法在parseVideo
中
该方法也暴露了请求参数的生成方法,r参数的在这里已经可以看出来了。但是s参数的还需要通过generateStr
方法查看,具体如下:
至此我们至少知道参数r和s的生成策略。
通过Java代码模拟请求
通过上面的分析,我们现在的关键点是需要生成r和s参数,r参数还好说,但是s参数要转换成Java代码太麻烦了。
但是Java可以直接调用js方法,具体实现如下:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
public class XiGuaTest {
@Test
public void test1() throws Exception {
String uriAPI = "http://service.iiilab.com/video/toutiao";// Post方式没有参数在这里
HttpPost httpRequst = new HttpPost(uriAPI);// 创建HttpPost对象
String link = "http://www.toutiao.com/a6456372102038553101/";
Map<String, String> map = excuteJs(link);
httpRequst.setHeader("Origin", "http://toutiao.iiilab.com");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("link", link));
params.add(new BasicNameValuePair("r", map.get("r")));
params.add(new BasicNameValuePair("s", map.get("s")));
httpRequst.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
HttpResponse httpResponse = new DefaultHttpClient().execute(httpRequst);
String result = "";
if (httpResponse.getStatusLine().getStatusCode() == 200) {
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);// 取出应答字符串
}
System.out.println(result);
}
private Map<String, String> excuteJs(String link) throws ScriptException,
FileNotFoundException, NoSuchMethodException {
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
engine.eval(new FileReader(
"E:\\application\\workspace\\test\\test\\src\\test\\test.js"));
Invocable inv = (Invocable) engine;
Object test2 = inv.invokeFunction("test2");
String param = link + "@" + test2.toString();
Object a = inv.invokeFunction("test", param);
Map<String, String> hashMap = new HashMap<String, String>();
hashMap.put("r", test2.toString());
hashMap.put("s", a.toString());
return hashMap;
}
}
js代码如下:
function test(a) {
var c = function() {
for (var d = 0,
f = new Array(256), g = 0; 256 != g; ++g) {
d = g,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
d = 1 & d ? -306674912 ^ d >>> 1 : d >>> 1,
f[g] = d
}
return "undefined" != typeof Int32Array ? new Int32Array(f) : f
} (),
b = function(g) {
for (var j, k, h = -1,
f = 0,
d = g.length; f < d;) {
j = g.charCodeAt(f++),
j < 128 ? h = h >>> 8 ^ c[255 & (h ^ j)] : j < 2048 ? (h = h >>> 8 ^ c[255 & (h ^ (192 | j >> 6 & 31))], h = h >>> 8 ^ c[255 & (h ^ (128 | 63 & j))]) : j >= 55296 && j < 57344 ? (j = (1023 & j) + 64, k = 1023 & g.charCodeAt(f++), h = h >>> 8 ^ c[255 & (h ^ (240 | j >> 8 & 7))], h = h >>> 8 ^ c[255 & (h ^ (128 | j >> 2 & 63))], h = h >>> 8 ^ c[255 & (h ^ (128 | k >> 6 & 15 | (3 & j) << 4))], h = h >>> 8 ^ c[255 & (h ^ (128 | 63 & k))]) : (h = h >>> 8 ^ c[255 & (h ^ (224 | j >> 12 & 15))], h = h >>> 8 ^ c[255 & (h ^ (128 | j >> 6 & 63))], h = h >>> 8 ^ c[255 & (h ^ (128 | 63 & j))])
}
return h ^ -1
};
var f = b(a) >>> 0;
return f.toString(10);
}
function test2(){
return Math.random().toString(10).substring(2);
}
执行结果如下:
{
"retCode": 200,
"retDesc": "成功",
"data": {
"text": "农村二货小伙玉米地偶遇媳妇,这个都要把我笑岔气了",
"video": {
"link": [
{
"url": "http://v3-tt.ixigua.com/6fa8e337a4bb0e291df12bfb467bb96c/59a4d89d/video/m/220490affee2214417cbb3ddbcd2037d9c3114f56700004805cf0a468f/#mp4",
"buttonText": "极速(360p)视频地址1",
"type": "极速(360p)"
},
{
"url": "http://v1-tt.ixiguavideo.com/c31e23f19a1553cde0359a08cce9701b/59a4d89d/video/m/220490affee2214417cbb3ddbcd2037d9c3114f56700004805cf0a468f/#mp4",
"buttonText": "极速(360p)视频地址2",
"type": null
},
{
"url": "http://v3-tt.ixigua.com/ced8474825e27b0585c7ed5c535101a5/59a4d89d/video/m/22020a871736eaf4e1695f2efca5d050e5b114f5320000a3774f5d4b3b/#mp4",
"buttonText": "高清(480p)视频地址1",
"type": "高清(480p)"
},
{
"url": "http://v1-tt.ixiguavideo.com/ab4820fc709fe1b45f224406d6249cda/59a4d89d/video/m/22020a871736eaf4e1695f2efca5d050e5b114f5320000a3774f5d4b3b/#mp4",
"buttonText": "高清(480p)视频地址2",
"type": null
},
{
"url": "http://v3-tt.ixigua.com/5db838d2555dd769f97a5d30c2e1b4f0/59a4d89d/video/m/22059ee25d2362645b7ab11544897329132114f6220000aad5618c70f3/#mp4",
"buttonText": "超清(720p)视频地址1",
"type": "超清(720p)"
},
{
"url": "http://v1-tt.ixiguavideo.com/c89c2a44bed1d74c1ea530f691645d6a/59a4d89d/video/m/22059ee25d2362645b7ab11544897329132114f6220000aad5618c70f3/#mp4",
"buttonText": "超清(720p)视频地址2",
"type": null
}
],
"download": [
{
"url": "http://v3-tt.ixigua.com/6fa8e337a4bb0e291df12bfb467bb96c/59a4d89d/video/m/220490affee2214417cbb3ddbcd2037d9c3114f56700004805cf0a468f/#mp4",
"buttonText": "极速(360p)视频地址1",
"type": "极速(360p)"
},
{
"url": "http://v3-tt.ixigua.com/ced8474825e27b0585c7ed5c535101a5/59a4d89d/video/m/22020a871736eaf4e1695f2efca5d050e5b114f5320000a3774f5d4b3b/#mp4",
"buttonText": "高清(480p)视频地址1",
"type": "高清(480p)"
},
{
"url": "http://v3-tt.ixigua.com/5db838d2555dd769f97a5d30c2e1b4f0/59a4d89d/video/m/22059ee25d2362645b7ab11544897329132114f6220000aad5618c70f3/#mp4",
"buttonText": "超清(720p)视频地址1",
"type": "超清(720p)"
}
]
}
},
"succ": true
}
播放如下:
总结
至此,我们就可以通过视频详情的url解析到视频的播放地址。通过一步步分析http请求过程,达到解析的效果