mirror of
https://github.com/lyz05/danmaku.git
synced 2026-02-02 17:59:53 +08:00
重构爱奇艺解析逻辑,优化tvid获取和视频信息请求
This commit is contained in:
@@ -1,138 +1,134 @@
|
|||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const pako = require("pako");
|
const pako = require("pako");
|
||||||
const {
|
const {
|
||||||
time_to_second,
|
time_to_second,
|
||||||
content_template,
|
content_template,
|
||||||
} = require("./utils");
|
} = require("./utils");
|
||||||
const memory = require("../../utils/memory");
|
const memory = require("../../utils/memory");
|
||||||
|
|
||||||
//资源消耗大 256M内存扛不住
|
|
||||||
function Iqiyi() {
|
function Iqiyi() {
|
||||||
this.name = "爱奇艺";
|
this.name = "爱奇艺";
|
||||||
this.domain = "iqiyi.com";
|
this.domain = "iqiyi.com";
|
||||||
this.example_urls = [
|
this.example_urls = [
|
||||||
"https://www.iqiyi.com/v_19rr1lm35o.html", //api lens 11
|
"https://www.iqiyi.com/v_bb6gsxzz78.html",
|
||||||
"http://www.iqiyi.com/v_1qzx9b00hs4.html?vfm=m_331_dbdy", //api lens 25
|
"https://www.iqiyi.com/v_19rr1lm35o.html",
|
||||||
"https://www.iqiyi.com/v_19rr1lm35o.html",
|
];
|
||||||
];
|
|
||||||
|
|
||||||
this.resolve = async (url) => {
|
// 新的tvid获取方法
|
||||||
const res = await axios({
|
this.get_tvid = async (url) => {
|
||||||
url: url,
|
const id = /v_(\w+)/.exec(url)[1];
|
||||||
method: "get",
|
const api = `https://pcw-api.iq.com/api/decode/${id}?platformId=3&modeCode=intl&langCode=sg`;
|
||||||
headers: {
|
const response = await axios.get(api);
|
||||||
"Accept-Encoding": "gzip,deflate,compress"
|
return response.data.data.toString();
|
||||||
}
|
};
|
||||||
});
|
|
||||||
const data = res.data;
|
|
||||||
const result = data.match(/<script id="__NEXT_DATA__" type="application\/json">(.*?)<\/script>/);
|
|
||||||
console.log(url)
|
|
||||||
let page_info = JSON.parse(result[1]);
|
|
||||||
// console.log('page_info:', page_info)
|
|
||||||
page_info = page_info.props.pageProps.videoInfo
|
|
||||||
const duration = time_to_second(page_info.duration);
|
|
||||||
this.title = page_info.tvName ? page_info.tvName : page_info.name;
|
|
||||||
const albumid = page_info.albumId;
|
|
||||||
const tvid = page_info.tvId.toString();
|
|
||||||
const categoryid = page_info.channelId;
|
|
||||||
const page = Math.round(duration / (60 * 5));
|
|
||||||
console.log("tvid", tvid);
|
|
||||||
let promises = [];
|
|
||||||
for (let i = 0; i < page; i++) {
|
|
||||||
const api_url = `https://cmts.iqiyi.com/bullet/${tvid.slice(-4, -2)}/${tvid.slice(-2)}/${tvid}_300_${i + 1}.z`;
|
|
||||||
const params = {
|
|
||||||
rn: "0.0123456789123456",
|
|
||||||
business: "danmu",
|
|
||||||
is_iqiyi: "true",
|
|
||||||
is_video_page: "true",
|
|
||||||
tvid: tvid,
|
|
||||||
albumid: albumid,
|
|
||||||
categoryid: categoryid,
|
|
||||||
qypid: "01010021010000000000"
|
|
||||||
};
|
|
||||||
promises.push(axios({
|
|
||||||
method: "get",
|
|
||||||
url: api_url,
|
|
||||||
params: params,
|
|
||||||
responseType: "arraybuffer"
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return promises;
|
|
||||||
};
|
|
||||||
|
|
||||||
function extract(xml, tag) {
|
// 获取视频基础信息
|
||||||
const reg = new RegExp(`<${tag}>(.*?)</${tag}>`, "g");
|
this.get_video_info = async (tvid) => {
|
||||||
const res = xml.match(reg)
|
const api = `https://pcw-api.iqiyi.com/video/video/baseinfo/${tvid}`;
|
||||||
?.map(x => x.substring(tag.length + 2, x.length - tag.length - 3));
|
const response = await axios.get(api);
|
||||||
return res || [];
|
return response.data.data;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.xml2json = (xml, contents,length) => {
|
this.resolve = async (url) => {
|
||||||
const danmaku = extract(xml, "content");
|
// 1. 获取tvid
|
||||||
const showTime = extract(xml, "showTime");
|
const tvid = await this.get_tvid(url);
|
||||||
const color = extract(xml, "color");
|
|
||||||
//const font = extract(xml, "font");
|
// 2. 获取视频基础信息
|
||||||
|
const videoInfo = await this.get_video_info(tvid);
|
||||||
|
this.title = videoInfo.name || videoInfo.tvName;
|
||||||
|
const duration = videoInfo.durationSec;
|
||||||
|
const albumid = videoInfo.albumId;
|
||||||
|
const categoryid = videoInfo.channelId || videoInfo.categoryId;
|
||||||
|
|
||||||
// 控制步长,减小内存占用
|
// 3. 计算需要请求的弹幕文件数量(每5分钟一个)
|
||||||
const step = Math.ceil(danmaku.length*length/10000);
|
const page = Math.ceil(duration / (60 * 5));
|
||||||
// console.log(step)
|
console.log("tvid:", tvid, "duration:", duration, "pages:", page);
|
||||||
for (let i = 0; i < danmaku.length; i+=step) {
|
|
||||||
// console.log(bulletInfo)
|
|
||||||
const content = JSON.parse(JSON.stringify(content_template));
|
|
||||||
content.timepoint = showTime[i];//showTime
|
|
||||||
content.color = parseInt(color[i], 16);//color
|
|
||||||
content.content = danmaku[i]; //content
|
|
||||||
content.size = 25;//font
|
|
||||||
contents.push(content);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.parse = async (promises) => {
|
// 4. 构建弹幕请求
|
||||||
memory();
|
let promises = [];
|
||||||
//筛选出成功的请求
|
for (let i = 0; i < page; i++) {
|
||||||
let datas = (await Promise.allSettled(promises))
|
const api_url = `https://cmts.iqiyi.com/bullet/${tvid.slice(-4, -2)}/${tvid.slice(-2)}/${tvid}_300_${i + 1}.z`;
|
||||||
.filter(x => x.status === "fulfilled")
|
const params = {
|
||||||
.map(x => x.value.data);
|
rn: "0.0123456789123456",
|
||||||
memory();
|
business: "danmu",
|
||||||
let contents = [];
|
is_iqiyi: "true",
|
||||||
for (let i = 0; i < datas.length; i++) {
|
is_video_page: "true",
|
||||||
const data = datas[i];
|
tvid: tvid,
|
||||||
let xml = pako.inflate(data, { to: "string" });
|
albumid: albumid,
|
||||||
this.xml2json(xml, contents,datas.length);
|
categoryid: categoryid,
|
||||||
datas[i] = null;
|
qypid: "01010021010000000000"
|
||||||
xml = null;
|
};
|
||||||
if (global.gc) {
|
promises.push(axios({
|
||||||
global.gc();
|
method: "get",
|
||||||
}
|
url: api_url,
|
||||||
memory();
|
params: params,
|
||||||
}
|
responseType: "arraybuffer"
|
||||||
// contents = make_response(contents);
|
}));
|
||||||
memory();
|
}
|
||||||
return contents;
|
return promises;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.work = async (url) => {
|
function extract(xml, tag) {
|
||||||
const promises = await this.resolve(url);
|
const reg = new RegExp(`<${tag}>(.*?)</${tag}>`, "g");
|
||||||
console.log(this.name, "api lens:", promises.length);
|
const res = xml.match(reg)
|
||||||
this.content = await this.parse(promises);
|
?.map(x => x.substring(tag.length + 2, x.length - tag.length - 3));
|
||||||
return {
|
return res || [];
|
||||||
title: this.title,
|
}
|
||||||
content: this.content,
|
|
||||||
msg: "ok"
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
this.xml2json = (xml, contents, length) => {
|
||||||
|
const danmaku = extract(xml, "content");
|
||||||
|
const showTime = extract(xml, "showTime");
|
||||||
|
const color = extract(xml, "color");
|
||||||
|
|
||||||
|
const step = Math.ceil(danmaku.length * length / 10000);
|
||||||
|
for (let i = 0; i < danmaku.length; i += step) {
|
||||||
|
const content = JSON.parse(JSON.stringify(content_template));
|
||||||
|
content.timepoint = showTime[i];
|
||||||
|
content.color = parseInt(color[i], 16);
|
||||||
|
content.content = danmaku[i];
|
||||||
|
content.size = 25;
|
||||||
|
contents.push(content);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.parse = async (promises) => {
|
||||||
|
memory();
|
||||||
|
let datas = (await Promise.allSettled(promises))
|
||||||
|
.filter(x => x.status === "fulfilled")
|
||||||
|
.map(x => x.value.data);
|
||||||
|
memory();
|
||||||
|
let contents = [];
|
||||||
|
for (let i = 0; i < datas.length; i++) {
|
||||||
|
const data = datas[i];
|
||||||
|
let xml = pako.inflate(data, { to: "string" });
|
||||||
|
this.xml2json(xml, contents, datas.length);
|
||||||
|
datas[i] = null;
|
||||||
|
xml = null;
|
||||||
|
if (global.gc) global.gc();
|
||||||
|
memory();
|
||||||
|
}
|
||||||
|
return contents;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.work = async (url) => {
|
||||||
|
const promises = await this.resolve(url);
|
||||||
|
console.log(this.name, "api lens:", promises.length);
|
||||||
|
this.content = await this.parse(promises);
|
||||||
|
return {
|
||||||
|
title: this.title,
|
||||||
|
content: this.content,
|
||||||
|
msg: "ok"
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Iqiyi;
|
module.exports = Iqiyi;
|
||||||
|
|
||||||
if (!module.parent) {
|
if (!module.parent) {
|
||||||
const m = new Iqiyi();
|
const m = new Iqiyi();
|
||||||
|
m.work(m.example_urls[0])
|
||||||
m.work(m.example_urls[1])
|
.then(() => {
|
||||||
.then(() => {
|
console.log(m.title);
|
||||||
// console.log(m.content);
|
memory();
|
||||||
console.log(m.title);
|
});
|
||||||
memory();
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user