123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- /*
- * @File : cntv.js
- * @Author : jade
- * @Date : 2024/4/25 10:26
- * @Email : jadehh@1ive.com
- * @Software : Samples
- * @Desc :
- */
- import {Spider} from "./spider.js";
- import {_} from "../lib/cat.js";
- import * as Utils from "../lib/utils.js";
- import {VodDetail, VodShort} from "../lib/vod.js";
- class CNTVSpider extends Spider {
- constructor() {
- super();
- this.siteUrl = "https://tv.cctv.com/m/index.shtml"
- this.apiUrl = "https://api.app.cctv.com"
- this.liveJsonUrl = "https://gh.con.sh/https://github.com/jadehh/LiveSpider/blob/main/json/live.json"
- }
- getName() {
- return "🤵♂️┃中央影视┃🤵♂️"
- }
- getAppName() {
- return "中央影视"
- }
- getJSName() {
- return "cntv"
- }
- getType() {
- return 3
- }
- async spiderInit() {
- await super.spiderInit();
- this.liveJson = JSON.parse(await this.fetch(this.liveJsonUrl, null, null))
- }
- async init(cfg) {
- await super.init(cfg);
- await this.spiderInit()
- }
- async getFilterByLive(dataList) {
- let extend_list = []
- let extend_dic = {"key": "live", "name": "直播", "value": []}
- for (const data of dataList) {
- if (data["appBarTitle"] !== "最近常看") {
- extend_dic["value"].push({"n": data["appBarTitle"], "v": data["pageId"]})
- }
- }
- extend_list.push(extend_dic)
- return extend_list
- }
- arrayIsinclude(str, items) {
- let isInclude = false
- for (const data of items) {
- if (str === data["title"]) {
- return true
- }
- }
- return isInclude
- }
- async getFilterByTv(dataList) {
- let extend_list = []
- for (const data of dataList) {
- let add_year_status = false
- let extend_dic = {"key": data["classname"], "name": data["title"], "value": []}
- for (const extendData of data["items"]) {
- if (data["classname"] === "nianfen") {
- if (!this.arrayIsinclude("2024", data["items"]) && extendData["title"] !== "全部" && !add_year_status) {
- extend_dic["value"].push({"n": "2024", "v": "2024"})
- add_year_status = true
- }
- }
- extend_dic["value"].push({"n": extendData["title"], "v": extendData["title"]})
- }
- extend_list.push(extend_dic)
- }
- return extend_list
- }
- async setClasses() {
- let liveTypeId = "cctvlive"
- let liveApi = this.apiUrl + `/api/navigation/iphone/AppStore/7.9.4/${liveTypeId}`
- let liveJson = JSON.parse(await this.fetch(liveApi, null, this.getHeader()))
- let extend_list = await this.getFilterByLive(liveJson["data"]["templates"])
- let defaultLiveId = extend_list[0]["value"][0]["v"]
- this.classes.push(this.getTypeDic("直播", defaultLiveId))
- this.filterObj[defaultLiveId] = extend_list
- let tvApi = "https://cbox.cctv.com/cboxpcvip/online2022/yxg/data1.jsonp?=pk"
- let tvContent = await this.fetch(tvApi, null, this.getHeader())
- let tvJSon = JSON.parse(tvContent.replaceAll("pk(", "").replaceAll(")", ""))
- for (const data of tvJSon["data"]) {
- let typeName = data["title"]
- this.classes.push(this.getTypeDic(typeName, typeName))
- this.filterObj[typeName] = await this.getFilterByTv(data["templates"])
- }
- }
- parseVodShortByJson(items) {
- let vod_list = []
- for (const item of items) {
- let vodShort = new VodShort()
- vodShort.vod_pic = item["img1"]
- if (_.isEmpty(vodShort.vod_pic)) {
- vodShort.vod_pic = item["epgHorizontalPic"]
- vodShort.vod_id = "live-" + item["epgChnlChar"] + "-" + vodShort.vod_pic
- } else {
- vodShort.vod_id = "play-" + item["playid"] + "-" + vodShort.vod_pic
- vodShort.vod_pic = item["img1"]
- }
- vodShort.vod_name = item["title"]
- vod_list.push(vodShort)
- }
- return vod_list
- }
- parseVodShortByTvJson(items) {
- let vod_list = []
- for (const item of items) {
- let vodShort = new VodShort()
- //关键是如何获取GUID 2d3224585904496ea837f682da0c4aa6
- vodShort.vod_id = "url-" + item["vsetid"]
- vodShort.vod_name = item["title"]
- vodShort.vod_pic = item["image"]
- vodShort.vod_remarks = item["sc"]
- vod_list.push(vodShort)
- }
- return vod_list
- }
- async parseVodShortListFromJson(objList) {
- let vod_list = []
- let top_status = false
- for (const data of objList) {
- if (data["title"] === "今日热点") {
- top_status = true
- } else if (!_.isEmpty(data["title"])) {
- if (top_status) {
- break
- }
- }
- if (top_status) {
- vod_list = [...vod_list, ...this.parseVodShortByJson(data["items"])]
- }
- }
- return vod_list
- }
- async getLiveUrl(channel_id, obj) {
- let liveApiUrl = `https://vdn.live.cntv.cn/api2/live.do?channel=pd://cctv_p2p_hd${channel_id}&client=iosapp`
- let liveResponse = await req(liveApiUrl, {"headers": this.getHeader()})
- let liveJson = JSON.parse(liveResponse["content"])
- let playList = {}
- let channelName = obj["channelName"].split(" ")[0].replaceAll("-", "").toLowerCase()
- let liveUrl = this.liveJson[channelName] ?? liveJson["hls_url"]["hls2"]
- playList["直播"] = ["点击播放$" + liveUrl]
- await this.jadeLog.info(`liveJson:${JSON.stringify(liveJson)}`)
- let vod_items = []
- if (this.liveJson[channelName] !== undefined) {
- } else {
- for (const data of obj["program"]) {
- let episodeName = data["showTime"] + "-" + data["t"]
- let episodeUrl = liveUrl + `?begintimeabs=${data["st"] * 1000}&endtimeabs=${data["et"] * 1000}`
- vod_items.push(episodeName + "$" + episodeUrl)
- }
- }
- if (vod_items.length > 0){
- playList["点播"] = vod_items.join("#")
- }
- return playList
- }
- async getVideoUrl(guid) {
- return {"中央影视": ['点击播放' + '$' + guid].join("#")}
- }
- async parseVodDetailfromJson(id, obj, pic) {
- let vodDetail = new VodDetail()
- let $;
- let guid;
- if (obj["url"] !== undefined) {
- vodDetail.vod_name = obj["title"]
- vodDetail.vod_pic = obj["img"]
- vodDetail.type_name = obj["tags"]
- vodDetail.vod_year = obj["time"]
- vodDetail.vod_content = obj["vset_brief"]
- vodDetail.vod_director = obj["vset_title"]
- $ = await this.getHtml(obj["url"])
- } else {
- if (_.isEmpty(obj["lvUrl"])) {
- vodDetail.vod_name = obj["channelName"]
- vodDetail.vod_pic = pic
- } else {
- $ = await this.getHtml(obj["lvUrl"])
- vodDetail.vod_name = $('[property$=title]')[0].attribs.content
- vodDetail.vod_content = $('[property$=description]')[0].attribs.content
- let pic = $('[property$=image]')[0].attribs.content
- if (!pic.startsWith("http")) {
- pic = "https:" + pic
- }
- vodDetail.vod_pic = pic
- }
- }
- if (!_.isEmpty($)) {
- guid = Utils.getStrByRegex(/var guid = "(.*?)"/, $.html())
- }
- let playlist
- if (_.isEmpty(guid) && obj["url"] === undefined) {
- playlist = await this.getLiveUrl(id, obj)
- } else {
- playlist = await this.getVideoUrl(guid)
- }
- vodDetail.vod_play_url = _.values(playlist).join('$$$');
- vodDetail.vod_play_from = _.keys(playlist).join('$$$');
- return vodDetail
- }
- async parseVodDetailFromJsonByTv(obj) {
- let vodDetail = new VodDetail()
- vodDetail.vod_name = obj["videoSetInfo"]["title"]
- vodDetail.type_name = obj["videoSetInfo"]["sc"]
- vodDetail.vod_pic = obj["videoSetInfo"]["image"]
- vodDetail.vod_content = obj["videoSetInfo"]["brief"]
- vodDetail.vod_area = obj["videoSetInfo"]["area"]
- let playlist = {}
- let vodItems = []
- for (const data of obj["videoRoughCut"]) {
- let title = data["title"].split("》").slice(-1)[0]
- vodItems.push(title + "$" + data["guid"])
- }
- playlist["中央影视"] = vodItems.join("#")
- vodDetail.vod_play_url = _.values(playlist).join('$$$');
- vodDetail.vod_play_from = _.keys(playlist).join('$$$');
- return vodDetail
- }
- async setHomeVod() {
- let resJson = JSON.parse(await this.fetch(this.apiUrl + "/api/page/iphone/HandheldApplicationSink/7.0.0/158", null, this.getHeader()))
- this.homeVodList = await this.parseVodShortListFromJson(resJson["data"]["templates"])
- }
- getExtendValue(extend, key) {
- if (extend[key] !== undefined && extend[key] !== "全部") {
- return extend[key]
- }
- return ""
- }
- async setCategory(tid, pg, filter, extend) {
- if (Utils.isNumeric(tid)) {
- tid = extend["live"] ?? tid
- let url = this.apiUrl + `/api/page/iphone/HandheldApplicationSink/7.0.0/${tid}`
- let response = JSON.parse(await this.fetch(url, null, this.getHeader()))
- this.vodList = this.parseVodShortByJson(response["data"]["templates"][0]["items"])
- } else {
- let letter = this.getExtendValue(extend, "zimu")
- let area = this.getExtendValue(extend, "diqu")
- let type = this.getExtendValue(extend, "leixing")
- let year = this.getExtendValue(extend, "nianfen")
- const limit = 12
- let url = "https://api.cntv.cn" + `/newVideoset/getCboxVideoAlbumList`
- let params = {
- "channelid": "",
- "sc": type,
- "fc": tid,
- "p": pg,
- "n": limit,
- "fl": letter,
- "area": area,
- "year": year,
- "serviceId": "cbox"
- }
- let resJson = JSON.parse(await this.fetch(url, params, this.getHeader()))
- this.vodList = this.parseVodShortByTvJson(resJson["data"]["list"])
- }
- }
- async setDetail(id) {
- //区分直播还是点播
- let aList = id.split("-")
- let playType = aList[0]
- let pic = aList[2]
- id = aList[1]
- if (playType === "play") {
- let resJson = JSON.parse(await this.fetch(`https://api.cntv.cn/video/videoinfoByGuid?serviceId=cbox&guid=${id}`, null, this.getHeader()))
- this.vodDetail = await this.parseVodDetailfromJson(id, resJson, pic)
- } else if (playType === "url") {
- let url = `https://api.app.cctv.com/api/getVideoPageDetail?videoSetContentId=${id}`
- let resJson = JSON.parse(await this.fetch(url, null, this.getHeader()))
- this.vodDetail = await this.parseVodDetailFromJsonByTv(resJson["data"])
- } else {
- let content = (await this.fetch(`https://api.cntv.cn/epg/epginfo3?serviceId=shiyi&c=${id}&cb=LiveTileShow.prototype.getEpg`, null, this.getHeader())).replaceAll("LiveTileShow.prototype.getEpg(", "").replaceAll(");", "")
- this.vodDetail = await this.parseVodDetailfromJson(id, JSON.parse(content)[id], pic)
- }
- }
- async setSearch(wd, quick, pg) {
- }
- async setPlay(flag, id, flags) {
- if (id.startsWith("http")) {
- this.playUrl = id
- let headers = this.getHeader()
- headers["Referer"] = "https://tv.cctv.com/"
- this.result.header = headers
- } else {
- this.playUrl = 'https://hls.cntv.myhwcdn.cn/asp/hls/2000/0303000a/3/default/' + id + '/2000.m3u8'
- }
- }
- }
- let spider = new CNTVSpider()
- async function init(cfg) {
- await spider.init(cfg)
- }
- async function home(filter) {
- return await spider.home(filter)
- }
- async function homeVod() {
- return await spider.homeVod()
- }
- async function category(tid, pg, filter, extend) {
- return await spider.category(tid, pg, filter, extend)
- }
- async function detail(id) {
- return await spider.detail(id)
- }
- async function play(flag, id, flags) {
- return await spider.play(flag, id, flags)
- }
- async function search(wd, quick) {
- return await spider.search(wd, quick)
- }
- export function __jsEvalReturn() {
- return {
- init: init, home: home, homeVod: homeVod, category: category, detail: detail, play: play, search: search,
- };
- }
- export {spider, CNTVSpider}
|