mirror of
https://github.com/lyz05/danmaku.git
synced 2026-02-02 17:59:53 +08:00
123 lines
4.0 KiB
JavaScript
123 lines
4.0 KiB
JavaScript
import axios from "axios";
|
|
import BaseSource from "./base.mjs";
|
|
import pako from "pako";
|
|
import memory from "../../utils/memory.js";
|
|
|
|
export default class IqiyiSource extends BaseSource {
|
|
constructor() {
|
|
super();
|
|
this.name = "爱奇艺";
|
|
this.domain = "iqiyi.com";
|
|
this.example_urls = [
|
|
"https://www.iqiyi.com/v_bb6gsxzz78.html",
|
|
"https://www.iqiyi.com/v_19rr1lm35o.html",
|
|
];
|
|
}
|
|
|
|
// 新的tvid获取方法
|
|
async get_tvid(url) {
|
|
const id = /v_(\w+)/.exec(url)[1];
|
|
const api = `https://pcw-api.iq.com/api/decode/${id}?platformId=3&modeCode=intl&langCode=sg`;
|
|
const response = await axios.get(api);
|
|
return response.data.data.toString();
|
|
};
|
|
|
|
// 获取视频基础信息
|
|
async get_video_info(tvid) {
|
|
const api = `https://pcw-api.iqiyi.com/video/video/baseinfo/${tvid}`;
|
|
const response = await axios.get(api);
|
|
return response.data.data;
|
|
};
|
|
|
|
async resolve(url) {
|
|
// 1. 获取tvid
|
|
const tvid = await this.get_tvid(url);
|
|
|
|
// 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 page = Math.ceil(duration / (60 * 5));
|
|
console.log("tvid:", tvid, "duration:", duration, "pages:", page);
|
|
|
|
// 4. 构建弹幕请求
|
|
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;
|
|
};
|
|
|
|
extract(xml, tag) {
|
|
const reg = new RegExp(`<${tag}>(.*?)</${tag}>`, "g");
|
|
const res = xml.match(reg)
|
|
?.map(x => x.substring(tag.length + 2, x.length - tag.length - 3));
|
|
return res || [];
|
|
}
|
|
|
|
xml2json(xml, contents, length) {
|
|
const danmaku = this.extract(xml, "content");
|
|
const showTime = this.extract(xml, "showTime");
|
|
const color = this.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(this.content_template));
|
|
content.timepoint = showTime[i];
|
|
content.color = parseInt(color[i], 16);
|
|
content.content = danmaku[i];
|
|
content.size = 25;
|
|
contents.push(content);
|
|
}
|
|
};
|
|
|
|
async parse(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();
|
|
}
|
|
return contents;
|
|
};
|
|
|
|
}
|
|
|
|
// module.exports = Iqiyi;
|
|
|
|
// if (!module.parent) {
|
|
// const m = new Iqiyi();
|
|
// m.work(m.example_urls[0])
|
|
// .then(() => {
|
|
// console.log(m.title);
|
|
// memory();
|
|
// });
|
|
// }
|