xxxx
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* @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}
|
||||
Reference in New Issue
Block a user