|
@@ -56,8 +56,24 @@ getStringBetween = (string, needleStart, needleEnd, offsetStart = 0, offsetEnd =
|
|
return string.substring(x + needleStart.length + offsetEnd, y + offsetStart);
|
|
return string.substring(x + needleStart.length + offsetEnd, y + offsetStart);
|
|
}
|
|
}
|
|
|
|
|
|
-getUrlFromSignature = (signatureCipher, baseContent) => {
|
|
|
|
|
|
+var cache = {}
|
|
|
|
+extractJSSignatureFunction = async (baseJsUrl, local) => {
|
|
|
|
+ console.log(`解析baseUrl: ${baseJsUrl}`);
|
|
|
|
+ if (cache[baseJsUrl]) {
|
|
|
|
+ console.log(`从缓存中获取JSSignatureFunction: ${baseJsUrl}`);
|
|
|
|
+ return cache[baseJsUrl];
|
|
|
|
+ }
|
|
|
|
+ const headers = {
|
|
|
|
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Safari/537.36',
|
|
|
|
+ }
|
|
|
|
+ const baseContent = await request('GET', baseJsUrl, null, headers, local);
|
|
const decipher = getDecipherFunction(baseContent);
|
|
const decipher = getDecipherFunction(baseContent);
|
|
|
|
+ cache[baseJsUrl] = decipher;
|
|
|
|
+ return decipher;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+getUrlFromSignature = async (signatureCipher, baseJsUrl, local) => {
|
|
|
|
+ const decipher = await extractJSSignatureFunction(baseJsUrl, local);
|
|
const searchParams = {}
|
|
const searchParams = {}
|
|
for (const item of signatureCipher.split("&")) {
|
|
for (const item of signatureCipher.split("&")) {
|
|
const [key, value] = item.split('=');
|
|
const [key, value] = item.split('=');
|
|
@@ -113,11 +129,6 @@ detail = async (url, local) => {
|
|
}
|
|
}
|
|
const html = await request('GET', url, null, headers, local);
|
|
const html = await request('GET', url, null, headers, local);
|
|
|
|
|
|
- let baseJsUrl = `https://www.youtube.com${JSON.parse(html.match(/set\(({.+?})\);/)[1])["PLAYER_JS_URL"]}`
|
|
|
|
- console.log(`解析baseUrl: ${baseJsUrl}`);
|
|
|
|
-
|
|
|
|
- const baseContent = await request('GET', baseJsUrl, null, headers, local);
|
|
|
|
-
|
|
|
|
let regex = /var ytInitialPlayerResponse\s*=\s*({.*?});/;
|
|
let regex = /var ytInitialPlayerResponse\s*=\s*({.*?});/;
|
|
let match = html.match(regex);
|
|
let match = html.match(regex);
|
|
if (!match || !match.length) {
|
|
if (!match || !match.length) {
|
|
@@ -136,11 +147,14 @@ detail = async (url, local) => {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ let baseJsUrl = `https://www.youtube.com${JSON.parse(html.match(/set\(({.+?})\);/)[1])["PLAYER_JS_URL"]}`
|
|
|
|
+ console.log(`解析baseUrl: ${baseJsUrl}`);
|
|
|
|
+
|
|
const formats = []
|
|
const formats = []
|
|
for (let format of [].concat(ytInitialPlayerResponse["streamingData"]["formats"]).concat(ytInitialPlayerResponse["streamingData"]["adaptiveFormats"])) {
|
|
for (let format of [].concat(ytInitialPlayerResponse["streamingData"]["formats"]).concat(ytInitialPlayerResponse["streamingData"]["adaptiveFormats"])) {
|
|
console.log(`format: ${JSON.stringify(format)}`);
|
|
console.log(`format: ${JSON.stringify(format)}`);
|
|
if (!format["url"]) {
|
|
if (!format["url"]) {
|
|
- format["url"] = getUrlFromSignature(format["signatureCipher"], baseContent);
|
|
|
|
|
|
+ format["url"] = await getUrlFromSignature(format["signatureCipher"], baseJsUrl, local);
|
|
}
|
|
}
|
|
if (format["url"]) {
|
|
if (format["url"]) {
|
|
const {vcodec, acodec} = parseCodecs(format)
|
|
const {vcodec, acodec} = parseCodecs(format)
|