pipixia.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /*
  2. * @File : pipixia.js
  3. * @Author : jade
  4. * @Date : 2024/2/2 13:33
  5. * @Email : jadehh@1ive.com
  6. * @Software : Samples
  7. * @Desc : 完成所有的功能开发(已失效)
  8. */
  9. import {_, Crypto, load} from '../lib/cat.js';
  10. import {VodDetail, VodShort} from "../lib/vod.js"
  11. import * as Utils from "../lib/utils.js";
  12. import {Spider} from "./spider.js";
  13. import {pipixiaMd5} from "../lib/pipiXiaObject.js"
  14. class PiPiXiaSpider extends Spider {
  15. constructor() {
  16. super();
  17. this.siteUrl = "http://aikun.tv/"
  18. this.pipixiaReconnectTimes = 0
  19. }
  20. getHeader() {
  21. let headers = super.getHeader();
  22. headers["Connection"] = "keep-alive"
  23. headers["Host"] = "pipixia.vip"
  24. return headers
  25. }
  26. getName() {
  27. return `🦐┃皮皮虾影视┃🦐`
  28. }
  29. getAppName() {
  30. return `皮皮虾影视`
  31. }
  32. getJSName() {
  33. return "pipixia"
  34. }
  35. getType() {
  36. return 3
  37. }
  38. async parseVodShortListFromDoc($) {
  39. let vod_list = []
  40. let vodElements = $($("[class=\"wow fadeInUp animated\"]")).find("[class=\"public-list-box public-pic-b\"]")
  41. for (const vodElement of vodElements) {
  42. let vodShort = new VodShort()
  43. vodShort.vod_id = Utils.getStrByRegex(/v\/(.*?).html/, $(vodElement).find("a")[0].attribs.href)
  44. vodShort.vod_name = $(vodElement).find("a")[0].attribs.title
  45. vodShort.vod_pic = this.baseProxy + Utils.base64Encode(this.siteUrl + "/" + $(vodElement).find("[class=\"lazy gen-movie-img mask-1\"]")[0].attribs["data-original"])
  46. vod_list.push(vodShort)
  47. }
  48. return vod_list
  49. }
  50. async parseVodShortListFromDocBySearch($) {
  51. let vod_list = []
  52. let vodElements = $("[class=\"row-right hide\"]").find("[class=\"search-box flex rel\"]")
  53. for (const vodElement of vodElements) {
  54. let vodShort = new VodShort();
  55. vodShort.vod_pic = this.baseProxy + Utils.base64Encode(this.siteUrl + "/" + Utils.getStrByRegex(/url\((.*?)\);/, $(vodElement).find("[class=\"cover\"]")[0].attribs.style))
  56. vodShort.vod_remarks = $($(vodElement).find("[class=\"public-list-prb hide ft2\"]")).html()
  57. vodShort.vod_name = $($(vodElement).find("[class=\"thumb-txt cor4 hide\"]")).html()
  58. vodShort.vod_id = Utils.getStrByRegex(/v\/(.*?).html/, $(vodElement).find("[class=\"button\"]")[0].attribs.href)
  59. vod_list.push(vodShort)
  60. }
  61. return vod_list
  62. }
  63. async parseVodShortListFromJson(obj) {
  64. let vod_list = []
  65. for (const vod_json of obj["list"]) {
  66. let vodShort = new VodShort();
  67. vodShort.vod_name = vod_json["vod_name"]
  68. vodShort.vod_id = vod_json["vod_id"]
  69. vodShort.vod_pic = this.baseProxy + Utils.base64Encode(this.siteUrl + "/" + vod_json["vod_pic"])
  70. vodShort.vod_remarks = vod_json["vod_remarks"]
  71. vod_list.push(vodShort)
  72. }
  73. return vod_list
  74. }
  75. async parseVodDetailFromDoc($) {
  76. let vodDetail = new VodDetail();
  77. let detailElement = $("[class=\"vod-detail style-detail rel box cor1\"]")
  78. vodDetail.vod_name = $($(detailElement).find("[class=\"slide-info-title hide\"]")).text()
  79. vodDetail.vod_pic = this.siteUrl + $(detailElement).find("[class=\"detail-pic lazy mask-1\"]")[0].attribs["data-original"]
  80. vodDetail.vod_remarks = $($($(detailElement).find("[class=\"slide-info hide\"]")[0]).find("[class=\"slide-info-remarks\"]")[0]).text()
  81. vodDetail.vod_year = $($($(detailElement).find("[class=\"slide-info hide\"]")[0]).find("[class=\"slide-info-remarks\"]")[1]).text()
  82. vodDetail.vod_area = $($($(detailElement).find("[class=\"slide-info hide\"]")[0]).find("[class=\"slide-info-remarks\"]")[2]).text()
  83. vodDetail.vod_director = $($($(detailElement).find("[class=\"slide-info hide\"]")[1]).find("a")).text()
  84. vodDetail.vod_actor = $($($(detailElement).find("[class=\"slide-info hide\"]")[2]).find("a")).text()
  85. let type_list = []
  86. for (const typeEle of $($(detailElement).find("[class=\"slide-info hide\"]")[3]).find("a")) {
  87. type_list.push($(typeEle).text())
  88. }
  89. vodDetail.type_name = type_list.join("/")
  90. vodDetail.vod_content = $($("[class=\"check text selected cor3\"]")).text()
  91. let playElemet = $("[class=\"anthology wow fadeInUp animated\"]")
  92. let playFormatElemets = $(playElemet).find("[class=\"swiper-slide\"]")
  93. let playUrlElements = $(playElemet).find("[class=\"anthology-list-play size\"]")
  94. let vod_play_from_list = []
  95. let vod_play_list = []
  96. for (let i = 0; i < playFormatElemets.length; i++) {
  97. let playFormatElement = playFormatElemets[i]
  98. vod_play_from_list.push(playFormatElement.children[1].data)
  99. let vodItems = []
  100. for (const playUrlElement of $(playUrlElements[i]).find("a")) {
  101. let episodeName = $(playUrlElement).text()
  102. let episodeUrl = playUrlElement.attribs.href
  103. vodItems.push(episodeName + "$" + episodeUrl)
  104. }
  105. vod_play_list.push(vodItems.join("#"))
  106. }
  107. vodDetail.vod_play_from = vod_play_from_list.join("$$$")
  108. vodDetail.vod_play_url = vod_play_list.join("$$$")
  109. return vodDetail
  110. }
  111. async getHtml(url = this.siteUrl, headers = this.getHeader()) {
  112. try {
  113. let html = await this.fetch(url, null, headers)
  114. if (!_.isEmpty(html) && html.indexOf("江苏反诈公益宣传") === -1) {
  115. return load(html)
  116. } else {
  117. if (this.pipixiaReconnectTimes < this.maxReconnectTimes) {
  118. Utils.sleep(2)
  119. this.pipixiaReconnectTimes = this.pipixiaReconnectTimes + 1
  120. return await this.getHtml(url, headers)
  121. } else {
  122. await this.jadeLog.error(`html获取失败`, true)
  123. }
  124. }
  125. } catch (e) {
  126. await this.jadeLog.error(`获取html出错,出错原因为${e}`)
  127. }
  128. }
  129. async setClasses() {
  130. let $ = await this.getHtml()
  131. this.classes = [this.getTypeDic("首页", "最近更新")]
  132. let $2 = await this.getHtml(this.siteUrl + "/s/1.html")
  133. let classElemets = $2("[class=\"nav-swiper rel\"]")[0]
  134. for (const classElement of $(classElemets).find("a")) {
  135. let type_id = Utils.getStrByRegex(/\/s\/(.*?).html/, classElement.attribs.href)
  136. let type_name = $(classElement).text()
  137. this.classes.push(this.getTypeDic(type_name, type_id))
  138. }
  139. }
  140. async getFilter($) {
  141. let elements = $("[class=\"nav-swiper rel\"]")
  142. let extend_list = []
  143. for (let i = 0; i < elements.length; i++) {
  144. let element = elements[i]
  145. let name = $($($(element).find("[class=\"filter-text bj cor5\"]")).find("span")).html()
  146. if (name !== "频道") {
  147. let extend_dic = {"key": (i + 1).toString(), "name": name, "value": []}
  148. for (const ele of $(element).find("a")) {
  149. extend_dic["value"].push({"n": $(ele).text(), "v": $(ele).text()})
  150. }
  151. extend_list.push(extend_dic)
  152. }
  153. }
  154. return extend_list
  155. }
  156. async setFilterObj() {
  157. for (const type_dic of this.classes) {
  158. let type_id = type_dic["type_id"]
  159. if (Utils.isNumeric(type_id)) {
  160. let url = this.siteUrl + `/s/${type_id}.html`
  161. let $ = await this.getHtml(url)
  162. this.filterObj[type_id] = await this.getFilter($)
  163. }
  164. }
  165. }
  166. async setHomeVod() {
  167. let $ = await this.getHtml(this.siteUrl + "/map.html")
  168. this.homeVodList = await this.parseVodShortListFromDoc($)
  169. }
  170. getExtend(extend, key) {
  171. if (extend[key] !== undefined && extend[key] !== "全部") {
  172. return extend[key]
  173. } else {
  174. return null
  175. }
  176. }
  177. getExtendDic(params, extend) {
  178. let class_value = this.getExtend(extend, "2")
  179. if (class_value !== null) {
  180. params["class"] = class_value
  181. }
  182. let area_value = this.getExtend(extend, "3")
  183. if (area_value !== null) {
  184. params["area"] = area_value
  185. }
  186. let year_value = this.getExtend(extend, "4")
  187. if (year_value !== null) {
  188. params["year"] = year_value
  189. }
  190. let lang_value = this.getExtend(extend, "5")
  191. if (lang_value !== null) {
  192. params["lang"] = lang_value
  193. }
  194. let letter_value = this.getExtend(extend, "6")
  195. if (letter_value !== null) {
  196. params["letter"] = letter_value
  197. }
  198. return params
  199. }
  200. async setCategory(tid, pg, filter, extend) {
  201. if (Utils.isNumeric(tid)) {
  202. let url = this.siteUrl + "/index.php/api/vod"
  203. let time_1 = Math.floor(new Date().getTime() / 1000)
  204. let key_1 = pipixiaMd5(time_1)
  205. let params = {
  206. "type": tid, "page": pg, "time": time_1.toString(), "key": key_1
  207. }
  208. params = this.getExtendDic(params, extend)
  209. let content = await this.post(url, params, this.getHeader())
  210. if (!_.isEmpty(content)) {
  211. let content_json = JSON.parse(content)
  212. if (content_json["code"] === 1) {
  213. this.vodList = await this.parseVodShortListFromJson(content_json)
  214. }
  215. }
  216. }
  217. }
  218. async setDetail(id) {
  219. let $ = await this.getHtml(this.siteUrl + `/v/${id}.html`)
  220. this.vodDetail = await this.parseVodDetailFromDoc($)
  221. }
  222. async getPlayConfig(element) {
  223. // let playJSUrl = this.siteUrl + element.attribs.src
  224. // let jsContent = await this.fetch(playJSUrl,null,null)
  225. // let playListConfig = JSON.parse(Utils.getStrByRegex(/MacPlayerConfig.player_list=(.*?),MacPlayerConfig/,jsContent))
  226. //
  227. let playListConfig = {
  228. "qq": {
  229. "show": "QQ虾线",
  230. "des": "",
  231. "ps": "1",
  232. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  233. }, "qiyi": {
  234. "show": "QY虾线",
  235. "des": "",
  236. "ps": "1",
  237. "parse": "http://play.shijie.chat/player/ec.php?code=qiyi&if=1&url="
  238. }, "youku": {
  239. "show": "YK虾线",
  240. "des": "",
  241. "ps": "1",
  242. "parse": "http://play.shijie.chat/player/ec.php?code=youku&if=1&url="
  243. }, "mgtv": {
  244. "show": "MG虾线",
  245. "des": "",
  246. "ps": "1",
  247. "parse": "http://play.shijie.chat/player/ec.php?code=mgtv&if=1&url="
  248. }, "NBY": {
  249. "show": "极速线路",
  250. "des": "",
  251. "ps": "1",
  252. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  253. }, "SLNB": {
  254. "show": "三路极速",
  255. "des": "",
  256. "ps": "1",
  257. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  258. }, "FYNB": {
  259. "show": "APP专享线路",
  260. "des": "",
  261. "ps": "0",
  262. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  263. }, "SPA": {
  264. "show": "极速A",
  265. "des": "",
  266. "ps": "0",
  267. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  268. }, "SPB": {
  269. "show": "极速B",
  270. "des": "",
  271. "ps": "1",
  272. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  273. }, "kyB": {
  274. "show": "极速直连",
  275. "des": "",
  276. "ps": "1",
  277. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  278. }, "JMZN": {
  279. "show": "极速直连",
  280. "des": "",
  281. "ps": "1",
  282. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  283. }, "ZNJSON": {
  284. "show": "极速直连",
  285. "des": "",
  286. "ps": "1",
  287. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  288. }, "znkan": {
  289. "show": "极速直连",
  290. "des": "",
  291. "ps": "1",
  292. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  293. }, "bilibili": {
  294. "show": "BLBL虾线",
  295. "des": "",
  296. "ps": "1",
  297. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  298. }, "pptv": {
  299. "show": "PP虾线", "des": "", "ps": "1", "parse": "http://play.shijie.chat/player/?url="
  300. }, "letv": {
  301. "show": "LE虾线", "des": "", "ps": "1", "parse": "http://play.shijie.chat/player/?url="
  302. }, "sohu": {
  303. "show": "SH虾线", "des": "", "ps": "1", "parse": "http://play.shijie.chat/player/?url="
  304. }, "DJMP4": {
  305. "show": "短剧专用",
  306. "des": "",
  307. "ps": "1",
  308. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  309. }, "CLDJ": {
  310. "show": "短剧①",
  311. "des": "",
  312. "ps": "1",
  313. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  314. }, "ChenXi": {
  315. "show": "短剧专用2",
  316. "des": "",
  317. "ps": "1",
  318. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  319. }, "HT-": {
  320. "show": "自营线",
  321. "des": "",
  322. "ps": "1",
  323. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  324. }, "htys": {
  325. "show": "解说线路", "des": "", "ps": "1", "parse": "http://play.shijie.chat/player/?url="
  326. }, "sgdj": {
  327. "show": "短剧③",
  328. "des": "",
  329. "ps": "1",
  330. "parse": "http://play.shijie.chat/player/ec.php?code=qq&if=1&url="
  331. }
  332. }
  333. return playListConfig
  334. }
  335. uic(url, uid) {
  336. let ut = Crypto.enc.Utf8.parse('2890' + uid + 'tB959C');
  337. let mm = Crypto.enc.Utf8.parse("2F131BE91247866E");
  338. let decrypted = Crypto.AES.decrypt(url, ut, {iv: mm, mode: Crypto.mode.CBC, padding: Crypto.pad.Pkcs7});
  339. return Crypto.enc.Utf8.stringify(decrypted);
  340. }
  341. async setVideoProxy(playUrl){
  342. let urls = []
  343. urls.push('proxy');
  344. urls.push(playUrl);
  345. const pUrls = urls
  346. for (let index = 1; index < pUrls.length; index += 2) {
  347. pUrls[index] = js2Proxy(false, this.siteType, this.siteKey, 'hls/' + encodeURIComponent(pUrls[index]), {});
  348. }
  349. pUrls.push('original');
  350. pUrls.push(playUrl);
  351. return pUrls
  352. }
  353. async setPlay(flag, id, flags) {
  354. let $ = await this.getHtml(this.siteUrl + id)
  355. let playElements = $("[class=\"player-left\"]")
  356. let scriptElements = $(playElements).find("script")
  357. await this.jadeLog.debug($(scriptElements[0]).html())
  358. let playConfig = JSON.parse($(scriptElements[0]).html().replaceAll("var player_aaaa=", ""))
  359. let playListConfig = await this.getPlayConfig(scriptElements[1])
  360. let jiexiUrl = playListConfig[playConfig["from"]]["parse"] + playConfig["url"]
  361. let jiexi$ = await this.getHtml(jiexiUrl, {"User-Agent": Utils.CHROME})
  362. let ConFig = JSON.parse(Utils.getStrByRegex(/let ConFig = (.*?),box = /, jiexi$.html()))
  363. let playUrl = this.uic(ConFig["url"], ConFig.config.uid)
  364. await this.jadeLog.debug(`播放链接为:${playUrl}`)
  365. if (flag.indexOf("极速") > -1) {
  366. this.playUrl = playUrl
  367. } else {
  368. if (this.catOpenStatus) {
  369. this.playUrl = await this.setVideoProxy(playUrl)
  370. } else {
  371. this.playUrl = playUrl
  372. }
  373. }
  374. }
  375. async setSearch(wd, quick) {
  376. let $ = await this.getHtml(this.siteUrl + `/vodsearch.html?wd=${decodeURI(wd)}`)
  377. this.vodList = await this.parseVodShortListFromDocBySearch($)
  378. }
  379. }
  380. let spider = new PiPiXiaSpider()
  381. async function init(cfg) {
  382. await spider.init(cfg)
  383. }
  384. async function home(filter) {
  385. return await spider.home(filter)
  386. }
  387. async function homeVod() {
  388. return await spider.homeVod()
  389. }
  390. async function category(tid, pg, filter, extend) {
  391. return await spider.category(tid, pg, filter, extend)
  392. }
  393. async function detail(id) {
  394. return await spider.detail(id)
  395. }
  396. async function play(flag, id, flags) {
  397. return await spider.play(flag, id, flags)
  398. }
  399. async function search(wd, quick) {
  400. return await spider.search(wd, quick)
  401. }
  402. async function proxy(segments, headers) {
  403. return await spider.proxy(segments, headers)
  404. }
  405. export function __jsEvalReturn() {
  406. return {
  407. init: init,
  408. home: home,
  409. homeVod: homeVod,
  410. category: category,
  411. detail: detail,
  412. play: play,
  413. proxy: proxy,
  414. search: search,
  415. };
  416. }
  417. export {spider}