123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- /*
- * @File : danmuSpider.js
- * @Author : jade
- * @Date : 2024/3/13 13:39
- * @Email : jadehh@1ive.com
- * @Software : Samples
- * @Desc :
- */
- import {_, load, Uri} from "./cat.js";
- import * as Utils from "./utils.js";
- import {JadeLogging} from "./log.js";
- import {VodDetail, VodShort} from "./vod.js";
- import {parseXML} from "./bilibili_ASS_Danmaku_Downloader.js";
- class DanmuSpider {
- constructor() {
- this.siteUrl = "https://search.youku.com"
- this.reconnectTimes = 0
- this.maxReconnectTimes = 5
- this.jadeLog = new JadeLogging(this.getAppName(), "DEBUG")
- }
- getAppName() {
- return "弹幕"
- }
- getHeader() {
- return {"User-Agent": Utils.CHROME, "Referer": this.siteUrl + "/"};
- }
- async reconnnect(reqUrl, params, headers, redirect_url, return_cookie, buffer) {
- await this.jadeLog.error("请求失败,请检查url:" + reqUrl + ",两秒后重试")
- Utils.sleep(2)
- if (this.reconnectTimes < this.maxReconnectTimes) {
- this.reconnectTimes = this.reconnectTimes + 1
- return await this.fetch(reqUrl, params, headers, redirect_url, return_cookie, buffer)
- } else {
- await this.jadeLog.error("请求失败,重连失败")
- return null
- }
- }
- async getResponse(reqUrl, params, headers, redirect_url, return_cookie, buffer, response) {
- {
- if (response.headers["location"] !== undefined) {
- if (redirect_url) {
- await this.jadeLog.debug(`返回重定向连接:${response.headers["location"]}`)
- return response.headers["location"]
- } else {
- return this.fetch(response.headers["location"], params, headers, redirect_url, return_cookie, buffer)
- }
- } else if (response.content.length > 0) {
- this.reconnectTimes = 0
- if (return_cookie) {
- return {"cookie": response.headers["set-cookie"], "content": response.content}
- } else {
- return response.content
- }
- } else if (buffer === 1) {
- this.reconnectTimes = 0
- return response.content
- } else {
- await this.jadeLog.error(`请求失败,请求url为:${reqUrl},回复内容为:${JSON.stringify(response)}`)
- return await this.reconnnect(reqUrl, params, headers, redirect_url, return_cookie, buffer)
- }
- }
- }
- async fetch(reqUrl, params, headers, redirect_url = false, return_cookie = false, buffer = 0) {
- let data = Utils.objectToStr(params)
- let url = reqUrl
- if (!_.isEmpty(data)) {
- url = reqUrl + "?" + data
- }
- let uri = new Uri(url);
- let response;
- response = await req(uri.toString(), {method: "get", headers: headers, buffer: buffer, data: null})
- if (response.code === 200 || response.code === 302 || response.code === 301 || return_cookie) {
- return await this.getResponse(reqUrl, params, headers, redirect_url, return_cookie, buffer, response)
- } else {
- await this.jadeLog.error(`请求失败,失败原因为:状态码出错,请求url为:${uri},回复内容为:${JSON.stringify(response)}`)
- return await this.reconnnect(reqUrl, params, headers, redirect_url, return_cookie, buffer)
- }
- }
- async getHtml(url = this.siteUrl, headers = this.getHeader()) {
- let html = await this.fetch(url, null, headers)
- if (!_.isEmpty(html)) {
- return load(html)
- } else {
- await this.jadeLog.error(`html获取失败`, true)
- }
- }
- async parseVodShortListFromJson(obj, vodDetail) {
- for (const componentObj of obj["pageComponentList"]) {
- if (componentObj["commonData"] !== undefined) {
- let searchVodDetail = new VodDetail()
- let commonData = componentObj["commonData"]
- searchVodDetail.type_name = commonData["feature"]
- if (commonData["notice"] !== undefined) {
- searchVodDetail.vod_actor = commonData["notice"].replaceAll("演员:", "").replaceAll(" ", "")
- }
- if (commonData["director"] !== undefined) {
- searchVodDetail.vod_director = commonData["director"].replaceAll("导演:", "").replaceAll(" ", "")
- }
- if (vodDetail.type_name === "电影") {
- searchVodDetail.vod_id = commonData["leftButtonDTO"]["action"]["value"]
- } else {
- searchVodDetail.vod_id = commonData["showId"]
- }
- searchVodDetail.vod_name = commonData["titleDTO"]["displayName"]
- if ( searchVodDetail.vod_name === vodDetail.vod_name || searchVodDetail.type_name.indexOf(vodDetail.vod_year) > -1 || searchVodDetail.type_name.indexOf(vodDetail.type_name) > -1 || searchVodDetail.vod_director === vodDetail.vod_director) {
- await this.jadeLog.debug(`匹配视频网站成功,名称为:${searchVodDetail.vod_name},类型为:${searchVodDetail.type_name},导演为:${searchVodDetail.vod_director}`, true)
- return searchVodDetail
- }
- }
- }
- await this.jadeLog.warning("没有匹配到弹幕网站")
- return null
- }
- async parseVodUrlFromJsonByEpisodeId(obj, episodeId) {
- for (const serises of obj["serisesList"]) {
- if (Utils.isNumeric(episodeId["episodeId"])) {
- if (parseInt(episodeId["episodeId"]).toString() === serises["displayName"]) {
- return serises["action"]["value"]
- }
- }
- }
- await this.jadeLog.error("没有找到匹配的集数")
- return ""
- }
- async downloadDanmu(url) {
- let json = JSON.parse(await this.fetch(url, null, this.getHeader()))
- let xml = parseXML(json)
- let params = {"do": "set", "key": "danmu", "value": xml}
- await req("http://127.0.0.1:9978/cache", {method: "post", data: params, postType: "form-data"});
- return "http://127.0.0.1:9978/cache?do=get&key=danmu"
- }
- async search(vodDetail, episodeId) {
- let params = {"pg": "1", "keyword": vodDetail.vod_name}
- let searchObj = JSON.parse(await this.fetch(this.siteUrl + "/api/search", params, this.getHeader()))
- let searchDetail = await this.parseVodShortListFromJson(searchObj, vodDetail)
- if (!_.isEmpty(searchDetail)){
- return await this.getVideoUrl(searchDetail.vod_id, episodeId)
- }else{
- return ""
- }
- }
- async getVideoUrl(showId, episodeId) {
- let url = "";
- if (!_.isEmpty(showId)) {
- if (showId.startsWith("http")) {
- url = showId
- } else {
- let params = {"appScene": "show_episode", "showIds": showId}
- let matchObj = JSON.parse(await this.fetch(this.siteUrl + "/api/search", params, this.getHeader()))
- url = await this.parseVodUrlFromJsonByEpisodeId(matchObj, episodeId)
- }
- if (!_.isEmpty(url)) {
- await this.jadeLog.debug(`弹幕视频播放连接为:${url}`)
- return await this.downloadDanmu("https://dmku.thefilehosting.com/?ac=dm&url=" + url)
- }
- }
- return url
- }
- async getDammu(voddetail, episodeId) {
- return await this.search(voddetail, episodeId)
- }
- }
- export {DanmuSpider}
|