Skip to content

Commit

Permalink
🥡将解析分离路由
Browse files Browse the repository at this point in the history
  • Loading branch information
Johnserf-Seed committed Sep 3, 2023
1 parent 1efe9e0 commit 6fec6dd
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 152 deletions.
176 changes: 24 additions & 152 deletions routes/api.js
Original file line number Diff line number Diff line change
@@ -1,164 +1,36 @@
let express = require('express');
const axios = require('axios');
const res = require('express/lib/response');
const errwin = /[\\\n\r/:*?\"<>|]/g;
const subwin = ``;
const httpurl = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/
// 获取XB参数
const express = require('express');
const { GetID, GetInfo } = require('../utils/douyinService');
const getXB = require('../utils/x-bogus.js')
// 单作品接口
const aweme_url = 'https://www.douyin.com/aweme/v1/web/aweme/detail/?'

let router = express.Router();

// 获取作品ID
var GetID = async function (res,dyurl) {
/* 获取API */
router.get('/', async function(req, res, next) {
try {
return await new Promise((resolve, reject) => {
try {
axios.get(dyurl, {
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'
}
}).then(function (response) {
// console.log(response.request.res.responseUrl);
var revideo = /video\/(\d*)/;
var item_ids = revideo.exec(response.request.res.responseUrl)[1];
console.log('作品id ' + item_ids);
resolve(item_ids);
}).catch(function (error) {
console.log(error + ' item_ids获取错误');
res.render('error');
reject(error);
});
} catch (error_1) {
console.log('获取作品ID失败 ' + error_1);
}
});
} catch (error_2) {
console.log(error_2);
res.render('error');
reject(error_2);
}
}
// 尝试从cookies中获取并解析dycookie
let dyCookie;
try {
dyCookie = JSON.parse(req.cookies['dycookie']);
} catch {
dyCookie = null;
}

// 获取作品信息
var GetInfo = async function (res,item_ids,dycookie) {
try {
return await new Promise((resolve, reject) => {
const params_url = `aweme_id=${item_ids}&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333`;
let xb = getXB(params_url);
console.log(aweme_url + params_url + `&X-Bogus=${xb}`);
axios.get(aweme_url + params_url + `&X-Bogus=${xb}`, {
headers: {
'cookie': `odin_tt=${dycookie['odin_tt']};sessionid_ss=${dycookie['sessionid_ss']};ttwid=${dycookie['ttwid']};passport_csrf_token=${dycookie['passport_csrf_token']};msToken=${dycookie['msToken']};`,
'referer': 'https://www.douyin.com/',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
}
})
.then(function (response) {
console.log('GetInfo ok');
let {
status_code
} = response.data;
// console.log(response)
if (status_code === 0) {
// 无水印视频链接
// let url = item_list.video.play_addr.url_list[0].replace(
// 'playwm',
// 'play'
// )
// let url = response.data.aweme_detail.video.play_addr.url_list[2]
let uri = response.data.aweme_detail.video.play_addr.uri;
let music = response.data.aweme_detail.music.play_url.uri;
let m_title = response.data.aweme_detail.music.title;
let unique_id = response.data.aweme_detail.author.unique_id;
let video_id = response.data.aweme_detail.aweme_id;
let aweme_type = response.data.aweme_detail.aweme_type;
let nickname = response.data.aweme_detail.author.nickname;
let userhome = 'https://www.douyin.com/user/' + response.data.aweme_detail.author.sec_uid;
let newimages = Array();
// 没有设置抖音号则获取短号
if (unique_id == '') {
unique_id = response.data.aweme_detail.author.short_id;
}
if (aweme_type == '0') {
var type = '视频';
var images = '';
} else {
var type = '图集';
var images = response.data.aweme_detail.images;
for (var i in images) {
newimages.push(images[i].url_list[0]);
}
}
// 转换成1080p
url = `http://aweme.snssdk.com/aweme/v1/play/?video_id=${uri}&ratio=1080p`;
// 视频文案过滤非法字符
let desc = response.data.aweme_detail.desc.replaceAll(errwin, subwin);

console.log('video play url ', url);
console.log('video desc ', desc);
var data = ({
url: url,
desc: desc,
music: music,
m_title: m_title,
nickname: nickname,
unique_id: unique_id,
video_id: video_id,
userhome: userhome,
type: type,
images: newimages
});
resolve(data);
} else {
console.log(status_code);
reject(status_code);
}
}).catch(function (error) {
console.log(error);
res.render('error');
reject(error);
});
});
} catch (error_1) {
console.log(error_1);
res.render('error');
reject(error_1);
}
}
// 如果未提供URL,则使用默认视频
let videoUrl = req.query.url;
if (!videoUrl) {
videoUrl = 'https://v.douyin.com/NKyY6Ch/';
}

/* GET api. */
router.get('/', async function(req, res, next) {
console.log(req.cookies['dycookie'])
if(req.cookies['dycookie'] == undefined){
var data = ({
work:false
})
res.render('index', data);
return
}
if (req.query.url == ''){
// 默认视频
req.query.url = 'https://v.douyin.com/NKyY6Ch/'
}
console.log('open shorturl ok');
// console.log(req.query.url)

// let urlReg = /(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|&|-)+)/g
// let dyurl = urlReg.exec(req.query.url)[0]
let dyurl = req.query.url;
await GetID(res,dyurl).then(item_ids => {
GetInfo(res,item_ids,req.cookies['dycookie']).then(data => {
//console.log('data',data);
res.render('index', { data });
});
}).catch((error) =>{
console.log('GetID Error',error);
res.render('error');
});
// 使用视频ID和cookie获取视频详情
const videoData = await GetInfo(videoId, dyCookie, getXB);
res.render('index', { videoData });
} catch (error) {
next(error); // 转发错误到错误处理中间件
}
});

console.log('open url ok');
});

module.exports = router;
93 changes: 93 additions & 0 deletions utils/douyinService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const axios = require("axios");

// 常量定义
const invalid = /[\\\n\r/:*?\"<>|]/g;
const repWith = ``;
const AWE_URL_BASE = "http://aweme.snssdk.com/aweme/v1/play/?";
const DETAIL_URL_BASE = 'https://www.douyin.com/aweme/v1/web/aweme/detail/?'
const USER_AGENT_MOBILE = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36";
const USER_AGENT_DESKTOP = "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";
const VIDEO_REGEX = /video\/(\d*)/;
const NOTE_REGEX = /note\/(\d*)/;

/**
* 获取作品ID
* @param {string} dyurl - 抖音短链接。
* @returns {string} 作品ID
* @throws {Error} 在请求失败或解析ID时可能会抛出错误。
*/
async function GetID(dyurl) {
const response = await axios.get(dyurl, {
headers: { "user-agent": USER_AGENT_DESKTOP },
});

if (response.request.res.responseUrl.includes('video')) {
item_ids = VIDEO_REGEX.exec(response.request.res.responseUrl)[1];
} else if (response.request.res.responseUrl.includes('note')) {
item_ids = NOTE_REGEX.exec(response.request.res.responseUrl)[1];
} else {
console.error("URL格式不匹配任何已知模式");
return;
}
return item_ids;
}

/**
* 根据作品ID和cookie获取作品详细信息
* @param {string} item_ids - 作品ID。
* @param {Object} dycookie - 抖音cookie对象。
* @param {Function} getXB - 获取XB参数的函数。
* @returns {Object} 作品的详细信息
* @throws {Error} 在请求失败或解析数据时可能会抛出错误。
*/
async function GetInfo(item_ids, dycookie, getXB) {
// 构造请求URL
const params_url = `aweme_id=${item_ids}&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333`;
const xb = getXB(params_url);
const url = `${DETAIL_URL_BASE}${params_url}&X-Bogus=${xb}`;

const response = await axios.get(url, {
headers: {
'cookie': `odin_tt=${dycookie["odin_tt"]};sessionid_ss=${dycookie["sessionid_ss"]};ttwid=${dycookie['ttwid']};passport_csrf_token=${dycookie['passport_csrf_token']};msToken=${dycookie['msToken']};`,
'referer': 'https://www.douyin.com/',
'user-agent': USER_AGENT_MOBILE
}
});

// 如果response.data为空或未定义
if (!response.data) {
return { work: false };
}

// 校验响应状态
if (response.data.status_code === 0) {
// 提取需要的数据
const { video, music, author, desc, aweme_id, aweme_type } = response.data.aweme_detail;
const unique_id = author.unique_id || author.short_id; // 如果unique_id为空,则使用short_id
const userhome = `https://www.douyin.com/user/${author.sec_uid}`;
const type = Number(aweme_type) === 0 ? '视频' : '图集';
const images = Number(aweme_type) !== 0 ? response.data.aweme_detail.images.map(image => image.url_list[0]) : [];
//const images = aweme_type !== 0 && response.data.aweme_detail.images ? response.data.aweme_detail.images.map(image => image.url_list[0]) : [];

const url = video?.bit_rate?.[0]?.play_addr?.url_list?.[0] ?? '';
const cleanedDesc = desc.replaceAll(invalid, repWith);

return {
url,
desc: cleanedDesc,
music: music.play_url.uri,
m_title: music.title,
nickname: author.nickname,
unique_id,
video_id: aweme_id,
userhome,
type,
images
};
} else {
// 如果响应状态码不为0,抛出错误
throw new Error(`Error with status code: ${response.data.status_code}`);
}
}

module.exports = { GetID, GetInfo };

0 comments on commit 6fec6dd

Please sign in to comment.